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
Related
I have a Rust program that needs to do some DNS lookups. It works just fine with the following Dockerfile:
FROM rust:1.63.0-bullseye AS build
WORKDIR /app
COPY . .
RUN cargo build --release
EXPOSE 8080
ENTRYPOINT ["/app/target/release/router"]
I've tried to create a somewhat minimalistic image for the program like so:
FROM rust:1.63.0-bullseye AS build
WORKDIR /app
COPY . .
RUN cargo build --release
RUN mkdir -p /app/lib
RUN cp -LR $(ldd ./target/release/router | grep "=>" | cut -d ' ' -f 3) /app/lib
FROM scratch AS websocket-router-rust
WORKDIR /app
COPY --from=build /app/lib /app/lib
COPY --from=build /lib64/ld-linux-x86-64.so.2 /lib64/ld-linux-x86-64.so.2
COPY --from=build /app/target/release/router /app/router
ENV LD_LIBRARY_PATH=/app/lib
EXPOSE 8080
ENTRYPOINT ["/app/router"]
However, DNS lookups seem to fail when using the latter Dockerfile. Any ideas what files could be missing that should be copied from the build stage?
UPDATE: Got it working by running a file access tracer inside the Docker image while making a request to the server and then copying over all the files that were read with COPY --from... The Dockerfile got a bit messy, but it's less than 30MB now. The main problem was that ldd doesn't return libnss SOs, so those were missing from the image.
You can set the DNS addresses in /etc/docker/daemon.json file:
{
"dns": ["10.0.0.2", "8.8.8.8"]
}
I do
git clone https://github.com/openzipkin/zipkin.git
cd zipkin
The create a Dockerfile as below
FROM openjdk
RUN mkdir app
WORKDIR /app
COPY ./ .
ENTRYPOINT ["sleep", "1000000"]
then
docker build -t abc .
docker run abc
I then run docker exec -it CONTAINER_ID bash
pwd returns /app which is expected
but I ls and see that the files are not copied
only the directories and the xml file is copied into the /app directory
What is the reason? how to fix it?
Also I tried
FROM openjdk
RUN mkdir app
WORKDIR /app
COPY . /app
ENTRYPOINT ["sleep", "1000000"]
That repository contains a .dockerignore file which excludes everything except a set of things it selects.
That repository's docker directory also contains several build scripts for official images and you may find it easier to start your custom image FROM openzipkin/zipkin rather than trying to reinvent it.
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 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.
I'm able to run a docker image of a web app when using golang:1.13 base, but not when using scratch. The working Dockerfile is:
FROM golang:1.13 AS builder
WORKDIR /app
COPY . .
RUN go build -o server
FROM golang:1.13
COPY --from=builder /app/server /app/server
COPY --from=builder /app/credentials/service-account.json /app/credentials/service-account.json
ENTRYPOINT ["/app/server"]
But when I change the final image base to scratch (line 6) like this:
FROM golang:1.13 AS builder
WORKDIR /app
COPY . .
RUN go build -o server
FROM scratch # <-- CHANGED
COPY --from=builder /app/server /app/server
COPY --from=builder /app/credentials/service-account.json /app/credentials/service-account.json
ENTRYPOINT ["/app/server"]
I get a standard_init_linux.go:211: exec user process caused "no such file or directory" error.
To build the docker image, I use docker build -t myimage ., and to run the image, I use docker run --rm -p 8080:8080 myimage:latest.
The app is a Go based web API that uses Gin framework, and GCP Service Account to access GCP services (the JSON file that I copy on build.)
Provided you are not using CGO (as #jakub mentioned), try disabling CGO in your build.
So change this line in your Dockerfile:
#RUN go build -o server
RUN CGO_ENABLED=0 go build -o server