Containers
High level comparison
docker | crictl | podman | |
---|---|---|---|
Build images | Yes | No | Yes |
Run / Inspect | Yes | Yes | Yes |
Talk to daemon | Yes (dockerd ) |
Yes (CRI-compatible runtimes) | NO (daemonless) |
Privilege | root or rootless | rootless | |
Run Pods | No | Yes | Yes |
Used by | k8s | kind |
Notes:
- All compatible with OCI specs.
podman build
uses code sourced from the Buildah project to build container images. Both podman and Buildah are from RedHat.- Other tools:
buildx
is a Docker CLI plugin for extended build capabilities with BuildKit.runc
: the low-level runtime, usually we do not need to work with directly.
Commands
Inpect Images / Containers:
docker | crictl | |
---|---|---|
List images | docker images |
crictl images |
List containers | docker ps |
crictl ps |
Attach to a running container | docker attach |
crictl attach |
Run a command in a container | docker exec |
crictl exec |
Show system-wide info | docker info |
crictl info |
Show container, image info | docker inspect |
crictl inspect |
Get logs of a container | docker logs |
crictl logs |
Show resource usage stats | docker stats |
crictl stats |
Show rutime version | docker version |
crictl version |
Image / Container Lifecycle:
docker | crictl | |
---|---|---|
Pull an image | docker pull |
crictl pull |
Create a container | docker create |
crictl create |
Run commands | docker run |
crictl run |
Start containers | docker start |
crictl start |
Stop containers | docker stop |
crictl stop |
Update configs | docker update |
crictl update |
Remove containers | docker rm |
crictl rm |
Remove images | docker rmi |
crictl rmi |
Kill containers | docker kill |
crictl stop |
Pod Lifecycle:
crictl | |
---|---|
List pods | crictl pods |
Run a pod | crictl runp |
Remove pods | crictl rmp |
Stop pods | crictl stopp |
Show status of the pods | crictl inspectp |
Forward local port to a pod | crictl port-forward |
Docker examples
# Run Docker Engine
$ sudo dockerd
# 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
# 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
Registries
$ docker login <registry_address>
# pull
$ docker pull <registry_address>/library/ubuntu:22.04
# push
$ docker tag ubuntu:22.04 <registry_address>/demo/ubuntu:22.04
$ docker push <registry_address>/demo/ubuntu:22.04
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}
Build
Choose image format
# Build OCI images (default for podman)
$ podman build --format=oci
# Build Docker images instead
$ podman build --format=docker
# Similarly in `docker buildx`
$ docker buildx build --output type=oci
$ docker buildx build --output type=docker
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
Networking
# List networks
$ docker network ls
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
runc
Most likely you do not need to use runc
directly, but you can get more info about the running containers:
$ runc list
$ ls /run/runc
$ cat /run/runc/<name>/state.json
containerd
# containerd view logs
$ journalctl -u containerd
ctr
vs crictl
:
ctr
: containerd CLI, not related to k8s.crictl
: CRI Compatible container runtime command line interface, related to k8s.
crictl image
= ctr -n=k8s.io images ls
kind load
uses "ctr", "--namespace=k8s.io", "images", "import", "--digests", "--snapshotter="+snapshotter, "-"
Others
The new docker sbom
CLI command displays 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.
Check docker info: docker info
Check if dockerd is running: sudo systemctl status docker