
How to Install and Use Docker Compose on Ubuntu 24
Docker Compose is a powerful orchestration tool that simplifies the deployment and management of multi-container Docker applications. By defining your entire application stack in a single YAML file, you can spin up complex environments with multiple interconnected services using just one command. This guide will walk you through installing Docker Compose on Ubuntu 24, demonstrate practical usage scenarios, and share troubleshooting tips that’ll save you from the common headaches most developers encounter when first diving into container orchestration.
Understanding Docker Compose and Its Architecture
Docker Compose sits on top of Docker Engine and provides a declarative way to define multi-container applications. Unlike running individual Docker containers with lengthy docker run commands, Compose uses a docker-compose.yml file to specify services, networks, and volumes in a structured format.
The tool operates on three core concepts:
- Services: Individual containers that make up your application (web server, database, cache, etc.)
- Networks: Virtual networks that allow containers to communicate securely
- Volumes: Persistent storage that survives container restarts and updates
When you run docker compose up, the tool reads your configuration file, creates the necessary networks and volumes, then starts all services in the correct order based on their dependencies.
Installing Docker Compose on Ubuntu 24
Ubuntu 24 ships with updated package repositories, making Docker Compose installation straightforward. There are two primary installation methods: using the official Docker repository (recommended) or installing via pip.
Method 1: Official Docker Repository Installation
First, update your package index and install prerequisite packages:
sudo apt update
sudo apt install ca-certificates curl gnupg lsb-release
Add Docker’s official GPG key and repository:
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
Install Docker Engine and Docker Compose:
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin
Verify the installation:
docker compose version
Method 2: Standalone Binary Installation
For environments where you prefer standalone binaries or need the latest version immediately:
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
Post-Installation Configuration
Add your user to the docker group to run Docker commands without sudo:
sudo usermod -aG docker $USER
newgrp docker
Test the installation with a simple hello-world container:
docker run hello-world
Real-World Implementation Examples
Example 1: LAMP Stack with WordPress
Here’s a practical docker-compose.yml file for a WordPress development environment:
version: '3.8'
services:
wordpress:
image: wordpress:latest
ports:
- "8080:80"
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: wpuser
WORDPRESS_DB_PASSWORD: wppassword
WORDPRESS_DB_NAME: wordpress
volumes:
- wordpress_data:/var/www/html
depends_on:
- db
networks:
- wp_network
db:
image: mysql:8.0
environment:
MYSQL_DATABASE: wordpress
MYSQL_USER: wpuser
MYSQL_PASSWORD: wppassword
MYSQL_ROOT_PASSWORD: rootpassword
volumes:
- db_data:/var/lib/mysql
networks:
- wp_network
phpmyadmin:
image: phpmyadmin:latest
ports:
- "8081:80"
environment:
PMA_HOST: db
MYSQL_ROOT_PASSWORD: rootpassword
depends_on:
- db
networks:
- wp_network
volumes:
wordpress_data:
db_data:
networks:
wp_network:
driver: bridge
Start the entire stack:
docker compose up -d
Example 2: Development Environment with Hot Reload
For Node.js applications with live reloading:
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile.dev
ports:
- "3000:3000"
volumes:
- .:/app
- /app/node_modules
environment:
- NODE_ENV=development
- CHOKIDAR_USEPOLLING=true
depends_on:
- redis
- postgres
redis:
image: redis:7-alpine
ports:
- "6379:6379"
postgres:
image: postgres:15-alpine
environment:
POSTGRES_DB: devdb
POSTGRES_USER: devuser
POSTGRES_PASSWORD: devpass
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "5432:5432"
volumes:
postgres_data:
Docker Compose vs Alternative Solutions
Feature | Docker Compose | Kubernetes | Docker Swarm | Podman Compose |
---|---|---|---|---|
Learning Curve | Low | High | Medium | Low |
Multi-host Support | No | Yes | Yes | No |
Production Ready | Single host only | Yes | Yes | Limited |
Resource Usage | Low | High | Medium | Low |
Configuration Format | YAML | YAML | YAML | YAML |
Performance Considerations and Best Practices
Docker Compose performance can vary significantly based on your configuration choices:
- Volume Performance: Named volumes typically perform better than bind mounts for database storage
- Network Overhead: Custom networks add minimal latency (< 1ms) but provide better isolation
- Image Size Impact: Alpine-based images start 2-3x faster than full distributions
- Memory Usage: A typical LAMP stack with Compose overhead uses ~200MB base memory
Security Best Practices
Always follow these security guidelines:
- Use environment files (.env) for sensitive data instead of hardcoding secrets
- Run containers as non-root users when possible
- Limit container capabilities with security_opt settings
- Use read-only filesystems for stateless services
- Regularly update base images to patch security vulnerabilities
Example secure configuration:
version: '3.8'
services:
app:
image: node:18-alpine
user: "1000:1000"
read_only: true
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
cap_add:
- CHOWN
- SETGID
- SETUID
tmpfs:
- /tmp
environment:
- NODE_ENV=production
Common Issues and Troubleshooting
Port Conflicts
One of the most frequent issues is port conflicts. Check what’s using a port:
sudo netstat -tulpn | grep :8080
sudo lsof -i :8080
Use different ports in your docker-compose.yml or stop conflicting services.
Permission Issues
If you encounter permission denied errors:
# Check Docker daemon status
sudo systemctl status docker
# Restart Docker service
sudo systemctl restart docker
# Verify group membership
groups $USER
Container Communication Problems
When containers can’t communicate, check network configuration:
# List Docker networks
docker network ls
# Inspect specific network
docker network inspect project_default
# Check container connectivity
docker compose exec service1 ping service2
Volume Mount Issues
For bind mount problems on Ubuntu 24:
# Check SELinux context (if enabled)
ls -Z /path/to/host/directory
# Fix ownership issues
sudo chown -R $USER:$USER ./project-directory
# Check AppArmor logs
sudo dmesg | grep -i apparmor
Advanced Usage Patterns
Multi-Environment Configuration
Use override files for different environments:
# docker-compose.yml (base)
version: '3.8'
services:
app:
image: myapp:latest
environment:
- NODE_ENV=production
# docker-compose.override.yml (development)
version: '3.8'
services:
app:
build: .
volumes:
- .:/app
environment:
- NODE_ENV=development
For production, use a specific override file:
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
Health Checks and Dependencies
Implement proper health checks for reliable startup:
services:
db:
image: postgres:15
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 10s
timeout: 5s
retries: 5
app:
image: myapp:latest
depends_on:
db:
condition: service_healthy
Monitoring and Logging
Set up centralized logging with the ELK stack:
version: '3.8'
services:
app:
image: myapp:latest
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
elasticsearch:
image: elasticsearch:8.5.0
environment:
- discovery.type=single-node
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
logstash:
image: logstash:8.5.0
volumes:
- ./logstash.conf:/usr/share/logstash/pipeline/logstash.conf
kibana:
image: kibana:8.5.0
ports:
- "5601:5601"
Monitor container resource usage:
# Real-time resource monitoring
docker compose top
# Detailed stats
docker stats $(docker compose ps -q)
# Check logs
docker compose logs -f service_name
Integration with CI/CD Pipelines
Docker Compose integrates seamlessly with GitLab CI, GitHub Actions, and Jenkins. Here’s a GitHub Actions example:
name: Deploy with Docker Compose
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Docker Compose
run: |
docker compose --version
- name: Build and test
run: |
docker compose -f docker-compose.test.yml up --build --abort-on-container-exit
- name: Deploy to staging
run: |
docker compose -f docker-compose.staging.yml up -d
For more comprehensive information about Docker Compose features and advanced configurations, check the official Docker Compose documentation.
Docker Compose transforms complex multi-container deployments into simple, reproducible processes. Whether you’re setting up development environments, running integration tests, or managing small-scale production deployments, mastering Compose will significantly streamline your containerization workflow. The key is starting with simple configurations and gradually incorporating advanced features as your infrastructure needs grow.

This article incorporates information and material from various online sources. We acknowledge and appreciate the work of all original authors, publishers, and websites. While every effort has been made to appropriately credit the source material, any unintentional oversight or omission does not constitute a copyright infringement. All trademarks, logos, and images mentioned are the property of their respective owners. If you believe that any content used in this article infringes upon your copyright, please contact us immediately for review and prompt action.
This article is intended for informational and educational purposes only and does not infringe on the rights of the copyright owners. If any copyrighted material has been used without proper credit or in violation of copyright laws, it is unintentional and we will rectify it promptly upon notification. Please note that the republishing, redistribution, or reproduction of part or all of the contents in any form is prohibited without express written permission from the author and website owner. For permissions or further inquiries, please contact us.