Building Smaller, Rootless, Non-Shell Docker Images and Other Things
Hello Friend,
I’m making a small change to the newsletter. I will stop throwing technical stuff at you from the start. I want to write about work-life occasionally. Why? I’m not living and working in the US. But most articles on the net about work-life and processes come from the US or Europe. Working for clients as a freelancer or in a near-shore or off-shore company and for the company that owns a product is quite different. Processes are different. Everything is different. I worked for various companies with vastly different models during my work life. Those work models affected me professionally and privately. My goal is to share my experience with you. So, I need your help. Please share your experience with me.
Thank you.
Building Docker Images Smaller, Rootless, and Non-Shell for Kubernetes
After building a Docker image faster, I wanted to build it for the K8s cluster. Running the container on the local machine isn’t the same as running it on a cluster. I’m packaging a Go application in my example. But the same principles apply to any other language.
Starting Dockerfile
I’m starting with the following Dockerfile(Dockerfile_1):
ARG GO_VERSION=1.20.3
FROM golang:${GO_VERSION}-buster as builder
WORKDIR /app
COPY go.mod go.sum /app/
RUN go mod download -x
COPY . /app/
RUN go build -o app
FROM debian:buster
WORKDIR /app
COPY --from=builder /app/app /app/
ENTRYPOINT [ "/app/app" ]
And I build it with the following command:
docker buildx build -t rnemet/echo:0.0.1 . -f Dockerfile_1 --cache-to type=registry,ref=rnemet/echo:test --cache-from type=registry,ref=rnemet/echo:test --cache-from type=registry,ref=rnemet/echo:main --load
I’m using the --cache-to
and --cache-from
flags to cache the build process and the --load
to load the image into the local Docker daemon. Also, I’m using BuildKit to build an image.
Let’s see what I got:
❯ docker images rnemet/echo
REPOSITORY TAG IMAGE ID CREATED SIZE
rnemet/echo 0.0.1 6fc43a3d85eb 4 minutes ago 133MB
If I run the container as a Pod in a K8s cluster or a Docker container on my local machine:
❯ docker exec -it echo bash
root@30fa7aa78401:/app# whoami
root
I managed:
to open a shell in the container
found out that I’m running as a root
I run the
whoami
command, which is not a command I need when I run the container
The whoami
is not the problem, but the fact that it is present. I don’t need it, and it’s not part of my application. There must be others as well. I need to clean up the image.
Then I learned that my app is run as root. This isn’t good. My app needs to run as a non-root user. Why? There are many reasons. For example, the app can access the whole system with root privileges. Do you remember? The container runtime isolates the process from the host system using namespaces. But the process can still access the host system.
As the cherry on top, I can open a shell in the container and run commands as root. I do not even want to discuss why this is not good.
If this interests you and wants to see how I managed to make the image smaller, rootless, and without a shell, read the rest here on my blog.