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:
-
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.
-
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.
-
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:
|
|
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:
- 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:
|
|
- Build the Docker image:
Open a terminal or command prompt and navigate to the directory where your Dockerfile is located. Use the
docker buildcommand to build the Docker image.
Syntax:
|
|
Example:
|
|
This command builds a Docker image named myapp using the Dockerfile in the current directory (.).
- Run the Docker container:
Once the Docker image is built successfully, you can run a Docker container based on that image using the
docker runcommand.
Syntax:
|
|
Example:
|
|
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:
- Use a minimal base image: Start with a lightweight base image, such as Alpine Linux or Distroless, to reduce the overall image size.
- Leverage multi-stage builds: Use multi-stage builds to separate the build environment from the runtime environment, reducing the final image size.
- Optimize layer caching: Arrange your Dockerfile instructions to take advantage of Docker’s layer caching, which can significantly speed up the build process.
- Use .dockerignore: Create a
.dockerignorefile to exclude unnecessary files and directories from the build context, reducing the image size. - 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
- FROM:
The
FROMinstruction specifies the base image that your image will be built upon. It is the starting point for your Dockerfile.
Example:
|
|
This instruction tells Docker to use the Ubuntu 20.04 image as the base for your image.
- RUN:
The
RUNinstruction 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:
|
|
This instruction updates the package list and installs the Nginx web server inside the container.
- COPY:
The
COPYinstruction copies files or directories from the host machine into the container’s filesystem.
Example:
|
|
This instruction copies the app.py file from the host machine into the /app/ directory inside the container.
- WORKDIR:
The
WORKDIRinstruction sets the working directory for any subsequentRUN,CMD,ENTRYPOINT,COPY, andADDinstructions.
Example:
|
|
This instruction sets the /app directory as the working directory for the container.
- CMD:
The
CMDinstruction specifies the default command to run when the container starts. It can be overridden at runtime.
Example:
|
|
This instruction tells Docker to run the app.py script using Python when the container starts.
- EXPOSE:
The
EXPOSEinstruction informs Docker that the container listens on specific network ports at runtime.
Example:
|
|
This instruction exposes port 80 on the container to allow external access.
- ENTRYPOINT:
The
ENTRYPOINTinstruction specifies the command that will be executed when the container starts. It is not overridden by thedocker runcommand.
Example:
|
|
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.
-
CMD (Command):
- The
CMDinstruction specifies the default command and/or parameters that should be executed when a container is run. - If the
CMDinstruction is used, it can be overridden by providing a command when starting the container (e.g.,docker run <image> <command>). - If multiple
CMDinstructions are specified in a Dockerfile, only the last one will take effect. - The
CMDinstruction is often used to provide a default command or script that the container should run.
- The
-
ENTRYPOINT (Entry Point):
- The
ENTRYPOINTinstruction specifies the executable that should be run when a container is started. - Unlike
CMD, theENTRYPOINTcommand cannot be easily overridden when starting the container. Instead, any arguments provided when starting the container will be appended to theENTRYPOINTcommand. - The
ENTRYPOINTinstruction is often used to set the main executable of the container, which is the program that the container should run.
- The
The main differences between CMD and ENTRYPOINT are:
-
Overriding:
CMDcan be easily overridden by providing a command when starting the container.ENTRYPOINTis more difficult to override, and any arguments provided when starting the container will be appended to theENTRYPOINTcommand.
-
Default Arguments:
CMDcan be used to provide default arguments for theENTRYPOINTcommand.- If both
CMDandENTRYPOINTare specified in a Dockerfile, theCMDarguments will be appended to theENTRYPOINTcommand.
-
Execution:
CMDspecifies the default command to be executed when the container starts.ENTRYPOINTspecifies 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.
Docker Pull Behavior When an Image Already Exists Locally
When docker pull <image>:<tag> is run and the image already exists locally, Docker compares the local image digest with the remote registry digest for that tag. For example, if ollama/ollama:latest is already present and a new version is released under the same tag, which means ollama released a new version, pulling again with docker pull ollama/ollama:latest retrieves the updated image. Containers cannot be updated in place, so a new container must be created from the updated image. The behavior affecting the new and existing images is outlined below.
Two outcomes exist:
1. Remote digest matches local image
- No layers are downloaded.
- No new image is created.
- Nothing changes locally.
2. Remote digest differs (a newer version is published under the same tag)
- New or changed layers are downloaded.
- A new image object is created with a new image ID.
- The specified tag (e.g.,
latest) is reassigned to the new image. - The previous image remains on disk.
- If the old image has no remaining tags, it becomes
<none>(dangling).
Core mechanics:
- Images are immutable.
- Docker does not overwrite existing images.
- Tags are movable references to image IDs.
- Running containers remain bound to the image ID used at creation.
- Containers must be recreated to use the newly pulled image.
Dangling Images
Dangling images consume disk space and accumulate over time. They are safe to remove if no container depends on them and no rollback is required.
Remove dangling images:
|
|
Remove all unused images:
|
|
In production systems, retaining previous images may be deliberate for rollback. In development environments, regular pruning prevents unnecessary disk growth.
Your inbox needs more DevOps articles.
Subscribe to get our latest content by email.
