dockerfile build cache permission issue

Issue

I’m building a container using a binary like this:

Basically the container will run an executable go program.

FROM myrepo/ubi8/go-toolset:latest AS build

COPY --chown=1001:0 . /build

 RUN cd /build && \
    go env -w GO111MODULE=auto && \
    go build

#---------------------------------------------------------------
FROM myrepo/ubi8/ubi-minimal:latest AS runtime

RUN microdnf update -y --nodocs && microdnf clean all && \
    microdnf install go -y && \
    microdnf install cronie -y && \
    groupadd -g 1000 usercontainer && adduser -u 1000 -g usercontainer usercontainer && chmod 755 /home/usercontainer && \
    microdnf clean all

ENV XDG_CACHE_HOME=/home/usercontainer/.cache

COPY executable.go /tmp/executable.go

RUN chmod 0555 /tmp/executable.go

USER usercontainer
WORKDIR /home/usercontainer

However, when running the container in Jenkins I’m getting this error:

failed to initialize build cache at /.cache/go-build: mkdir /.cache: permission denied

When running the container manually in a kubernetes deployment I’m not getting any issue but Jenkins is throwing this error and I can see the pod in CrashLoopBackOff and the container is showing the previous permissions issue.

Also, I’m not sure if I’m building the container correctly. Maybe I need to include the executable go program in the binary and later create the runtime?

Any clear example would be appreciated.

Solution

Go is a compiled language, which means that you don’t actually need the go tool to run a Go program. In a Docker context, a typical setup is to use a multi-stage build to compile an application, and then copy the built application into a final image that runs it. The final image doesn’t need the Go toolchain or the source code, just the compiled binary.

I might rewrite the final stage as:

FROM myrepo/ubi8/go-toolset:latest AS build
# ... as you have it now ...

FROM myrepo/ubi8/ubi-minimal:latest AS runtime

# Do not install `go` in this sequence
RUN microdnf update -y --nodocs && 
    microdnf install cronie -y && \
    microdnf clean all

# Create a non-root user, but not a home directory;
# specific uid/gid doesn't matter
RUN adduser --system usercontainer

# Get the built binary out of the first container
# and put it somewhere in $PATH
COPY --from=build /build/build /usr/local/bin/myapp

# Switch to a non-root user and explain how to run the container
USER usercontainer
CMD ["myapp"]

This sequence doesn’t use go run or use any go command in the final image, which hopefully gets around the issue of needing a $HOME/.cache directory. (It will also give you a smaller container and faster startup time.)

Answered By – David Maze

Answer Checked By – David Marino (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.