Build context in Dockerfile; Best practices

Best practices while building the Dockerfile.

The context in Dockerfile is relative to the current working directory of the Dockerfile and that the location where Dockerfile is present becomes its context.

Which means we can create a Directory with some content and place our Dockerfile inside it and then traverse a number of directories away from the directory and can still execute the build command

Here is an example of out general approach to building an image from a Dockerfile with . context:

# docker build --tag nginx-linuxcent .

And we list the image as follows:

[vamshi@docker01 ~]$ docker images
REPOSITORY                                   TAG                 IMAGE ID            CREATED             SIZE
nginx-linuxcent                              latest              0b0a4ea4d48a        3 minutes ago      210.1 MB

The build context is a . dot and the Dockerfile is present in the same directory.
If You are working locally you don’t really need a repository name and specifying just the image name is sufficient and then adding a tag is considered optional, in such cases a latest tag is appended to the end of the newly build image

As a standard practice that the Dockerfile doesn’t traverse back from the current working directory. Lets see an demonstration of of building a Dockerfile by giving the relative path from its Dockerfile.

Example given:

[vamshi@node01 ~]$ ls nginx/
default.conf Dockerfile-nginx index.html nginx.conf Portal.tar.gz

Here is our nginx/Dockerfile-nginx.

cat Dockerfile-nginx
FROM nginx:1.17.2-alpine
COPY index.html /usr/share/nginx/html/
ADD Portal.tar.gz /tmp/new1/portal
CMD ["/usr/sbin/nginx"]

Our command to build this Dockerfile-nginx now becomes:

[vamshi@docker01 ~]$ docker build -t nginx-linuxcent -f nginx/Dockerfile-nginx nginx/
Sending build context to Docker daemon 155.4 MB
Step 1/4 : FROM nginx:1.17.2-alpine
---> 55ceb2abad47
Step 2/4 : COPY index.html /usr/share/nginx/html/
---> cc652d0fc2b7
Removing intermediate container 11f195a0e2ac
Step 3/4 : ADD Portal.tar.gz /tmp/new1/portal1/
---> b18a86545c47
Removing intermediate container 1e1849be08b4
Step 4/4 : CMD /usr/sbin/nginx
---> Running in fdac087b636b
---> 02e2795eab12
Removing intermediate container fdac087b636b
Successfully built 02e2795eab12

Or you can also mention the absolute path as shown below.

[vamshi@docker01 ~]$  # docker build -t nginx-linuxcent -f /home/vamshi/nginx/Dockerfile-nginx /home/vamshi/nginx/

The above example successfully builds a docker image. The Directory nginx/ is its build context as nginx/Dockerfile-nginx is the relative path of the input Dockerfile-nginx to docker build command.

Dockerfile and the context being different

Placing the Dockerfile-nginx inside the nginx directory and context placed one directory above the Dockerfile-nginx.

We now need to modify and carefully place the ADD/COPY commands relative to its directory in order for it to work properly, The context being one directory ahead, they should be prefixed with the directory name as we see below:

FROM nginx:1.17.2-alpine
COPY nginx/index.html /usr/share/nginx/html/
ADD nginx/Portal.tar.gz /tmp/new1/portal1/
CMD ["/usr/sbin/nginx"]

Now our docker build command takes the following syntax:

[vamshi@docker01 ~]$ docker build -t nginx-linuxcent -f nginx/Dockerfile-nginx .
Sending build context to Docker daemon 155.4 MB
Step 1/4 : FROM nginx:1.17.2-alpine
 ---> 55ceb2abad47
Step 2/4 : COPY nginx/index.html /usr/share/nginx/html/
 ---> Using cache
 ---> cc652d0fc2b7
Step 3/4 : ADD nginx/Portal.tar.gz /tmp/new1/portal1/
 ---> Using cache
 ---> b18a86545c47
Step 4/4 : CMD /usr/sbin/nginx
 ---> Using cache
 ---> 02e2795eab12
Successfully built 02e2795eab12

Here the context remains outside the directory and the Dockerfile is present inside the subdirectory, the ADD/COPY commands are prefixed with the relative path of the dubirectory

Common errors Encountered with context mismatch:

unable to prepare context: The Dockerfile must be within the build context

How to tag a Docker image with a repository name during build process?

You can name your Dockerfile anything and it doesnt matter to the build process as long as you refer it with the -f

The standard naming convention is as shown below.

# docker build -t <DOCKER_IMAGE-NAME>:<TAG> -f Dockerfile .

Syntax:

# docker build -t <REPOSITORY/REGISTRY NAME>/<DOCKER_IMAGE-NAME>:<TAG> -f Dockerfile .
# docker build --tag mydocker-registry-name/nginx-linuxcent:version1.0 -f Dockerfile .

Here the Dockerfile need not be explicitly mentioned with -f as the name of the file is Dockerfile and the context being .

# docker build --tag mydocker-registry-name/nginx-linuxcent:version1.0 - .

The Build context . at the end is important because it signifies the current context and the context cannot span backward.

The tag name is a must for best practices and helps in identifying the newly build images and tagging enables visible versioning and better identification of images.

Docker build with no-cache

Creating Docker images with the --no-cache option when you do not use cache when building the image, The default option for this is set to false and can be used explicitly to enforce no-cache..

It can be at times important when building container images which are dependent upon downloading latest libraries from the internet or practically from your on-premise code repository which contains the freshly compiled code artifacts.

Build the Docker image with no cache:

# docker build --no-cache -t mydocker-registry-name/nginx:version0.1 -f Dockerfile .

Once the docker container is successfully built, we can take a look at the newly created image as below.

# docker images
REPOSITORY                                       TAG                 IMAGE ID            CREATED             SIZE
mydocker-registry-name/nginx:                    version0.1          bcdd25553d01        3 minutes ago       298 MB

Conclusion:

The docker build context becomes the present path of the Dockerfile.The docker image build is a simple process if things are neatly organized and the context can be quiet tricky if you are managing multiple Docker builds. You have the flexibility to give the absolute of relative path to the docker build.
Its always advised to implement the relative path and use the . dot as context being in the same directory where your Dockerfile is present to run the Docker builds.

Ensure to use the no-cache option

And have a proper tagging in place to enable better version identity of your docker images.

If at all you need to build an image being in different context then always write the Dockerfile relative to the directory path of current context

Leave a Reply

Your email address will not be published. Required fields are marked *