Docker
An overview of Docker image and container operations, Dockerfile instructions, and CPU, memory, and disk I/O resource limits.
Updated
Image Operations
Pulling Images
# Pull the latest image (the default tag is latest)
docker pull nginx
# Pull a specific version (e.g. Python 3.8)
docker pull python:3.8
# Pull images of all tags (e.g. every busybox version)
docker pull -a busybox
Building Images
# Build an image from a Dockerfile (the current directory must contain a Dockerfile)
docker build -t myapp:1.0 .
# Commit a new image from a container (save a running container as an image)
docker commit container_id myapp:snapshot
Deleting Images
# Delete by name
docker rmi nginx:latest
# Delete by image ID (short or long ID)
docker rmi 501ad78535f0
# Force delete (even if containers depend on it)
docker rmi -f myapp:old
# Delete all unused images
docker image prune -a
# Delete all local images
docker rmi -f $(docker images -aq)
Listing Images
# Show all images (including intermediate layers)
docker images -a
# Filter by name (e.g. all nginx-related images)
docker images nginx*
# Show image IDs only
docker images -q
Searching Images
# Search images on Docker Hub
docker search redis
# Filter for official images with at least 1000 stars
docker search --filter "is-official=true" --filter "stars=1000" mysql
Viewing Image Details
# Show image metadata (such as layer info, environment variables)
docker image inspect nginx:latest
# View the image build history
docker history myapp:1.0
Importing and Exporting Images
# Export an image to a .tar file (for offline transfer)
docker save -o nginx.tar nginx:latest
# Load an image from a .tar file
docker load -i nginx.tar
Publishing Images
# Log in to Docker Hub or a private registry
docker login -u username -p password registry.example.com
# Push an image (tag it first)
docker push registry.example.com/myapp:prod
Container Operations
Creating Containers
# Basic run (enters an interactive terminal after starting)
docker run -it --name my_ubuntu ubuntu:22.04 /bin/bash
# Run in background + port mapping + volume mount
docker run -d --name my_nginx -p 8080:80 -v /data:/usr/share/nginx/html nginx:latest
# Create without starting
docker create --name pending_container redis:alpine
Deleting Containers
# Stop a container
docker stop my_nginx
# Force-delete a running container
docker rm -f my_nginx
# Batch-delete all stopped containers
docker container prune
# Delete all containers
docker rm -f $(docker ps -aq)
Updating Container Configuration
# Dynamically adjust a container's memory limit (the container must be running or stopped)
docker update --memory 512m my_container
# Change a container's restart policy (e.g. auto-restart after a crash)
docker update --restart=always my_container
# Enter a container, modify files, and commit as a new image
docker commit my_container my_image:v2
docker run -d --name new_container my_image:v2
Viewing Container Status
# View running containers
docker ps
# View all containers (including stopped ones)
docker ps -a --format "table {{.ID}}\t{{.Names}}\t{{.Status}}"
# View a container's resource usage
docker stats my_container
Viewing Container Internals
# Follow logs in real time (like tail -f)
docker logs -f --tail 100 my_container
# View container metadata (such as IP, mount points)
docker inspect my_container | grep -E "IPAddress|Mounts"
# View the container's process list
docker top my_container
Entering a Container
# Enter a running container interactively
docker exec -it my_container /bin/bash
# Run a one-off command inside a container
docker exec my_container ls /var/log
Hot-Updating Containers
# Rolling update (in Swarm mode)
docker service update --image nginx:v2 --update-parallelism 2 web_service
File Transfer Between Host and Container
# Copy a file from a container to the host
docker cp my_container:/app/config.yaml /backup/
# Upload a file from the host to a container
docker cp /data/update.patch my_container:/tmp/
Dockerfile
Common Dockerfile instructions are as follows; building the image is done with docker build -t image-name:tag Dockerfile-directory.
# ========== Base image configuration ==========
# Use the official Alpine base image (lightweight, only 5MB)
# Multi-stage build example: the first stage is named builder, used as the compile environment
FROM alpine:3.18 AS builder
# Maintainer info (replaces the deprecated MAINTAINER)
LABEL maintainer="yourname@example.com"
# ========== Environment variables and arguments ==========
# Set the application path inside the container
ENV APP_HOME=/app
# Build-time argument, can be overridden with --build-arg
ARG BUILD_VERSION=1.0.0
# ========== System configuration ==========
# Update the system and install dependencies (combine RUN commands to reduce image layers)
RUN apk update && apk add --no-cache \
python3 \
py3-pip \
curl \
nginx \
&& rm -rf /var/cache/apk/*
# ========== File operations ==========
# Set the working directory
WORKDIR $APP_HOME
# Copy local files into the image (prefer COPY)
COPY requirements.txt .
# Automatically extracts remote files (use ADD with caution)
ADD https://example.com/static-assets.tar.gz /tmp
# ========== Application build ==========
# Install Python dependencies
RUN pip3 install --no-cache-dir -r requirements.txt
# Copy the application source code
COPY src/ .
# ========== Network and storage ==========
# Declare the listening port (needs docker run -p mapping)
EXPOSE 8080
# Declare a persistent data volume
VOLUME ["/data"]
# ========== Security configuration ==========
# Create a non-root user
RUN adduser -D appuser && chown -R appuser:appuser $APP_HOME
# Switch the runtime user
USER appuser
# ========== Health check ==========
HEALTHCHECK --interval=30s --timeout=3s \
CMD curl -f http://localhost:8080/health || exit 1
# ========== Multi-stage build ==========
# Second stage: the production image
FROM alpine:3.18 AS production
# Copy the build result from the builder stage
COPY --from=builder /app /app
WORKDIR /app
# ========== Startup command ==========
# Prefer the exec form to avoid shell parsing issues
# Fixed entrypoint; when multiple entrypoints exist, only the last one takes effect
ENTRYPOINT ["python3"]
# Default arguments passed to the entrypoint (can be overridden by docker run)
# e.g. `docker run image-name:tag main.py`
# then the container no longer runs `python3 app.py` on startup, but runs `python3 main.py`
CMD ["app.py"]
# ========== Metadata ==========
# Triggered automatically when a child image is built
ONBUILD COPY . /app
Resource Management
Docker resource management matters: it protects other containers from being affected by coding problems such as memory leaks, infinite loops, and large file reads/writes (uploads/downloads), so that a single memory leak does not freeze and stop every container together.
CPU Shares
CPU share numbers only matter when resources are contended.
The proportion of CPU time slices a container occupies is its own share divided by the total shares of all contending containers.
If running on multiple CPUs, or when there is no contention, even a share of 1 can occupy an entire CPU.
docker run -itd \
# Declare the name of the container to create
--name test-cpu-1 \
# Specify the container's CPU weight
--cpu-shares 50 \
# The image to use
centos
Pinning a Container to Specific CPU Cores
docker run -itd \
# Declare the name of the container to create
--name test-cpu-2 \
# Restrict the container to CPU 0 and CPU 1
--cpuset-cpus 0,1 \
# Specify the container's CPU weight
--cpu-shares 512 \
# The image to use
centos
Limiting a Container's Memory
docker run -itd \
# Declare the name of the container to create
--name test-memory \
# Use at most 0.5G of memory
--memory 512m \
# The image to use
centos
Limiting a Container's I/O Resources
docker run -itd \
# Declare the name of the container to create
--name test-io \
# Specify a partition rather than a whole disk
--device=/dev/sda1 \
# Grant device operation permissions
--cap-add=SYS_RAWIO \
# Mount a volume; mounted volumes go through file reads and writes, not the low-level API, and may bypass the read/write limits
# When mounting with -v, if the external directory is deleted, even creating a same-named directory later will not sync it into docker
# because the corresponding inode can no longer be found
-v /var/www/html:/var/www/html \
# Limit read speed to 10mbps/s
--device-read-bps /dev/sda1:10mb \
# Limit write speed to 1mbps/s
--device-write-bps /dev/sda1:1mb \
# The image to use
centos
Automatic Resource Release
docker run -itd \
# Declare the name of the container to create
--name test-auto-free \
# Automatically release after execution finishes, for scenarios where the container acts as a job runner
# such as the build stage in a build scenario, a stress-test runtime environment, and so on
--rm \
# The image to use
centos \
# The command to run
sleep 8