Docker packages applications and their dependencies into containers that start in seconds and run the same on a laptop, a CI runner and a server. This post installs Docker Engine on a fresh Ubuntu 20.04 LTS server (released 23 April 2020) and sets it up so it is safe to leave running.
Versions in use on this date. Docker Engine 19.03.8 (the 19.03.9 patch is due in the same week). Ubuntu 20.04 also provides its own docker.io package (19.03.8), which is fine for labs; the Docker-maintained docker-ce repository gets releases faster and is what most guides and vendors assume.
What gets installed
flowchart TB
CLI[docker CLI] -->|REST over /var/run/docker.sock| D[dockerd daemon]
D --> C[containerd]
C --> R[runc creates containers]
D --> IMG[(Images and layers<br/>/var/lib/docker overlay2)]
D --> NET[Bridge network docker0<br/>iptables rules]
R --> CT[Container processes<br/>namespaces and cgroups]
D <-->|pull and push| REG[Docker Hub or private registry]
The daemon runs as root and listens on a Unix socket. Anyone who can talk to that socket effectively has root on the host, which matters for the next steps.
Install from the Docker repository
sudo apt update
sudo apt install -y apt-transport-https ca-certificates curl gnupg lsb-release
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" \
| sudo tee /etc/apt/sources.list.d/docker.list
sudo apt update
apt-cache policy docker-ce | head
sudo apt install -y docker-ce docker-ce-cli containerd.io
On a brand-new release, the Docker repository sometimes lags behind for the newest Ubuntu codename. If apt update reports no focal packages, either use the Ubuntu package (sudo apt install docker.io) until the repository catches up, or use bionic as the repository suite temporarily. Check the Docker documentation for the current status.
Verify
sudo systemctl status docker --no-pager
sudo docker version
sudo docker info | grep -E 'Storage Driver|Cgroup|Server Version'
sudo docker run --rm hello-world
Expect Storage Driver: overlay2. hello-world proves that the daemon can pull from Docker Hub and start a container.
Allow your user (and understand the risk)
sudo usermod -aG docker $USER
newgrp docker # or log out and in
docker ps
Members of the docker group can start a container that mounts the host’s root filesystem, so the group is equivalent to root. Add only administrators. Docker 19.03 also offers rootless mode as an experimental feature; it is not ready for most production uses yet.
Daemon settings worth setting on day one
/etc/docker/daemon.json:
{
"log-driver": "json-file",
"log-opts": { "max-size": "10m", "max-file": "3" },
"live-restore": true,
"default-address-pools": [{ "base": "172.30.0.0/16", "size": 24 }]
}
sudo systemctl restart docker
- Log limits: by default the
json-filedriver never rotates, and a chatty container can fill the disk. Limits apply to containers created after the change. live-restorekeeps containers running while the daemon restarts for upgrades.- Address pools avoid clashes between Docker networks and your corporate or VPN ranges (
172.17.0.0/16is the default bridge).
Security and operations basics
- Do not expose the daemon over TCP (
-H tcp://0.0.0.0:2375); that is an unauthenticated root shell for the network. If remote access is needed, use SSH (DOCKER_HOST=ssh://user@host, supported in 18.09 and later) or TLS client certificates. - Remember that published ports bypass ufw: Docker inserts its own iptables rules, so
-p 8080:80is open to the world even if ufw denies it. Publish to loopback (-p 127.0.0.1:8080:80) when only a reverse proxy should reach it. - Put
/var/lib/dockeron a volume with room to grow; images, layers and volumes live there. Watch it withdocker system df. - Pin image versions; avoid
latestin anything you deploy. - Update with
sudo apt update && sudo apt upgrade; withlive-restoreenabled, running containers survive.
Uninstall or reset
sudo apt purge docker-ce docker-ce-cli containerd.io
sudo rm -rf /var/lib/docker /var/lib/containerd # deletes ALL images, containers and volumes
Copy any volume data you care about first. The next post walks through the first ten commands you will use daily.