Happy Dussehra! May good always win. Happy Diwali! Wishing you a bright year ahead. Merry Christmas! Warm wishes from Vizag. Happy New Year! Here’s to a great year ahead.

Archive · Docker

Installing Docker on Ubuntu 20.04

Install Docker Engine from the official repository, run it as a service, give users access safely, set sane logging defaults and verify the installation.

3 min read

  • Ubuntu 20.04 LTS
  • Docker Engine 19.03.8
  • containerd
  • overlay2

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-file driver never rotates, and a chatty container can fill the disk. Limits apply to containers created after the change.
  • live-restore keeps 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/16 is the default bridge).

Security and operations basics

  1. 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.
  2. Remember that published ports bypass ufw: Docker inserts its own iptables rules, so -p 8080:80 is 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.
  3. Put /var/lib/docker on a volume with room to grow; images, layers and volumes live there. Watch it with docker system df.
  4. Pin image versions; avoid latest in anything you deploy.
  5. Update with sudo apt update && sudo apt upgrade; with live-restore enabled, 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.