Contents

Docker Images

Website Visitors:

What are Docker Images?

Docker images are read-only templates that contain everything needed to run a container, including the application code, runtime, libraries, dependencies, and configuration files. They are built using a declarative file called a Dockerfile, which specifies the instructions for creating the image. Docker images are stored in a registry, such as Docker Hub, from where they can be pulled and run on any Docker-enabled host.

The key characteristics of Docker images are:

  1. Immutability: Docker images are immutable, meaning that once an image is created, it cannot be modified. If you need to make changes, you must create a new image with the desired modifications.

  2. Layered Architecture: Docker images are built using a layered architecture, where each layer represents a specific set of changes. This allows for efficient image building, as only the modified layers need to be rebuilt, and the unchanged layers can be reused. If any layer is failed and script is stopped, when you fix it and run the script again, it will continue from the layer it is stopped.

  3. Caching: Docker leverages caching to speed up the image building process. When you build a new image, Docker checks the cache for existing layers and reuses them if possible, reducing the time required to build the image.

Components of a Docker Image

  • Base Image: The base image serves as the foundation for the Docker image and contains the operating system and essential tools required to run the application.

  • Layers: Docker images are composed of multiple layers, each representing a set of filesystem changes. Layers are stacked on top of each other, with each layer adding or modifying files in the image.

  • Metadata: Docker images also include metadata such as the image name, tags, creation date, and size, which provide information about the image.

Building Docker Images

To build a Docker image, you need to create a Dockerfile that defines the steps for building the image. The Dockerfile typically includes instructions for installing dependencies, copying files into the image, setting environment variables, and defining the entry point for the container. Once the Dockerfile is created, you can use the docker build command to build the image.

In the docker file, everything in the left in caps are instructions. Next to the instructions, everything to the right are arguments to those instructions. In below example, run, copy, entrypoint are instructions and ubuntu, apt-get update etc are arguments.

It is generally recommended to use lowercase letters for the arguments in a Dockerfile. This is a common convention and best practice in the Docker community.

Here’s an example Dockerfile:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# Start from base image
FROM ubuntu

# Run the update command install python software
RUN apt-get update && apt-get -y install python

# Install flask
RUN pip install flask flask-mysql

# Copies all files in current directory to docker's /opt/source-code folder. You should have files in the same directory where you have the dockerfile. 
COPY . /opt/source-code

# Set the command to run everytime container starts.
ENTRYPOINT FLASK_APP=/opt/source-code/app.py flask run

Save above script with the name dockerfile in the current directory. Next run the docker build . command. This command reads the current folder, picks up dockerfile file and starts building it. In the command, . is also mandatory.

Custom dockerfile file name

If you have a file named dockerfile when you run docker build . command, it reads the dockerfile automatically. So you do not have to specify any filename. But if you have a differnt file name for your dockerfile, then you should use -f parameter to specify the filename as shown below:

docker build -f /home/ubuntu/mydockerfile -t myimage .

Here, using -f parameter we have specified the path to the docker file mydockerfile which is located at /home/ubuntu. So, the whole path is /home/ubuntu/mydockerfile. -t parameter is for specifying a tag or name to your new image.

Managing Docker Images

Docker provides several commands to manage Docker images, including:

  • docker build: Builds a new Docker image from a Dockerfile.
  • docker pull: Pulls a Docker image from a registry (e.g., Docker Hub).
  • docker push: Pushes a Docker image to a registry.
  • docker images: Lists all the Docker images on the local system.
  • docker rmi: Removes one or more Docker images.

Docker images can be stored and shared in public or private registries, such as Docker Hub, Amazon Elastic Container Registry (ECR), or a self-hosted registry like Harbor.

Running DockerFile

To run a Dockerfile and build a Docker image from it, you need to use the docker build command. Here’s a step-by-step guide on how to run a Dockerfile:

  1. Create a Dockerfile: First, create a Dockerfile in your project directory. You can use a text editor to create and edit the Dockerfile. Make sure to include the necessary instructions for building your Docker image, such as FROM, RUN, COPY, CMD, etc.

Example Dockerfile:

1
2
3
4
5
FROM ubuntu:20.04
RUN apt-get update && apt-get install -y nginx
COPY app.py /app/
WORKDIR /app
CMD ["python", "app.py"]
  1. Build the Docker image: Open a terminal or command prompt and navigate to the directory where your Dockerfile is located. Use the docker build command to build the Docker image.

Syntax:

1
docker build -t <image_name> <path_to_Dockerfile>

Example:

1
2
docker build -t myapp .
# **docker builder prune -a** - removes all docker build cache.

This command builds a Docker image named myapp using the Dockerfile in the current directory (.).

  1. Run the Docker container: Once the Docker image is built successfully, you can run a Docker container based on that image using the docker run command.

Syntax:

1
docker run -d --name <container_name> <image_name>

Example:

1
docker run -d --name mycontainer myapp

This command runs a Docker container named mycontainer based on the myapp image in the background (-d flag).

That’s it! You have now successfully run a Dockerfile to build a Docker image and run a Docker container based on that image. You can customize the Dockerfile and Docker run command based on your specific requirements and application setup.

Optimizing Docker Images

To optimize Docker images, you can consider the following best practices:

  1. Use a minimal base image: Start with a lightweight base image, such as Alpine Linux or Distroless, to reduce the overall image size.
  2. Leverage multi-stage builds: Use multi-stage builds to separate the build environment from the runtime environment, reducing the final image size.
  3. Optimize layer caching: Arrange your Dockerfile instructions to take advantage of Docker’s layer caching, which can significantly speed up the build process.
  4. Use .dockerignore: Create a .dockerignore file to exclude unnecessary files and directories from the build context, reducing the image size.
  5. Implement security best practices: Keep your base images up-to-date, use trusted base images, and apply security best practices to ensure the overall security of your Docker images.

Dockerfile Instructions with Examples

  1. FROM: The FROM instruction specifies the base image that your image will be built upon. It is the starting point for your Dockerfile.

Example:

1
FROM ubuntu:20.04

This instruction tells Docker to use the Ubuntu 20.04 image as the base for your image.

  1. RUN: The RUN instruction executes commands inside the container during the build process. It is used to install packages, update software, or perform any other necessary setup tasks.

Example:

1
RUN apt-get update && apt-get install -y nginx

This instruction updates the package list and installs the Nginx web server inside the container.

  1. COPY: The COPY instruction copies files or directories from the host machine into the container’s filesystem.

Example:

1
COPY app.py /app/

This instruction copies the app.py file from the host machine into the /app/ directory inside the container.

  1. WORKDIR: The WORKDIR instruction sets the working directory for any subsequent RUN, CMD, ENTRYPOINT, COPY, and ADD instructions.

Example:

1
WORKDIR /app

This instruction sets the /app directory as the working directory for the container.

  1. CMD: The CMD instruction specifies the default command to run when the container starts. It can be overridden at runtime.

Example:

1
CMD ["python", "app.py"]

This instruction tells Docker to run the app.py script using Python when the container starts.

  1. EXPOSE: The EXPOSE instruction informs Docker that the container listens on specific network ports at runtime.

Example:

1
EXPOSE 80

This instruction exposes port 80 on the container to allow external access.

  1. ENTRYPOINT: The ENTRYPOINT instruction specifies the command that will be executed when the container starts. It is not overridden by the docker run command.

Example:

1
ENTRYPOINT ["nginx", "-g", "daemon off;"]

This instruction sets Nginx as the entry point for the container with the specified arguments.

CMD vs ENTRYPOINT

In the context of Docker, CMD and ENTRYPOINT are both instructions used in a Dockerfile to specify the command that should be executed when a container is started. However, they have different behaviors and use cases.

  1. CMD (Command):

    • The CMD instruction specifies the default command and/or parameters that should be executed when a container is run.
    • If the CMD instruction is used, it can be overridden by providing a command when starting the container (e.g., docker run <image> <command>).
    • If multiple CMD instructions are specified in a Dockerfile, only the last one will take effect.
    • The CMD instruction is often used to provide a default command or script that the container should run.
  2. ENTRYPOINT (Entry Point):

    • The ENTRYPOINT instruction specifies the executable that should be run when a container is started.
    • Unlike CMD, the ENTRYPOINT command cannot be easily overridden when starting the container. Instead, any arguments provided when starting the container will be appended to the ENTRYPOINT command.
    • The ENTRYPOINT instruction is often used to set the main executable of the container, which is the program that the container should run.

The main differences between CMD and ENTRYPOINT are:

  1. Overriding:

    • CMD can be easily overridden by providing a command when starting the container.
    • ENTRYPOINT is more difficult to override, and any arguments provided when starting the container will be appended to the ENTRYPOINT command.
  2. Default Arguments:

    • CMD can be used to provide default arguments for the ENTRYPOINT command.
    • If both CMD and ENTRYPOINT are specified in a Dockerfile, the CMD arguments will be appended to the ENTRYPOINT command.
  3. Execution:

    • CMD specifies the default command to be executed when the container starts.
    • ENTRYPOINT specifies the executable that should be run when the container starts.

Entrypoint is the exe that is run/executed when the container starts and CMD is used to send arguments to that entrypoint exe. In general, it’s recommended to use ENTRYPOINT to set the main executable of the container and CMD to provide default arguments for that executable. This allows for more flexibility in how the container is run, as the ENTRYPOINT command can be supplemented with additional arguments when starting the container.

Your inbox needs more DevOps articles.

Subscribe to get our latest content by email.