Docker is a containerization platform: an application is packaged together with its environment and dependencies into an image, from which isolated containers are spun up. The same image deploys identically on any Linux machine.
The scenario of this article: a web container with nginx on host port 8080,
plus a database in Compose.
Installation (Ubuntu)#
The official Docker repository:
# Repository signing key
sudo apt update
sudo apt install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Repository (deb822 format)
sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF
# Install the engine and plugins (including Compose)
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
The package from the Ubuntu distribution (apt install docker.io) is a
legitimate but usually lagging alternative.
Permissions: working without sudo#
The daemon listens on a unix socket accessible to the docker group:
sudo usermod -aG docker $USER
A reboot is not needed — re-login is enough (or newgrp docker in the
current session). Check:
docker run hello-world
Members of the
dockergroup effectively have root access to the host (a host root/mount into a container is possible) — grant it only to people you would trust as root.
Containers#
# Run web: nginx from host 8080 to container 80, name web (-d — in background)
docker run -d --name web -p 8080:80 nginx
# What is running now / everything, including stopped ones
docker ps
docker ps -a
# Logs (follow: -f)
docker logs web
# Stop / start / restart
docker stop web
docker start web
docker restart web
# Into a running container — a shell
docker exec -it web bash
# One-off container: kill on exit (--rm)
docker run -it --rm ubuntu bash
# Remove a stopped container
docker rm web
The
webname is used in all commands instead of the long ID.--rm— for one-off tasks; named containers — for services.
Images#
# Download an image from Docker Hub
docker pull nginx
# Local images
docker images
# Build from the Dockerfile in the current directory
docker build -t my-app .
# Remove an image
docker rmi nginx
Networks#
# A user-defined network
docker network create my-network
# List networks
docker network ls
# Run a container in this network
docker run -d --name web --network my-network nginx
# Remove a network
docker network rm my-network
Inside a user-defined network containers resolve by name:
webis reachable from neighbours simply ashttp://web:80— without digging for IPs. The default bridge network has no such DNS.
Volumes#
# Create a named volume
docker volume create app-data
# List volumes
docker volume ls
# Attach a volume to a container
docker run -d --name web -v app-data:/var/lib/nginx nginx
# Remove
docker volume rm app-data
A volume (
-v app-data:/path) lives separately from the container — data survives container removal. Binding a host directory works the same way:-v ./html:/usr/share/nginx/html(bind mount).
Docker Compose#
Compose describes a multi-container application in a single YAML — the
composition, networks, volumes and variables. compose.yaml (v2: the
version section is no longer needed):
services:
web:
image: nginx
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html
db:
image: postgres
environment:
POSTGRES_PASSWORD: example
Commands (the modern CLI — docker compose as two words, a plugin from the
installation above; hyphenated docker-compose is legacy v1):
# Bring the whole application up in background
docker compose up -d
# What is running
docker compose ps
# Logs (follow: -f) for one service or all
docker compose logs -f web
# Rebuild images after Dockerfile edits
docker compose build
# A shell inside a service
docker compose exec web bash
# Stop and remove containers/networks
docker compose down
# The same, but wiping volume data too
docker compose down --volumes
docker compose downdoes not touch volumes — databases survive restarts; to wipe the data too, add--volumes. Compose services resolve by name inside the user-defined network that Compose creates itself.