Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 45

Understanding Dockerfiles: Building Your Container Images

Recommended resources

Introduction

In our last lesson, we explored Docker's role as a containerization platform, focusing on its client-server architecture and the core components: the Docker Engine, Images, Containers, and Registries. We learned that an Image is a blueprint for a container. Now, we'll dive into how that blueprint is actually written.

This lesson directly addresses the learning outcome: Describe the purpose of a Dockerfile and explain its key instructions (FROM, RUN, COPY, CMD, EXPOSE). We will define what a Dockerfile is, and then meticulously break down the essential instructions you need to know to construct one. Mastering this is fundamental to automating the creation of consistent and portable application environments, a key skill for your exams.



1. What is a Dockerfile?

A Dockerfile is a plain text file that contains a series of instructions or commands. The Docker Engine reads these instructions and executes them in sequence to automatically build a Docker image. Think of it as a recipe: the Dockerfile lists the ingredients and steps, and the docker build command is the chef that follows the recipe to bake the cake (the Docker image).

Purpose of a Dockerfile:

  • Automation: It automates the process of creating a Docker image, removing manual steps and potential errors.
  • Consistency: It ensures that every image built from the same Dockerfile is identical, providing a consistent environment from development to production.
  • Documentation: The Dockerfile itself serves as clear documentation for how the application environment is set up.
  • Version Control: Since it's a text file, you can track it in version control systems like Git, allowing you to manage changes to your application's infrastructure just like you manage changes to your code.

The diagram below illustrates this build process.

Dockerfile to Docker Image Build Process
This diagram shows the process where a `Dockerfile` is read by a builder (the Docker Engine), with each instruction creating a new layer, ultimately resulting in a complete Docker Image.

To begin, let's watch a short video that introduces the concept and basic syntax of a Dockerfile.

Dockerfile creation Tutorial - Dockerfile Instructions Explained with example!

The video 'Dockerfile creation Tutorial' by Cloud Champ provides a clear introduction to what a Dockerfile is and its basic syntax.

Watch the first part of the video from 00:00 to 01:58. Focus on understanding that a Dockerfile is a text file with a specific name (Dockerfile) and follows a simple INSTRUCTION argument format.



2. Key Dockerfile Instructions

A Dockerfile is built using a specific set of instructions. For your exams, it is crucial to know the purpose of the most common ones. While there are many instructions, your syllabus requires a deep understanding of FROM, RUN, COPY, CMD, and EXPOSE.

The following table gives a quick overview of these and other common instructions. It's a useful reference for revision.

Docker Build: A Beginner's Guide to Building Docker Images - Stackify

The article 'Docker Build: A Beginner's Guide' provides an excellent summary table of Dockerfile instructions. Review this table to get a high-level sense of the available commands.

Focus on the table under the 'Docker Instructions' heading. Pay special attention to the explanations for FROM, RUN, COPY, EXPOSE, and CMD.

Now, let's examine each of the required instructions in detail.

a) FROM

The FROM instruction is mandatory and must be the first instruction in a Dockerfile. It specifies the base image upon which you are building. This base image could be an operating system (like Ubuntu), a programming language runtime (like Python or Node.js), or another application.

  • Purpose: To set the foundation for your image.
  • Syntax: FROM <image>:<tag>
  • Example:
    FROM python:3.9-slim
    
    This instruction tells Docker to use the official Python image with the tag 3.9-slim from Docker Hub as the starting point.

Dockerfile creation Tutorial - Dockerfile Instructions Explained with example!

Let's see a practical demonstration of the FROM instruction.

Watch the segment from 01:58 to 06:09. The presenter explains how FROM sets the base image and demonstrates how to find and specify image tags from Docker Hub.

b) RUN

The RUN instruction executes commands in a new layer on top of the current image and commits the results. These are build-time commands, meaning they are executed only when you are building the image.

  • Purpose: To install software packages, run scripts, create directories, or perform any setup needed for the application environment.
  • Syntax: RUN <command> (shell form) or RUN ["executable", "param1", "param2"] (exec form).
  • Example:
    RUN apt-get update && apt-get install -y curl
    
    This command updates the package list and installs the curl utility inside the image. Each RUN instruction creates a new image layer.

Dockerfile creation Tutorial - Dockerfile Instructions Explained with example!

The next segment of the video explains how the RUN instruction is used to execute commands during the image build.

Watch from 06:09 to 08:34. Notice how RUN is used to install a package (apk add curl) inside the Alpine Linux base image. This happens during the docker build process.

c) COPY

The COPY instruction copies files or directories from a source on the host machine (your local filesystem) into the filesystem of the container.

  • Purpose: To add your application code, configuration files, or other necessary assets into the image.
  • Syntax: COPY <src> <dest>
  • Example:
    
    
    
    # Set the working directory
    WORKDIR /app
    
    
    
    
    # Copy the application file into the container at /app/app.py
    COPY app.py .
    
    Here, we first set a working directory with WORKDIR (a best practice) and then copy app.py from the build context (the same directory as the Dockerfile) into the /app directory inside the image.

Dockerfile creation Tutorial - Dockerfile Instructions Explained with example!

Watch this segment to understand how COPY is used to get your application code into the image.

Watch from 17:55 to 19:11. The video demonstrates copying a local app.py file into a directory within the image.

Note on COPY vs. ADD: You might also see the ADD instruction. It is similar to COPY but has extra features, like downloading files from a URL and auto-extracting tar files. The general best practice is to prefer COPY because it is more explicit and transparent. Use ADD only if you specifically need its extra features.

d) EXPOSE

The EXPOSE instruction informs Docker that the container listens on the specified network ports at runtime. This instruction does not actually publish the port; it functions as a type of documentation between the person who builds the image and the person who runs the container.

  • Purpose: To document which ports inside the container are intended for serving traffic.
  • Syntax: EXPOSE <port>/<protocol>
  • Example:
    EXPOSE 8080
    
    This line indicates that the application inside the container will be listening on port 8080. To make this port accessible from the outside, you still need to use the -p or -P flag with the docker run command (e.g., docker run -p 8080:8080 my-image).

Dockerfile creation Tutorial - Dockerfile Instructions Explained with example!

This short segment explains the role of the EXPOSE instruction.

Watch from 20:26 to 21:42. The key takeaway is that EXPOSE is metadata; it tells Docker which port the container will listen on, but doesn't map it to the host.

e) CMD

The CMD instruction provides the default command and/or parameters for an executing container. This is a run-time command.

  • Purpose: To specify what command should run when the container starts.
  • Syntax: CMD ["executable","param1","param2"] (exec form, preferred)
  • Key Rules:
    1. A Dockerfile can only have one CMD instruction. If you list more than one, only the last CMD will take effect.
    2. The CMD can be easily overridden by providing a command when you start the container (e.g., docker run my-image <new_command>).
  • Example:
    CMD ["python", "app.py"]
    
    This sets the default command to run python app.py when the container starts.

RUN vs. CMD - A Critical Distinction for Exams:

  • RUN executes commands when you build the image. It's for setting up the environment.
  • CMD executes a command when you run the container. It's for starting the application.
Comparison Table: CMD vs ENTRYPOINT in Dockerfiles
This table compares CMD and ENTRYPOINT, another instruction for running commands. The key difference to note for CMD is that its primary purpose is to provide default arguments for a container and that it can be easily overridden.


3. Example Dockerfile

Let's bring these instructions together into a single, complete Dockerfile for a simple Python web application.

Application Files:

  • app.py: A simple Flask web server.
  • requirements.txt: A file listing Python dependencies (e.g., Flask).
  • Dockerfile: The file we will create.

Dockerfile Content:




# 1. Specify the base image from Docker Hub
FROM python:3.9-slim




# 2. Set the working directory inside the container
WORKDIR /app




# 3. Copy the dependencies file first to leverage Docker's layer caching
COPY requirements.txt .




# 4. Install the dependencies using a RUN command
RUN pip install -r requirements.txt




# 5. Copy the rest of the application code into the working directory
COPY . .




# 6. Expose the port that the application runs on
EXPOSE 5000




# 7. Specify the default command to run when the container starts
CMD ["python", "-m", "flask", "run", "--host=0.0.0.0"]

Explanation:

  1. FROM: Starts with a slim Python 3.9 image.
  2. WORKDIR: Sets all subsequent commands to run inside the /app directory.
  3. COPY requirements.txt .: Copies only the requirements file.
  4. RUN pip install ...: Installs the dependencies. This step is done before copying the main code to take advantage of Docker's layer caching. Dependencies don't change often, so this layer won't need to be rebuilt unless requirements.txt changes.
  5. COPY . .: Copies the rest of the source code (e.g., app.py).
  6. EXPOSE: Documents that the app inside the container uses port 5000.
  7. CMD: Specifies the command to start the Flask application when a container is launched from this image.


Conclusion

In this lesson, we demystified the Dockerfile and its role as the automated recipe for creating Docker images. You now have a solid, exam-ready understanding of the most critical instructions.

Key Takeaways:

  • Dockerfile Purpose: A text file with instructions to automate the building of a consistent and portable Docker image.
  • FROM: Sets the base image; must be the first instruction.
  • RUN: Executes commands during the build process to set up the image environment (e.g., install packages).
  • COPY: Copies files from the host machine into the image's filesystem.
  • EXPOSE: Documents the network port the container will listen on at runtime. It is metadata and does not publish the port.
  • CMD: Specifies the default command to execute when the container runs. It can be overridden.

Preview of the Next Lesson:

Now that we know how to build an image using a Dockerfile, the next logical step is to learn how to share and retrieve these images. In the upcoming lesson, we will focus on this part of your syllabus: Explain the function of a container registry like Docker Hub for storing and distributing container images.