Building clean Go application in Docker - docker

I'm trying to create Go web server into small Docker images. Ideally the clean image contains only the Go application itself (and maybe supporting web components, but not the Go-building environment).
Here is my Dockerfile:
# golang:latest as build-env
FROM golang:latest AS build-env
RUN mkdir /app
ADD . /app/
WORKDIR /app
RUN cd /app && GO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o myapp .
# go build -o myapp
FROM scratch
COPY --from=build-env /app/myapp /app/images /
EXPOSE 8080
ENTRYPOINT /myapp
It uses the Docker Builder Pattern and scratch image, which is a special docker image that's empty.
It builds OK, but when I run it, I'm getting:
docker: Error response from daemon: OCI runtime create failed: container_linux.go:344: starting container process caused "exec: \"/bin/sh\": stat /bin/sh: no such file or directory": unknown.
UPDATE:
So the ENTRYPOINT need to be changed to the exec form:
ENTRYPOINT ["/myapp"]
Having done that, I'm getting a new error:
standard_init_linux.go:207: exec user process caused "no such file or directory"
Having use a small footprint Linux image as the base (i.e. Alpine Linux) instead of scratch wouldn't help either:
$ docker run -it -p 8080:8080 go-web-docker-small
standard_init_linux.go:207: exec user process caused "no such file or directory"
$ docker run -it -p 8080:8080 go-web-docker-small /bin/sh -i
standard_init_linux.go:207: exec user process caused "no such file or directory"
How to fix it? Thx!

The last line of your Dockerfile is
ENTRYPOINT /myapp
There are two forms of the ENTRYPOINT (and CMD and RUN) instructions. An "exec form" looks like a JSON list, and provides an uninterpreted list of arguments to run as the main container process. A "shell form" does not look like a JSON list, and is implicitly wrapped in /bin/sh -c '...'.
Your ENTRYPOINT uses the shell form, and a FROM scratch image doesn't have a shell, producing the error you get. You can change this to the exec form
ENTRYPOINT ["/myapp"]

While building Dockerfile provided by you, I am getting following error:
COPY failed: stat /var/lib/docker/overlay2/cc1f8144192760ce7bf9cda7a7dfd0af16065901594c38609c813ea103cfd8d7/merged/app/images: no such file or directory
Fixed copy command and few others and image is building with following in Dockerfile
# golang:latest as build-env
FROM golang:latest AS build-env
RUN mkdir /app
ADD . /app/
WORKDIR /app
RUN cd /app && GO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o myapp .
# go build -o myapp
FROM scratch
COPY --from=build-env /app/myapp .
EXPOSE 8080
ENTRYPOINT ["./myapp"]

Related

Go multistage docker build fails with standard_init_linux.go:228: exec user process caused: no such file or directory

I've followed several articles and examples including the one from the official Docker example for multi-stage builds.
Here is my Dockerfile:
# build stage
FROM golang:1.16-buster AS builder
WORKDIR /src
COPY go.mod ./
COPY go.sum ./
RUN go mod download
COPY *.go ./
COPY dev.env ./
RUN go build
# exec stage
FROM alpine:3.15
WORKDIR /app
COPY --from=builder /src/tendies-cli /app/
ENTRYPOINT [ "./tendies-cli" ]
CMD [ "reset", "refill" ]
Every time I docker run it returns
standard_init_linux.go:228: exec user process caused: no such file or directory
But even when I run it in interactive shell mode using docker run -it cli /bin/sh I can see that the executable is there. I'm a docker newbie so any advice would be great.
I'm running on MacOS Big Sur and Docker Engine 20.10.11 CE
Try build with this command
GOOS=linux GOARCH=amd64 go build -ldflags="-w -s"
I faced this problem too when trying to build a minimalist docker image and run it on docker scratch
source: https://chemidy.medium.com/create-the-smallest-and-secured-golang-docker-image-based-on-scratch-4752223b7324

Invalid publish opts format when running sidecar

I want to run docker container with sidecar by this tutorial.
For example, i have java spring boot application. Then i made such Dockerfile:
# Dockerfile for GitLab CI/CD
FROM maven:3.5.2-jdk-8-alpine AS MAVEN_BUILD
ARG SPRING_ACTIVE_PROFILE
MAINTAINER SlandShow
COPY pom.xml /build/
COPY src /build/src/
WORKDIR /build/
RUN mvn clean install -Dspring.profiles.active=$SPRING_ACTIVE_PROFILE && mvn package -B -e -Dspring.profiles.active=$SPRING_ACTIVE_PROFILE
FROM openjdk:8-alpine
WORKDIR /app
COPY --from=MAVEN_BUILD /build/target/task-0.0.1-SNAPSHOT.jar /app/task-0.0.1-SNAPSHOT.jar
ENTRYPOINT ["java", "-jar", "task-0.0.1-SNAPSHOT.jar"]
After that i build docker image and run it:
$ docker build .
$ docker container run -p 8010:8010 <imageId>
Docker-CLI returns hash for started contaner. For example- cc82fa748a62de634893f5594a334ada2854f0be0dff8149efb28ae67c98191c.
Then i'am trying to start sidecar:
docker run -pid=container:cc82fa748a62de634893f5594a334ada2854f0be0dff8149efb28ae67c98191c -p 8080:8080 brendanburns/topz:db0fa58 /server --addr=0.0.0.0:8080
And get:
docker: invalid publish opts format (should be name=value but got '8080:8080').
What's wrong with it?
My fault, i forgot - before -p...

starting container process caused "exec: \"go\": executable file not found in $PATH": unknown

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.

How to run a docker container created with go binary?

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

Error running dotnet core 2.1 app on Alpine image

Running Docker on a Win10 machine. Linux containers enabled. My app runs fine on Windows and Debian images but when I switched to Alpine I get this error
PS C:\Code\TestApp> docker run -it testapp:latest
C:\Program Files\Docker\Docker\Resources\bin\docker.exe: Error response from daemon: OCI runtime create failed: container_linux.go:348: starting container process caused "exec: \"/app/TestApp\": stat /app/TestApp: no such file or directory": unknown.
I've tried changing the Entrypoint to match some examples but no dice.
FROM microsoft/dotnet:2.1-runtime-deps-alpine3.7 AS base
WORKDIR /app
FROM microsoft/dotnet:2.1-sdk-alpine3.7 AS build
WORKDIR /src
COPY TestApp/TestApp.csproj TestApp/
RUN dotnet restore TestApp/TestApp.csproj
COPY . .
WORKDIR /src/TestApp
RUN dotnet build TestApp.csproj -c Release -o /app
FROM build AS publish
RUN dotnet publish TestApp.csproj -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
# This is for Windows and Debian images
# ENTRYPOINT ["dotnet", "TestApp.dll"]
ENTRYPOINT ["/app/TestApp"]
Add some debug information in your different stages of this multi-stage build:
RUN ls -alrth /app
(after each COPY or RUN dotnet commands)
And make sure to build it with a name and tag different from your first builds for Windows, in order to be sure to not try a Windows-built image in your Linux environment.
docker build -t testApp-linux ...

Resources