Docker
Developing containerized applications within the Docker ecosystem.
Developing containerized applications within the Docker ecosystem.
To install Docker, follow the official instructions provided here. Once installed, validate the following:
docker
CLI is installed and accessible from your command line.Command
docker --version
Output
Docker version 20.10.21, build baeda1f
Command
docker pull hello-world
Output
Using default tag: latest
latest: Pulling from library/hello-world
719385e32844: Pull complete
Digest: sha256:c79d06dfdfd3d3eb04cafd0dc2bacab0992ebc243e083cabe208bac4dd7759e0
Status: Downloaded newer image for hello-world:latest
docker.io/library/hello-world:latest
Command
docker run hello-world
Output
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
...
Docker is an open-source platform for developing, deploying, and distributing containerized software.
The two primary Docker entities are images and containers. Images provide application executable and file system information and may be distributed through registries, which are services that hosts and provide images. These images are defined via Dockerfiles, consisting of sequential build instructions. Relatedly, containers are running instances of images. These container processes are isolated from each other and may be started, stopped, moved, or deleted via the Docker CLI. Any data within a container’s private file system that is not written to persistent storage will be lost upon deleting the container.
docker build . -t techsquawks/hello-world
docker run -t techsquawks/hello-world
FROM alpine:3.14
ENTRYPOINT [ "echo", "hello world!" ]
hello world!
The first l0
++010+
.ne of the Dockerfile defines the base image to use when building the image. In this case, alpine
is leveraged due to its minimal image size. The second line defines the container entrypoint, or the underlying command that will be executed upon running the container.
Docker containers are executed and maintained by the Docker host, which can be accessed via the Docker API or, more preferably, the Docker CLI. docker build
prompts the Docker engine to build the image from the local Dockerfile and tag the image with techsquawks/hello-world
so the build may be readily referenced. Likewise, docker run
executes the resulting image, with the executable program and arguments determined by the Dockerfile ENTRYPOINT
line.
Docker broadly consists of three components, the Docker client, Docker Host, and Docker Hub. The Docker client is used to interact the Docker engine and invoke certain actions. The docker engine builds images and manages containers. Lastly, Docker Hub is an image registry, and is used to distribute images for both public and private use cases.
Figure 1: The three primary Docker components, the Docker Client, Docker Host, and Docker Hub. The Docker Host manages containers and images on a particular machine, the Docker Client invokes certain Docker operations, and the images may be distributed (pushed and pulled) from Docker Hub.
An image is a read-only template that contains all the necessary files, libraries, and configuration required to initialize a container. It acts as a blueprint which defines the application, but is not the actual running process.
To illustrate this, we first start with a Docker image that leverages an existing Ubuntu base image, which contains all the same shared libraries and utilities found in the Ubuntu OS. Similar to how application code can leverage shared libraries, developers can reference existing base images to simplify what dependencies are needed.
docker build . -t techsquawks/ubuntu
docker run -t techsquawks/ubuntu
# Use Ubuntu as base image for container
FROM ubuntu:23.04
# Install latest packages
RUN apt-get update && apt-get install -y locales && rm -rf /var/lib/apt/lists/* \
&& localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8
ENV LANG en_US.utf8
# Copy local text file into container
COPY message.txt message.txt
# Print message from file
ENTRYPOINT [ "cat", "message.txt" ]
ubuntu image example
If we don’t want to leverage an existing image, we can leverage the scartch
base image, which is the most minimal base image Docker provides, containing no directories or files. This can be useful when wanting to minimize the container and image size or for creating custom base images.
docker build . -t techsquawks/ubuntu
docker run -t techsquawks/ubuntu
# A 'scratch' image is an empty base image.
FROM scratch
# Copy binary executable
COPY hello hello
# Run executable
ENTRYPOINT [ "./hello" ]
ubuntu image example
In the above, we copy the hello
binary executable into the image, which has been compiled for the Docker scratch image architecture. We can then execute the binary via the entrypoint.
The COPY command copies the local hello
binary executable into the image file system the image file system, so it can be accessed as the container runs. The entrypoint indicates the executable that should be run when running our container.
For a compressive list of Docker commands that can be used when building an image, please refer to the table below:
Instruction | Description |
---|---|
ADD | Add local or remote files and directories. |
ARG | Use build-time variables. |
CMD | Specify default commands. |
COPY | Copy files and directories. |
ENTRYPOINT | Specify default executable. |
ENV | Set environment variables. |
EXPOSE | Describe which ports your application is listening on. |
FROM | Create a new build stage from a base image. |
HEALTHCHECK | Check a container’s health on startup. |
LABEL | Add metadata to an image. |
MAINTAINER | Specify the author of an image. |
ONBUILD | Specify instructions for when the image is used in a build. |
RUN | Execute build commands. |
SHELL | Set the default shell of an image. |
STOPSIGNAL | Specify the system call signal for exiting a container. |
USER | Set user and group ID. |
VOLUME | Create volume mounts. |
WORKDIR | Change working directory. |
A container is the actual running instance of an application that has been packaged from an image. It includes all the specified files, libraries, and settings from the image it was based upon, and may be aallocated a certain percentage of the host machine’s CPU, meomry, and storrage from the container runtime. Containers run inside a host operating system but are isolated from it, sharing the kernel and resources while having their own file system and network interface.
For instance, consider the previous image example:
docker build . -t techsquawks/ubuntu
# Use Ubuntu as base image for container
FROM ubuntu:23.04
# Install latest packages
RUN apt-get update && apt-get install -y locales && rm -rf /var/lib/apt/lists/* \
&& localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8
ENV LANG en_US.utf8
# Copy local text file into container
COPY message.txt message.txt
# Print message from file
ENTRYPOINT [ "cat", "message.txt" ]
ubuntu image example
The following are common commands for managing containers in the Docker runtime.
Executes a specified Docker image, opening a new container from it and running the commands or processes within it. This command allows you to interact with the container’s filesystem, environment variables, ports, and volumes, making it suitable for running applications or other tasks in a managed and isolated environment.
Executes a command or start a process within one or more existing Docker containers. This command allows you to interact with the processes in a container without starting a new one, which makes it ideal for managing and controlling the applications or services already running inside a container.
Displays the output of the standard output and standard error streams of one or more Docker containers or images. This command shows the most recent log data by default, but you can use options to display older log data, filter by specific patterns, or follow log output in real-time as it becomes available. The docker logs
command is a valuable tool for monitoring and troubleshooting applications running within containers.
Stops a running container in Docker. When executed, it sends an SIGTERM signal to the container, which initiates the process of stopping the container’s services and processes. If the container does not respond to the SIGTERM signal within 10 seconds, a second signal, usually SIGKILL, is sent to terminate the container forcefully. This command can be used with options to specify additional behaviors, such as -t
or --timeouts
to set stop timeouts, or -f
or --force-exit
to force stop a container that’s not responding.
Removes stopped, exited, or running containers. By default, it removes only stopped containers that do not have any instances running in them. When executed, docker rm CONTAINER_IDS
or docker rm IMAGE@TAG
will remove the specified container(s), effectively deleting their files and state from the local machine.
However, note that docker rm
does not remove images associated with a container if those images are not in use by other containers. To completely remove an image, you would have to use docker rmi
. You can also use various options with the rm
command, like -f
, --force
, or -v
, to modify its behavior, e.g., to force removal without prompting for user confirmation, or to include volumes in removal.