Docker Daemon Configuration and Image Management Essentials
Docker leverages specific Linux kernel features to provide an isolated and resource-managed environment for applications. Key among these are Namespaces and Cgroups. Namespaces are responsible for isolating resources like CPU, memory, and network, ensuring that containers operate independently without interfering with each other. Cgroups (Control Groups) provide mechanisms to limit and monitor resource usage, preventing any single container from monopolizing system resources. For efficient storage, Docker employs copy-on-write file systems, with OverlayFS being a common choice, allowing multiple containers to share a base image efficiently while maintaining their own writable layers.
Docker Installation on CentOS 7
This guide assumes an offline installation approach using pre-downloaded RPM packages on CentOS 7.5.
- Transfer RPM packages: Copy the necessary Docker Engine packages (
docker-ce,docker-ce-cli, andcontainerd.io) to your server, for example, into a directory named/opt/docker-rpms/. - Install packages: Navigate to the directory containing the RPMs and use
yum localinstallto install them.
sudo yum localinstall /opt/docker-rpms/docker-ce-19.03.6-3.el7.x86_64.rpm \
/opt/docker-rpms/docker-ce-cli-19.03.6-3.el7.x86_64.rpm \
/opt/docker-rpms/containerd.io-1.2.10-3.2.el7.x86_64.rpm
After installation, manage the Docker daemon:
- Start Docker service:
sudo systemctl start docker
- Enable Docker to start on boot:
sudo systemctl enable docker
- Verify enabled services:
systemctl list-unit-files | grep enabled
Configuring Docker Daemon
Customize Docker daemon settings by editing the daemon.json file, typically located at /etc/docker/daemon.json. This file allows configuring aspects like registry mirrors for faster image pulls and the default data root directory for Docker. If the file doesn't exist, create it.
{
"registry-mirrors": ["https://your-mirror-id.mirror.aliyuncs.com"],
"data-root": "/var/lib/docker-data"
}
After making changes, reload the systemd daemon configuration and restart the Docker service for the changes to take effect.
sudo systemctl daemon-reload
sudo systemctl restart docker.service
Running Your First Container
To confirm Docker is working, run the hello-world container. Docker will automatically pull the image if it's not present locally and then execute it.
docker run hello-world
Docker Daemon Communication Methods
By default, the Docker client communicates with the Docker daemon via a Unix socket at unix:///var/run/docker.sock. If the daemon is stopped, the client cannot connect:
$ sudo systemctl stop docker
$ docker info
Client:
Debug Mode: false
Server:
ERROR: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
errors pretty printing info
Docker supports several communication protocols:
- Unix Socket:
unix:///var/run/docker.sock(default) - TCP Socket:
tcp://host:port(for remote access) - File Descriptor:
fd://socketfd
Enabling Remote TCP Access
To enable the Docker daemon to listen for connections over TCP, you need to modify its systemd unit file. Edit the file /usr/lib/systemd/system/docker.service.
sudo vim /usr/lib/systemd/system/docker.service
Locate the ExecStart line and modify it to include the TCP listener. For example, to listen on all network interfaces (0.0.0.0) on port 2375, in addition to the default Unix socket:
[Service]
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock --containerd=/run/containerd/containerd.sock
After saving the changes, reload systemd configurations and restart the Docker service:
sudo systemctl daemon-reload
sudo systemctl restart docker.service
Verify that the daemon is listening on the specified TCP port:
$ sudo systemctl status docker.service
● docker.service - Docker Application Container Engine
Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
Active: active (running) since Mon 2023-10-26 10:00:00 EST; 1min 9s ago
Docs: https://docs.docker.com
Main PID: 12345 (dockerd)
Tasks: 13
Memory: 46.2M
CGroup: /system.slice/docker.service
└─12345 /usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock --containerd=/run/containerd/containerd.sock
Confirm the port is open:
$ netstat -ntlp | grep 2375
tcp6 0 0 :::2375 :::* LISTEN 12345/dockerd
You can now connect to this Docker daemon remotely from another machine (e.g., at IP 192.168.1.51):
docker -H 192.168.1.51:2375 info
docker -H 192.168.1.51:2375 images
Essential Docker Image Operations
Searching and Pulling Images
- Search for images: Find available images on Docker Hub.
docker search nginx
- Download an image: Pull an image from a registry. If no tag is specified, Docker pulls the
latesttag by default.
docker pull nginx:latest
# or simply
docker pull nginx
Docker follows a specific process when retrieving an image:
- Checks for the image locally.
- Queries the specified image registry (e.g., a private registry) if provided in the image name.
- If no specific registry is mentioned and the image isn't found locally, it attempts to download from the default Docker Hub registry.
Creating Images from Running Containers
You can create a new image from a running container's current state, similar to taking a VM snapshot. This is useful for quickly saving changes made inside a contianer for later reuse.
docker commit [CONTAINER_ID] [NEW_IMAGE_NAME]:[TAG]
Example:
docker commit 0cc7ddd85c92 custom-nginx:1.0
Note: You cannot delete an image that has dependent child images (e.g., an image created using docker commit from it) without first deleting the dependent images. Attempting to do so will result in an error:
Error response from daemon: conflict: unable to delete ae2feff98a0c (cannot be forced) - image has dependent child images
To run a container from the newly created image:
docker run -d -p 90:80 custom-nginx:1.0
Removing Images
To delete an image, all containers based on that image must first be stopped and removed. If a container is running, it cannot be force-deleted.
- List all images:
docker images
- List all containers (including stopped ones):
docker ps -a
- Stop a running container:
docker stop [CONTAINER_NAME_OR_ID]
- Remove a container:
docker rm [CONTAINER_ID]
- Remove an image:
docker rmi [IMAGE_ID]
Exporting and Importing Images
Docker images can be saved to a tar archive and loaded back, useful for transferring images between Docker hosts without a registry.
- Export an image to a tarball:
docker save nginx > nginx_image.tar.gz
docker save nginx:latest > nginx_v1.tar.gz
- Import an image from a tarball:
docker load -i <fileName>.tar.gz
Important: If the exact image already exists in your local Docker image cache, importing it again might not update the visible tags or create new ones unless the existing image is first removed.
Example workflow for re-importing:
# Stop and remove all containers based on 'nginx'
docker ps -a | grep nginx
docker stop [CONTAINER_ID_1] [CONTAINER_ID_2] ...
docker rm [CONTAINER_ID_1] [CONTAINER_ID_2] ...
# Remove the existing nginx image
docker rmi nginx:latest
# Load the image from the archive
docker load -i nginx_image.tar.gz
Tagging Images
Image tags act like aliases or pointers to an existing image ID, similar to hard links in a filesystem. This is crucial for pushing images to private registries, which often require a specific naming convention (e.g., registry_hostname/repo_name:tag).
docker image tag [SOURCE_IMAGE][:TAG] [TARGET_IMAGE][:TAG]
Example: Tagging the nginx:latest image for a hypothetical registry at myregistry.com:
docker image tag nginx:latest myregistry.com/web/nginx:v1.0
Listing images will now show the new tag pointing to the same image ID:
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest ae2feff98a0c 13 days ago 133MB
myregistry.com/web/nginx v1.0 ae2feff98a0c 13 days ago 133MB
You can then launch a container using the new tag:
docker run -itd --name mywebserver -p 90:80 myregistry.com/web/nginx:v1.0
Common docker run options:
Building Custom Images with Dockerfiles
Dockerfiles provide a robust, repeatable way to define and build custom images. Here's an example to create a JDK image:
- Prepare JDK tarball: Upload the JDK (e.g.,
jre1.8.0_211.tar.gz) to a directory, for instance,/opt/jdk-build/. - Pull base image: We'll use
frolvlad/alpine-glibcas Alpine Linux normally uses musl libc, which is incompatible with Oracle JDK. This base image provides glibc.
docker pull frolvlad/alpine-glibc
- Create Dockerfile: In the
/opt/jdk-build/directory, create a file namedDockerfile.
FROM frolvlad/alpine-glibc
LABEL maintainer="your-name-here"
# Configure Alpine package mirror and install bash
RUN echo "https://mirror.tuna.tsinghua.edu.cn/alpine/v3.4/main/" > /etc/apk/repositories && \
apk add --no-cache bash
# Add and extract the JRE tarball
ADD jre1.8.0_211.tar.gz /usr/java/jdk/
# Set JAVA_HOME and update PATH
ENV JAVA_HOME=/usr/java/jdk/jre1.8.0_211
ENV PATH="${PATH}:${JAVA_HOME}/bin"
# Make Java executable (if not already)
RUN chmod +x /usr/java/jdk/jre1.8.0_211/bin/java
# Set working directory
WORKDIR /opt
- Build the image: Run the
docker buildcommand from the directory containing the Dockerfile. The.indicates the build context.
docker build -t mycompany/jdk1.8:v1.0 .
- Run a container from the custom image:
docker run -itd --name myjdkapp mycompany/jdk1.8:v1.0
- Verify JDK installation inside the container:
docker exec -it myjdkapp bash
bash-4.3# java -version
java version "1.8.0_211"
Java(TM) SE Runtime Environment (build 1.8.0_211-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.211-b12, mixed mode)
Inspecting Image Details
- View image build history: See the layers and commands used to build an image.
docker history mycompany/jdk1.8:v1.0
- Examine image metadata: Get detailed information about an image, including its configuration, layers, and environment variables.
docker image inspect mycompany/jdk1.8:v1.0