Skip to content

Dockerfile

Intro

In the previous section, we learned how to create a new image from a running container. In this section, we will explore the process of creating a custom Docker image using a manifest called Dockerfile.

Let's begin with an example. Imagine you have developed a Python code and now you wish to run it on a new server. Essentially, you need to install an operating system and all the necessary packages to execute your code. The diagram below illustrates the steps involved:

Dockerfile-core-1

In a Dockerfile, we can refer to the operating system mentioned in the above diagram as the base image. In a Dockerfile, the base image refers to the starting point for building a new Docker image. It is the foundation upon which your custom image is built. The base image contains the operating system and other dependencies required for your application to run.

After specifying the base image, we can proceed to run commands in the Dockerfile to install Python and dependency packages, as well as copy files into the image. Finally, we can create an entry point that will be responsible for running the code.

Dockerfile-mapping

Dockerfile is a text based flow of the above diagram. A Dockerfile is a text file that contains a set of instructions and commands used to build a Docker image. It serves as a blueprint or recipe for creating a customized Docker image. The Dockerfile specifies the base image to start from, as well as the steps needed to install dependencies, configure the environment, and copy files into the image.

Dockerfile structure

Let's revisit our Python code example and align the execution flow with the structure of a Dockerfile.

Dockerfile

The structure of a Dockerfile typically follows a specific format and order of instructions. Here is a general outline of a Dockerfile structure:

  1. Base Image: The first instruction in a Dockerfile is usually the FROM instruction, which specifies the base image to use. It defines the starting point for building your custom image. For example: FROM ubuntu:latest

  2. Environment Configuration: This section includes instructions to configure the environment within the Docker image. It often involves installing dependencies, setting environment variables, and performing system-level configurations. Common instructions used here include RUN, ENV, and ARG.

  3. File Copy: In this section, you can copy files and directories from the host machine into the Docker image using the COPY or ADD instructions. This allows you to include application code, configuration files, and other necessary assets in the image.

  4. Working Directory: The WORKDIR instruction sets the working directory for subsequent instructions. It is a good practice to set a specific directory where the application code and files will reside within the image.

  5. Execution Commands: This section includes instructions to run commands or scripts inside the Docker image during the build process. The RUN instruction is commonly used here to install packages, compile code, or perform other necessary tasks.

  6. Expose Ports: The EXPOSE instruction specifies the network ports on which the container will listen at runtime. It is used to document which ports should be published when running the container.

  7. Container Execution: The final instructions in a Dockerfile define the command or entry point that will be executed when the container is run. This can be specified using the CMD or ENTRYPOINT instruction.

It's important to note that the structure and contents of a Dockerfile can vary depending on the specific requirements of your application or project. However, the outlined structure provides a general guideline for creating Dockerfiles.

You should understand how to use the syntax in a Dockerfile, but there's no need to memorize all the Dockerfile syntax. You can refer to the Dockerfile reference documentation to find detailed information about each instruction and its usage. This documentation provides comprehensive details on all the available instructions and their options. It serves as a valuable resource to assist you in creating and understanding Dockerfile syntax.

The first Dockerfile

In this section, we will be writing our first Dockerfile and creating a custom image to run a Python Flask application.

You can find all manifest and sample codes in here.

Referring to the previous diagram, we require a manifest to set up an operating system known as the base image. Additionally, we need to install Python along with its dependencies, including pip. Finally, we'll copy the Python source code into the image and define the command for execution. The below code lines is a manifest describing all these steps:

# Use Ubuntu as the base image
FROM ubuntu:latest

# Set the working directory inside the container
WORKDIR /app

# Update packages and install necessary dependencies
RUN apt-get update && apt-get install -y \
    python3 \
    python3-pip

# Install Python dependencies
RUN pip3 install flask

# Copy the application code into the container
COPY . .

# Expose the port on which the Flask app will listen
EXPOSE 5000

# Define the command to run the Flask app
CMD ["python3", "app.py"]

This manifest, commonly referred to as the Dockerfile, should be saved in a file named Dockerfile. To build the image based on the Dockerfile, you can use the docker build command.

docker build -t first .

-t <image_name> specifies the name and optionally a tag for the image. <path_to_Dockerfile> is the path to the directory containing the Dockerfile. You can use . to indicate the current directory if the Dockerfile is located there.

Congratulations! You have successfully built your first custom image, which is now ready to be used. To run a container using the newly created image, you can follow these steps:

docker run first

By executing the docker run command, a container will be created and started based on the specified image. You can now access and interact with your Python Flask application inside the running container. You can access to the app with http://localhost:5000 .

Do we always require an OS base image like Ubuntu to build our custom image? Are there alternative solutions for creating an image for your Python code?

While using an OS base image like Ubuntu is a common approach, it is not the only solution for building Docker images for Python code. Docker provides specialized base images specifically designed for running Python applications. These images, such as python, python-alpine, or python-slim, come with the necessary dependencies and configurations for Python development.

These Python-specific base images are generally smaller in size compared to full OS base images like Ubuntu. They are optimized for running Python applications and provide a more lightweight option. Using a Python-specific base image can help reduce the overall image size and improve the efficiency of your Docker containers.

However, the choice of base image depends on your specific requirements. If your application requires specific OS-level dependencies or configurations, an OS base image like Ubuntu may be more suitable. It allows you to have greater control and flexibility over the environment.

Ultimately, it is essential to consider your application's needs and choose the appropriate base image accordingly. Let's write the second Dockerfile and improve the first one by using a Python base image instead of Ubuntu.

Here's an example of a revised Dockerfile using a Python base image:

# Use Python as the base image
FROM python:3.9-slim

# Set the working directory inside the container
WORKDIR /app

# Install Python dependencies
RUN pip3 install flask

# Copy the application code into the container
COPY . .

# Expose the port on which the Flask app will listen
EXPOSE 5000

# Define the command to run the Flask app
CMD ["python3", "app.py"]

Comments