Docker Compose has fundamentally changed how developers approach containerized applications, particularly when coordinating services that depend on one another. This tool replaces manual container management with a structured YAML-driven workflow, enabling teams to define entire application architectures in a single configuration file.
For Ubuntu environments, this translates to reproducible deployments, simplified scaling, and reduced operational overhead. This guide provides a fresh perspective on Docker Compose installation and usage, offering deeper insights into its practical implementation.
Before you begin this tutorial, you'll need a few things in place:
sudo
privileges or root
access. This allows you to install packages and manage Docker.Modern applications often involve interconnected components like APIs, databases, and caching layers. Managing these elements individually with Docker commands becomes cumbersome as complexity grows. Docker Compose addresses this by allowing developers to declare all services, networks, and storage requirements in a docker-compose.yml
file. This approach ensures consistency across environments—whether you’re working on a local Ubuntu machine or a cloud server.
For example, consider a web application comprising a Node.js backend, PostgreSQL database, and Redis cache. Without Docker Compose, each component requires separate docker run
commands with precise networking flags. With Compose, these relationships are organized once, enabling one-command setups and teardowns.
Follow these steps to install Docker Compose on your Ubuntu machine:
Docker Compose functions as an extension of Docker, so verify its status with:
sudo systemctl status docker
Example output:
● docker.service - Docker Application Container Engine
Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
Active: active (running) since Thu 2025-02-20 08:55:04 GMT; 5min ago
TriggeredBy: ● docker.socket
Docs: https://docs.docker.com
Main PID: 2246435 (dockerd)
Tasks: 9
Memory: 53.7M
CPU: 304ms
CGroup: /system.slice/docker.service
└─2246435 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
If inactive, start it using sudo systemctl start docker
.
Refresh your package lists to ensure access to the latest software versions:
sudo apt-get update
You will see:
Hit:1 https://download.docker.com/linux/ubuntu jammy InRelease
Hit:2 http://archive.ubuntu.com/ubuntu jammy InRelease
Hit:4 http://security.ubuntu.com/ubuntu jammy-security InRelease
Hit:5 http://repo.hostman.com/ubuntu focal InRelease
Hit:6 http://archive.ubuntu.com/ubuntu jammy-updates InRelease
Hit:7 http://archive.ubuntu.com/ubuntu jammy-backports InRelease
Hit:3 https://prod-cdn.packages.k8s.io/repositories/isv:/kubernetes:/core:/stable:/v1.31/deb InRelease
Hit:8 https://packages.redis.io/deb jammy InRelease
Reading package lists... Done
Secure communication with Docker’s repositories requires these packages:
sudo apt-get install ca-certificates curl
Authenticate Docker packages by adding their cryptographic key:
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
This step ensures packages haven’t been altered during transit.
Add the repository tailored to your Ubuntu version:
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
The command auto-detects your OS version using VERSION_CODENAME
.
Update repositories and install the Compose extension:
sudo apt update
sudo apt-get install docker-compose-plugin
Confirm successful setup with:
docker compose version
The output displays the Docker Compose version:
Docker Compose version v2.33.0
Let’s deploy a web server using Nginx to demonstrate Docker Compose’s capabilities.
Create a dedicated workspace:
mkdir ~/compose-demo && cd ~/compose-demo
Create the configuration file:
nano docker-compose.yml
Insert the following content:
services:
web:
image: nginx:alpine
ports:
- "8080:80"
volumes:
- ./app:/usr/share/nginx/html
In the above YAML file:
services
: Root element declaring containers.web
: Custom service name.image
: Uses the Alpine-based Nginx image for reduced footprint.ports
: Maps host port 8080 to container port 80.volumes
: Syncs the local app directory with the container’s web root.Build the HTML structure:
mkdir app
nano app/index.html
Add this HTML snippet:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Docker Compose Test</title>
</head>
<body>
<h1>Hello from Docker Compose!</h1>
</body>
</html>
Let’s explore how you can use Docker Compose for container orchestration:
Launch containers in the background:
docker compose up -d
Example output:
[+] Running 2/2
✔ Network compose-demo_default Created
✔ Container compose-demo-web-1 Started
Docker Compose automatically pulls the Nginx image if missing and configures networking.
Check operational containers:
docker compose ps -a
Visit http://localhost:8080
locally or http://<SERVER_IP>:8080
on remote servers. The test page should display your HTML content.
If the page doesn’t load or if you encounter any issues, you can inspect container logs:
docker compose logs web
Example output:
web-1 | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
web-1 | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
web-1 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
web-1 | 10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
web-1 | 10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
web-1 | /docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh
…
Stop containers temporarily:
docker compose stop
Example output:
[+] Stopping 1/1
✔ Container compose-demo-web-1 Stopped
Remove all project resources:
docker compose down
Example output:
[+] Running 2/2
✔ Container compose-demo-web-1 Removed
✔ Network compose-demo_default Removed
While the workflow above covers fundamentals, these commands enhance container management:
docker compose up --build
: Rebuild images before starting containers.docker compose pause
: Freeze containers without terminating them.docker compose top
: Display running processes in containers.docker compose config
: Validate and view the compiled configuration.docker compose exec
: Execute commands in running containers (e.g., docker compose exec web nginx -t
tests Nginx’s configuration).Docker Compose transforms multi-container orchestration from a manual chore into a streamlined, repeatable process. By adhering to the steps outlined—installing Docker Compose, defining services in YAML, and leveraging essential commands—you can manage complex applications with confidence.