i have Makefiles on my app , and all my commands on Makefile
i put this on Dockerfile:
# start from the latest golang base image
FROM golang:alpine
RUN apk update && apk add --no-cache gcc && apk add --no-cache libc-dev
# Set the current working Directory inside the container
WORKDIR /app
# Copy go mod and sum files
COPY go.mod go.sum ./
# Download all dependencies. they will be cached of the go.mod and go.sum files are not changed
RUN go mod download
# Copy the source from the current directory to the WORKDIR inisde the container
COPY . .
# Build the Go app
RUN go build .
# Exporse port 3000 or 8000 to the outisde world
EXPOSE 3000
# Command to run the executable
CMD ["make", "-C", "scripts", "test" ]
CMD ["make", "-C", "scripts", "prod" ]
and got
docker: Error response from daemon: OCI runtime create failed:
container_linux.go:349: starting container process caused "exec:
\"make\": executable file not found in $PATH": unknown.
is it possible to run make -c scripts test in Docker? how to correct way to use this command in Docker?
in dockerfile i run golang:alpine
if you wish to avoid adding all dependencies of make to your alpine image and keep the shipping container small in size:
build your binary outside ur container and copy only the shippable binary to ur alpine container
build your binary in a normal golang container then copy the binary to a small shippable alpine container
you could give https://github.com/go-task/task a try, does not require too many dependencies compared to installing make in ur alpine container and replace ur make file with task file.
Related
I'm kinda stuck exploring Docker features in order to create simple container with some Go utilities installed. I need to create image that has gosec and govulncheck utilities installed so I can run them on code in container. My petty attempt produced the following:
# syntax=docker/dockerfile:1
FROM golang:1.19-alpine
WORKDIR /app
ENV GO111MODULE=on
# copying my code to check
COPY go.mod ./
COPY go.sum ./
RUN go mod download
COPY *.go ./
RUN go build -o /docker-gs-ping
RUN apk add --no-cache git
RUN go install github.com/securego/gosec/v2/cmd/gosec#latest
RUN go install golang.org/x/vuln/cmd/govulncheck#latest
EXPOSE 8080
CMD [ "gosec ./..." ]
Running the container results in error:
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "gosec ./...": stat gosec ./...: no such file or directory: unknown.
ERRO[0000] error waiting for container: context canceled
It looks like I need to specify paths to installed utilities, but I couldn't make it work
This isn't a path issue; the problem is the syntax you've used in the CMD statement in your Dockerfile. You're using the JSON-format of the CMD statement; the first argument in the JSON list is the name of the command to run. You've asked Docker to run a command named gosec ./..., which of course doesn't exist.
You need to split that into multiple list items:
CMD [ "gosec", "./..." ]
Alternatively, you can use the shell form of the CMD directive:
CMD gosec ./...
Either of those will run gosec when you start the container.
My projects need to access private go modules and to access to modules it needs a GOPROXY.
So I've create an image from base image golang alpine
PROXY IMAGE:
FROM golang:1.16.4-alpine3.13 AS builder
ARG GITLAB_LOGIN
ARG GITLAB_TOKEN
modules.
WORKDIR /app
ENV GO111MODULE="auto"
ENV GONOSUMDB=*.someting.text
ENV GOPROXY=https://proxy.golang.org,direct
ENV GOPRIVATE="gitlab.something.text"
#ARG GOPROXY=http://localhost:41732,https://proxy.golang.org,direct
RUN apk add --no-cache git
RUN echo "machine gitlab.something.text login ${GITLAB_LOGIN} password ${GITLAB_TOKEN}" > ~/.netrc
COPY ["go.mod", "go.sum", "./"]
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build \
-installsuffix 'static' \
-o /app/proxy .
FROM scratch AS final
COPY --from=builder /app /app
CMD [ "/app/proxy"]
And the alpine image has a shell so I can execute commands with RUN.
But then I want to use my proxy image as a base image.
IMAGE THAT USES THE PROXY IMAGE:
FROM proxy:latest
COPY go.mod go.sum ./
RUN go mod download && go mod verify
COPY . .
RUN go build -o bin/app .
CMD [ "/app" ]
And then the image that is using the proxy image cannot access the shell.
So my question is, is there a way to forward/pass the shell from the base alpine image through the proxy image so the images that use the proxy image can access the shell that is provided by the alpine image.
Cause the error I get in the image that is using the proxy image as the base is
CI runtime create failed: container_linux.go:380: starting container process caused: exec: "/bin/sh": stat /bin/sh: no such file or directory: unknown
but of course this error does not happen in the proxy image cause it's base image is alpine.
The final stage of the proxy image is built FROM scratch. As you note this contains absolutely nothing, not even a shell, so if you want to use it as a base image, you need to change this to something else:
FROM golang:1.16.4-alpine3.13 AS builder
...
FROM alpine:3.13 # AS final
COPY --from=builder /app/proxy /usr/local/bin/proxy
CMD ["proxy"]
However, your Go build sequence produces a static binary; if it can run successfully as the only thing in a FROM scratch image then it can run successfully in any Linux environment. You can COPY --from an image as well as a build stage. It might be easier to not use the proxy as a base image, but instead copy it into other images where you need it:
FROM golang # not the proxy
# Get the proxy binary from the other image
COPY --from=proxy /app/proxy /usr/local/bin
# Build the Go application as above
COPY go.mod go.sum ./
...
I am trying to containerize and as well as start my Go lang application using Docker-compose,
The image is built successfully according to the logs but my container does not for docker-compose up and it throws the following error to my console.
Cannot start service app: OCI runtime create failed: container_linux.go:346: starting container process caused "exec: \"go\": executable file not found in $PATH": unknown
Here is what my Docker file looks like.
ARG GO_VERSION=1.13
FROM golang:${GO_VERSION}-alpine AS builder
# We create an /app directory within our
# image that will hold our application source
# files
RUN mkdir /raedar
# Create the user and group files that will be used in the running container to
# run the process as an unprivileged user.
RUN mkdir /user && \
echo 'nobody:x:65534:65534:nobody:/:' > /user/passwd && \
echo 'nobody:x:65534:' > /user/group
# Install git.
# Git is required for fetching the dependencies.
# Allow Go to retrieve the dependencies for the buld
RUN apk update && apk add --no-cache ca-certificates git
RUN apk add --no-cache libc6-compat
# Force the go compiler to use modules
ENV GO111MODULE=on
ADD . /raedar/
WORKDIR /raedar/
RUN go get -d -v golang.org/x/net/html
COPY go.mod go.sum ./
COPY . .
# Compile the binary, we don't want to run the cgo
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o bin/main cmd/app/main.go
# Final stage: the running container.
FROM scratch AS final
WORKDIR /root/
# Import the user and group files from the first stage.
COPY --from=builder /user/group /user/passwd /etc/
# Import the Certificate-Authority certificates for enabling HTTPS.
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
# Import the compiled executable from the first stage.
COPY --from=builder /raedar/bin/main .
EXPOSE 8080
# Perform any further action as an unprivileged user.
USER nobody:nobody
# Run the compiled binary.
CMD ["./main"]
The error shows you're trying to run go, not ./main:
exec: \"go\": executable file not found in $PATH
A matching Dockerfile would have the line CMD ["go", "./main"] rather than CMD ["./main"].
So either you're unexpectedly building a different Dockerfile, or you're changing the command when you run a container with that image. In particular, if you're using docker-compose, make sure you're not setting command: go ./main or entrypoint: go, either of which could cause this behavior.
I am trying to create a docker container with a Dockerfile and a go file binary.
I have two files in my folder: Dockerfile and main, where the latter is a binary of my simple go file.
Contents of Dockerfile:
FROM golang:1.11-alpine
WORKDIR /app
COPY main /app/
RUN ["chmod", "+x", "/app/main"]
ENTRYPOINT ["./main"]
I tried following steps:
sudo docker build -t naive5cr .
sudo docker run -d -p 8080:8080 naive5cr
The error which i see in thru "docker logs " :
standard_init_linux.go:207: exec user process caused "no such file or directory"
my go file content [i think it is irrelevant to the problem]:
func main() {
http.HandleFunc("/", index)
http.ListenAndServe(port(), nil)
}
func port() string {
port := os.Getenv("PORT")
if len(port) == 0 {
port = "8080"
}
return ":" + port
}
the binary "main" runs as expected when run standalone. so there is no problem with the content of go file.
You need to compile with CGO_ENABLED=0 to prevent links to libc on Linux when networking is used in Go. Alpine ships with musl rather than libc, and attempts to find libc result in the no such file or directory error. You can verify this by running ldd main to see the dynamic links.
You can also build on an Alpine based host to link to musl instead of libc. The advantage of a completely statically compiled binary is the ability to run on scratch, without any libraries at all.
go compiles down to native code, so make sure to build your go code on the Docker image, instead of copying the binary to the docker image.
e.g.
FROM golang:1.11-alpine
WORKDIR /app
ADD . /app
RUN cd /app && go build -o goapp
ENTRYPOINT ./goapp
Also as a bonus, here is how to create really tiny Docker images with multistage Docker builds:
FROM golang:1.11-alpine AS build-env
ADD . /src
RUN cd /src && go build -o goapp
FROM alpine
WORKDIR /app
COPY --from=build-env /src/goapp /app/
ENTRYPOINT ./goapp
I'm building a multi-stage Dockerfile for my go project.
FROM golang:latest as builder
COPY ./go.mod /app/go.mod
COPY ./go.sum /app/go.sum
#exporting go1.11 module support variable
ENV GO111MODULE=on
WORKDIR /app/
#create vendor directory
RUN go mod download
COPY . /app/
RUN go mod vendor
#building source code
RUN go build -mod=vendor -o main -v ./src/
FROM alpine:latest
RUN apk --no-cache add ca-certificates
COPY --from=builder /app/main /app/main
WORKDIR /app/
ARG port="80"
ENV PORT=$port
EXPOSE $PORT
CMD ["./main"]
When I'm running the image, it throws error:
standard_init_linux.go:207: exec user process caused "no such file or directory"
I've verified that the 'main' file exist in /app/main.
I also tried to give executable permission by adding
chmod +x /app/main
but still it doesn't work.
What can possibly be wrong?
The "latest" version of the golang image is debian based, which uses libc. Alpine uses musl. If you do not compile with CGO_ENABLED=0, networking libraries will link to libc and the no such file or directory error point to a missing library. You can check these shared library links with ldd /app/main. A few solutions I can think of:
compile your program with CGO_ENABLED=0
switch your build image to FROM golang:alpine
change your second stage to be FROM debian