Docker Cheatsheet
Docker Images and Containers
# Lists images stored in the docker daemon's data root, by default /var/lib/docker.
$ docker image ls
# List all containers
$ docker ps -a
# List running containers including CPU/memory size
$ docker ps -s
# Specify format
$ docker ps -a --format "{{.ID}},{{.Names}},{{.Status}},{{.Image}},{{.Ports}}"
# Go inside the container; `-i` for `interactive, `t` for `terminal.
$ docker exec -it <container> bash
# Execute
$ docker exec -i ... # interactive mode
$ docker exec -d ... # detached mode
# Start a Ubuntu 20.04
$ docker run -it --entrypoint "/bin/bash" ubuntu:20.04
# Export a container’s filesystem as a tar archive
$ docker export --output="latest.tar" <container>
# port forwarding
$ docker run -p 8080:8080 myserver
# kill all containers
$ docker kill $(docker ps -q)
# Remove all containers in exited status
$ docker rm $(docker ps -a -f status=exited -q)
# Check port mapping
$ docker port CONTAINER_NAME
6443/tcp -> 127.0.0.1:34305
# Remove unused data (images, containters, networks, build cache, etc)
$ docker system prune
Docker Info and Daemon
Docker daemon communicates with the Linux kernel in order to create containers. docker CLI -> dockerd -> kernel
.
# Run Docker daemon in the foreground
$ dockerd
# Run Docker daemon as a systemd service
$ sudo systemctl start docker
# Check if dockerd is running
$ sudo systemctl status docker
# Check docker status
$ curl -s --unix-socket /var/run/docker.sock http/_ping
OK%
# Check docker info (these 2 are the same)
$ docker info
$ docker system info
# Display the SBOM (Software Bill Of Materials) of any Docker image. This feature outputs the SBOM in a table or can be exported into SPDX and CycloneDX formats.
$ docker sbom
# Check disk usage
$ docker system df
$ docker system df -v # v for verbose
Docker Registries
# Create a local registry
$ docker run -d -p 5000:5000 --restart=always --name registry registry:2
# 5000 is used inside the container (hardcoded in Dockerfile);
# if 5000 is already used on local machine, change it to another port like 5001
$ docker run -d -p 5001:5000 --restart=always --name registry registry:2
# Check if registry is running
$ docker ps
# If needs login
$ docker login $REGISTRY
# Pull from docker.io/library/ubuntu:latest
$ docker pull ubuntu
# Tag and Push to local registry
$ docker tag ubuntu:22.04 $REGISTRY/demo/ubuntu:22.04
$ docker push $REGISTRY/demo/ubuntu:22.04
# Pull from local registry
$ docker pull $REGISTRY/library/ubuntu:22.04
Check registry:
$ curl -X GET http://myregistry:5000/v2/_catalog
{"repositories":["myimage"]}
$ curl -X GET http://myregistry:5000/v2/mymage/tags/list
{"name":"myimage","tags":["latest"]}
# with user and password
$ curl -X GET -u <user>:<pass> https://myregistry:5000/v2/_catalog
# with cert
$ curl --cacert domain.crt https://myregistry:5000/v2/_catalog
Docker image name = repository + ":" + tag
Source Code
The Git repo of the official Docker image for distribution. https://github.com/docker/distribution-library-image/tree/master
https://github.com/distribution/distribution
Download and run registry locally:
wget https://github.com/distribution/distribution/releases/download/v2.8.2/registry_2.8.2_linux_amd64.tar.gz
tar xvzf registry_2.8.2_linux_amd64.tar.gz
./registry --version
./registry github.com/docker/distribution 2.8.2
Notice github.com/docker/distribution instead of github.com/distribution/distribution
Registry Mirror
Docker registry mirror: add registry-mirrors
to the /etc/docker/daemon.json
configuration file.
{
...
"registry-mirrors": ["https://mirror.gcr.io"]
}
Now docker pull
will pull from the https://mirror.gcr.io
instead of docker.io
.
Side note: containerd
registry mirror can be configured in /etc/containerd/config.toml
The official image: registry:2
- Docker hub: https://hub.docker.com/_/registry
- Source code: https://github.com/docker/distribution-library-image
Docker Networking
# List networks
$ docker network ls
# Create network
$ docker network create
# Remove network
$ docker network rm
# Connect container to network
$ docker network connect NETWORK_NAME CONTAINER_NAME
# Verify the `CONTAINER_NAME` is added to the `Containers` field of the network:
$ docker inspect NETWORK_NAME --type network
Check by docker network ls
Name | Driver | Note |
---|---|---|
bridge | bridge | Docker's default |
kind | bridge | kind's default |
host | host | no network isolation |
none | null |
DRIVER:
null
: the container does not have external network interfaces, only a local loopback interface.host
: the container is attached to the host's network, the configs inside the container matches the configs outside the container.bridge
: containers connected to the same bridge network can communicate; containers on different bridge networks cannot communicate directly with each other.
To get more details:
$ docker network inspect bridge
Containers Networking Options
- container to container on the same node (the same Docker daemon host): through a
bridge
network - container to container on different nodes: through a
overlay
network - container to outside world:
--publish or -p <hostport>:<containerport>
DNS
Inherit /etc/resolv.conf
on the host, but can override per-container in docker run
/ docker create
using the flags: --dns
, --dns-search
, --dns-opt
, --hostname
.
Isolation
On Linux, Docker manipulates iptables
rules to provide network isolation.
credHelper
credHelpers
can be set in ~/.docker/config.json
"credHelpers": {
"gcr.io": "gcloud"
}
It means any image pull from gcr.io
will use the binary docker-credential-gcloud
to get the username and secret. (The binary = docker-credential-
+ suffix.)
$ echo gcr.io | docker-credential-gcloud get
To login:
$ docker login 10.200.0.1 -u admin -p ${REGISTRY_PASSWORD}
Configurations and Files
Docker Root Dir (used by the docker daemon to keep track of the state).
/var/lib/docker/
, e.g./var/lib/docker/overlay2
: image and container layers./var/lib/docker/volumes
Server ("Rootful"):
dockerd
(daemon) config:/etc/docker/daemon.json
- Socket:
/var/run/docker.sock
Server (Rootless Mode):
dockerd
(daemon) config:~/.config/docker
- Socket:
$XDG_RUNTIME_DIR/docker.sock
$XDG_RUNTIME_DIR
is typically set to/run/user/$UID
- Data dir:
~/.local/share/docker
by default
Client:
~/.docker/config.json
is for thedocker
CLI.
Registry:
- config:
/etc/registry/config.yaml
- storage:
/var/lib/registry
Dockerfile
CMD vs ENTRYPOINT
Both CMD
and ENTRYPOINT
instructions define what command gets executed when running a container. There are few rules that describe their co-operation.
- Dockerfile should specify at least one of
CMD
orENTRYPOINT
commands. ENTRYPOINT
should be defined when using the container as an executable.CMD
should be used as a way of defining default arguments for anENTRYPOINT
command or for executing an ad-hoc command in a container.CMD
will be overridden when running the container with alternative arguments.
Example: Containerize a Node app
Use this Dockerfile
template:
# node
FROM node:12-slim
# the path inside the container
WORKDIR /usr/src/app
# copy the package.json and package-lock.json, and install dependencies
COPY package*.json ./
RUN npm install
# copy all the source code
COPY . .
# port
EXPOSE 8080
# run the command inside the container
CMD [ "node", "app.js" ]
And add a .dockerignore
file:
Dockerfile
.dockerignore
node_modules
npm-debug.log
FAQ
What is Docker?
When we talk about Docker, usually we are referring to Docker Engine, which consists of
- the Docker daemon (
dockerd
). - a REST API that specifies interfaces for interacting with the daemon.
- a command line interface (CLI) client (
docker
) that talks to the daemon (through the REST API wrapper), e.g.docker run <image>
,docker image ls
.
Because Docker operates at the OS level, it can still be run inside a VM.
2 most important APIs: Images and Container APIs.
What's the virtual size?
virtual = image size + container layers size.
Docker Compose vs Docker Stack vs Swarm
docker compose
: a tool for defining and running multi-container Docker applications; v1 (the separate binarydocker-compose
was deprecated), v2 is a subcommandcompose
in thedocker
CLI.docker stack
: Manage Swarm stacks.- both works with
docker-compose.yml
, howeverdocker stack
only works with version 3. - Swarm: a cluster of Docker daemons. Now
swarm
is also a subcommand ofdocker
CLI. Compose: multiple containers on the same host (daemon).
import vs load
import
is used with the tarball which are created withdocker export
.load
is used with the tarball which are created withdocker save
.
Docker for Mac
The Docker for Mac application does not use docker-machine to provision that VM; but rather creates and manages it directly.
Rootless Mode
Allows running the dockerd
and containers as a non-root user to mitigate potential vulnerabilities in the daemon and the container runtime.
Rootless mode executes the Docker daemon and containers inside a user namespace.
Specify CLI context:
$ docker context use rootless
root vs rootless:
- root:
DOCKER_HOST
defaults tounix:///var/run/docker.sock
(allows only local connections by the root user). - rootless:
export DOCKER_HOST=unix://${XDG_RUNTIME_DIR}/docker.sock
, e.g.unix:///run/user/123456/docker.sock
Storage
Storage Options
- Storage Driver: for writing ephemeral data in container's writable layer, at a lower speed.
- can also use
tmpfs mount
for ephemeral data to avoid writing into the container’s writable layer, which increases container's performance.
- can also use
- Volume: for write-intensive application, persistent data, shared data; better performance. The data is stored in Docker's storage directory (unlike bind mount below, which can be any absolute path on the host machine).
- a volume doesn’t increase the size of the containers using it
- Bind Mount: a file or directory on the host machine is mounted into a container. Similar to
hostpath
in k8s.
Overlay: lower vs upper vs merged
lower
: Image layers, read-only.upper
: Container layers, read-write. Each running containers has a thin read-write layer. Do not persiste after the container is deleted.merged
: the union mount of the lower and upper. If a name exists in both, the object in 'upper' is visible while the object in 'lower' is hidden or merged.
Storage Driver
Storage Driver:
- controls how images and containers are stored and managed on your Docker host.
- allows you to write to the container’s writable layer.
Check which storage driver is being used:
$ docker info
...
Server:
Containers: 24
Images: 507
Storage Driver: overlay2
Backing Filesystem: extfs
...
Storage Driver - Overlay2
overlay2
is the preferred storage driver.
OverlayFS is a feature provided by Linux Kernel.
OverlayFS layers multiple directories on a single Linux host and presents them as a single directory.
Layers can be found in /var/lib/docker/overlay2
- Each image and container layer has its own folder.
- the special
l
directory contains shortened layer identifiers as symbolic links, to avoid hitting the page size limitation on arguments to themount
command.ls -l /var/lib/docker/overlay2/l
Check mounts: mount | grep overlay
Backing filesystem: ext4
or xfs
.
Build
docker can build a docker image or an OCI image:
docker buildx build --output type=oci .
docker buildx build --output type=docker .
docker build vs docker buildx build
2 Docker build commands:
docker build
: the legacy builder; always takes a copy of the local filesystem.docker buildx build
: Extended build capabilities with BuildKit.- BuildKit has been integrated to docker build since Docker 18.09.
- BuildKit only requests the resources that the build needs, when they're needed.
- A drop-in replacement for the legacy build.
- In newer versions of Docker Desktop and Docker Engine, you're using Buildx by default when you invoke the docker build command.
BuildKit, or buildkitd
, is the daemon process that executes the build workloads. A build execution starts with the invocation of a docker build command. Buildx interprets your build command and sends a build request to the BuildKit backend.
# List builder (will show BUILDKIT version)
$ docker buildx ls
# Inspect builder
$ docker buildx inspect $BUILD_NAME
$ docker buildx inspect default