Containers
My Production Dockerfile Rules: How I Build Docker Images
Most Dockerfiles I see in production are security nightmares waiting to happen. Running as root. Using :latest tags. Copying entire directories including secrets. And the images? Bloated with debugging tools that attackers love.
Here’s the thing. Writing a good Dockerfile isn’t hard. It’s just that nobody taught you the rules. Today, I’m going to show you every best practice you need to build production-ready containers. We’ll cover image selection, build optimization, security hardening, and maintainability. And at the end, I’ll show you how AI can apply all these rules automatically.
Let’s start with the foundation: choosing the right base image.
Say Goodbye to Tedious Docker Commands: Embrace Docker to Bake Images
Building and pushing container image with Docker is easy. Right? We define a Dockerfile and we execute a command like docker image build .... Docker file is easy to define and the rest is just a CLI command. How hard can it be?
Well… It can be hard or, at least, tedious.
Imagine that we have to build images for multiple platforms, that each of those images should be released both as a specific version but also as latest. Then add to that the situation that we need to build more than one image, let’s say a backend and a frontend.
How many commands do we need to execute and how many arguments should each of those commands have? Can we remember all those arguments and are we willing to execute a bunch of commands?
That simple example already shows that building and pushing container images can be hard and tedious. The good news is that there is a better way. There is a declarative way to do all that.
Stop Losing Requests! Learn Graceful Shutdown Techniques
Look at this.
I will send a request to the application,…
curl "http://silly-demo.127.0.0.1.nip.io/fibonacci?number=50"…and simulate failure or upgrade or any similar action by deleting the Pod where the application is running.
kubectl --namespace a-team delete pod \
--selector app.kubernetes.io/name=silly-demoThe output of the curl command is as follows.
<html>
<head><title>502 Bad Gateway</title></head>
<body>
<center><h1>502 Bad Gateway</h1></center>
<hr><center>nginx</center>
</body>
</html>Since we initiated the delete process before the server returned a response we got 502 Bad Gateway message. The application was deleted before it could respond and I, the user of that application, failed to get what I was looking for. That’s horrible experience that could have been improved by enabling the application to shut down gracefully.