-
Notes
-
Dockerfile
Dockerfile contains builds commands that are needed to create a Docker image.
For each build command in the Dockerfile, Docker will generate a new filesystem layer.
An image is a combination of all filesystem layers created by the build commands of the Dockerfile.
Each layer is mapped to a specific build command in the Dockerfile.
For a new created image, Docker will execute all the build commands in the Dockerfile.
When building an already built image, Docker will always execute the build commands if a parent build command was changed or it generated a new filesystem layer.
Otherwise Docker will use the filesystem layer from its cache.
Best practices: A build command that might create a new filesystem layer every time it's executed (e.g., update OS, library) should be placed at the bottom of the Dockerfile
or placed in a parent Dockerfile and use the generated image as a parent image for the descendant Dockerfiles.
The parent image image can be re-built only when needed.
Best practices: If possible, multiple build commands should be combined in one single build command.
-
Example of a 'non-optimized' Dockerfile
Example of a Dockerfile:
Build Dockerfile:
Let's inspect the layers of the ubuntu image (ubuntu:20.04):
Let's inspect the layers of the new image (ubuntu-nginx:20.04):
Note that the image 'ubuntu-nginx:20.04' inherit all the layers of the parent image 'ubuntu-nginx:20.04'.
The five new layers are the ones created by executing the build steps in the Dockerfile.
-
Example of an 'optimized' Dockerfile
Let's optimize a bit the Dockerfile we used above:
Build Dockerfile:
Let's inspect the layers of the new image:
First note that the build steps were reduced to only three steps.
This result to only two new layers created for the new images instead of five with the 'non-optimized' Dockerfile.
Note, in the Dockerfile, that the steps to create the mtitek group and user are placed before the installation instructions of curl and nginx.
This is to show that the instructions that are more likely to generate the same exact result, no matter how many time they are executed,
should be placed at the top of the Docker file.
This will save time when building the image frequently.
Note also the instruction rm -rf /var/lib/apt/lists/*, which is helpful to save some space disk on the final image.
-
Dockerfile instructions: USER
The USER instruction set the user that will be used to run the processes inside the container.
By default, if the USER instruction is not set, docker run all processes as root.
Let's check the current user running on the Docker host:
Let's first try a Dockerfile without the USER instruction:
Let's build the Dockerfile:
Let's check the user within the container:
Let's try now a Dockerfile with the USER instruction:
Let's build the Dockerfile:
Let's check the user within the container:
Note that the Dockerfile create the group "tek" with the group id (gid) "1000".
It also create the user "mti" with the user id (uid) "1000" and the group id (gid) "1000".
The image that we create from this Dockerfile will run with the user "mti".
Note that group and user names are, more or less, friendly names than anything else.
The important part is the uid and gid.
These two elements will map the container's user and group to the host's user and group.
So, in the above example, the container will be running using the same uid and gid that match the ones of the Docker host.
Which is the user and group "mtitek".
This means that the container's user will get the same privileges that the user "mtitek" has.
-
Dockerfile instructions: VOLUME
Let's create a Dockerfile that will use the VOLUME instruction to mount a local directory.
I will adapt a bit the nginx Dockerfie to print the logs in a directory.
Here's the Dockerfile (this is for demo purposes only):
Let's build the Dockerfile:
Let's create a local directroy:
Let's run the nginx image (the host's directory ~/nginx-loc-dir is mounted to the container's directory /var/log/nginx):
Check the nginx process:
Let's access nginx at the published port 8080:
Check the nginx logs:
-
Dockerfile instructions: WORKDIR
The WORKDIR instruction set the working directory for the remaining build instructions.
This working directory will also be the default directory for all processes running inside the container.
Let's try a Dockerfile with the WORKDIR instruction set a '/tmp':
Let's build the Dockerfile:
Let's check the working directory within the container: