Build a docker image with daemonist’s knowledges
Docker is a solution any developpers has heard of or considered during their carrier. Yet, there is a fundamental notion that I’m not seeing discussed for initiate to Docker : the daemon context.
It’s time to fix that and finally give a proper word to everyone on this topic.
The daemon context is by default the Dockerfile location
For an application hosted within a container, a trivial structure would look like this :
└───app1
Dockerfile
file1.txt
You build the image with a trivial docker build command :
docker build -t <image name> .
Nothing fancy, that’s what most of people know.
Moving forward, you have now 2 applications and they share same codebase. After a reflexion on the ideal refactorisation, you end up with this structure :
├───app1
│ Dockerfile
│ file.txt
│
├───app2
│ Dockerfile
│ file.txt
│
└───shared_codebase
file.txt
Here’s the problem : your docker images aren’t building because it cannot find the files within shared_codebase.
What went wrong ?
In the naive way, the main parameter — in my example the “dot” representing the actual folder from which I’m calling docker build — is the path. People tend to confuse this parameter as a path toward a valid Dockerfile in order to build the image.
What induces people in error is this error message :
It’s partially correct. The problem has nothing to do with Dockerfiles’ location. The path given with “dot” is not actually a path toward a Dockerfile, but a path toward a daemon context. And in a simple structure, a Dockerfile happens to be at the same level as a declared daemon context.
To understand it better, let’s use an analogy.
You’re a daemonist. As such, you want to summon a docker daemon so that it can work for you. To do so, a docker daemon needs two things : a set of instructions to follow (a Dockerfile) and a location providing everything necessary to complete those instructions (a context).
As a daemonist, you need a “magic formula” (a docker bash command).
The docker daemon is quite straightforward and unhappy to follow a mortal like you. So any wrong move will make it disappear without any work done. Knowing this, a summoning follow those steps :
- the docker daemon is sommuned thanks to your magic formula ;
- it looks for instructions written on a Dockerfile. You might have chosen a custom name for your Dockerfile. If so, make sure to specify it in your formula ;
- once instructions are found, the docker daemon begins its work and executes the instructions one by one. The docker daemon is lazy and won’t bother get out of its given location to find files or folders needed during COPY or ADD command. Make sure those are already present it its direct area (the daemon context).
Embrace the docker daemonist within you
With the difference between Dockerfile location and daemon context taken into consideration, it’s now possible to change the “magic formula” a bit in order to fits the need of the new structure.
docker build -t <image name> <path to context> -f <path to Dockerfile>
Let’s try to build the docker image of app1 following the given structure :
├───app1
│ Dockerfile
│ file.txt
│
├───app2
│ Dockerfile
│ file.txt
│
└───shared_codebase
file.txt
This Dockerfile :
FROM ubuntu:22.04
WORKDIR app
COPY shared_codebase shared_codebase/
COPY app1 app1/
CMD /bin/bash
And this command :
docker build -t my-image . -f ./app1/Dockerfile
To make sure the structure is correct within the container, you can use this command :
docker run -it my-image
Conclusion
A lot of people still confuse Dockerfile location and context path. I hope this article was helpful to discern the difference between both and will simplify the way you’re building docker images.