
Install and Use Docker Compose on Ubuntu 24 – Hosting Setup
Docker Compose is an essential tool for orchestrating multi-container Docker applications, allowing developers to define and manage complex application stacks using simple YAML configuration files. On Ubuntu 24, setting up Docker Compose properly is crucial for development environments, staging servers, and production deployments. This guide will walk you through the complete installation process, basic usage patterns, troubleshooting common issues, and practical hosting scenarios that you’ll encounter when managing containerized applications on your Ubuntu server.
Understanding Docker Compose Architecture
Docker Compose operates as a wrapper around the Docker engine, interpreting YAML configuration files to orchestrate multiple containers as a single application stack. Unlike running individual Docker containers manually, Compose manages networking, volumes, environment variables, and dependencies between services automatically.
The tool works by reading a docker-compose.yml
file that defines services, networks, and volumes. When you execute compose commands, it translates these definitions into Docker API calls, creating and managing containers according to your specifications. Each service in your compose file becomes one or more containers, and Compose handles the networking between them using Docker’s built-in networking capabilities.
Installation Methods on Ubuntu 24
Ubuntu 24 offers several approaches for installing Docker Compose, each with different advantages depending on your specific needs and environment setup.
Method 1: Installing via Docker’s Official Repository
This method provides the most up-to-date version directly from Docker’s maintained repositories:
# Update package index
sudo apt update
# Install required packages for HTTPS repository access
sudo apt install apt-transport-https ca-certificates curl gnupg lsb-release
# Add Docker's official GPG key
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
# Add Docker repository
echo "deb [arch=$(dpkg --print-architecture) 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 > /dev/null
# Update package index again
sudo apt update
# Install Docker Engine and Docker Compose
sudo apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin
Method 2: Standalone Binary Installation
For environments where you need more control over the specific version or prefer manual installation:
# Download the latest stable release
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# Make the binary executable
sudo chmod +x /usr/local/bin/docker-compose
# Create symbolic link for easier access
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
Method 3: Installation via Python pip
This approach works well in Python-heavy environments but requires additional dependency management:
# Install Python pip if not already available
sudo apt install python3-pip
# Install Docker Compose via pip
pip3 install docker-compose
# Add local bin to PATH if needed
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
Verification and Initial Configuration
After installation, verify that Docker Compose is working correctly and configure user permissions for non-root usage:
# Check Docker Compose version
docker-compose --version
# Verify Docker service status
sudo systemctl status docker
# Add current user to docker group (eliminates need for sudo)
sudo usermod -aG docker $USER
# Apply group membership (requires logout/login or newgrp)
newgrp docker
# Test Docker without sudo
docker run hello-world
Basic Docker Compose Usage Patterns
Understanding fundamental Compose patterns will help you build more complex applications. Here’s a practical example that demonstrates core concepts:
# Create project directory
mkdir my-web-app && cd my-web-app
# Create docker-compose.yml
cat > docker-compose.yml << EOF
version: '3.8'
services:
web:
image: nginx:alpine
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html
depends_on:
- api
environment:
- NGINX_HOST=localhost
- NGINX_PORT=80
api:
image: node:16-alpine
working_dir: /app
volumes:
- ./api:/app
ports:
- "3000:3000"
command: npm start
environment:
- NODE_ENV=development
- DB_HOST=database
database:
image: postgres:13
environment:
- POSTGRES_DB=myapp
- POSTGRES_USER=developer
- POSTGRES_PASSWORD=secure_password
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "5432:5432"
volumes:
postgres_data:
networks:
default:
driver: bridge
EOF
Essential commands for managing this stack:
# Start all services in background
docker-compose up -d
# View running services
docker-compose ps
# Check service logs
docker-compose logs web
docker-compose logs -f api # Follow log output
# Scale specific services
docker-compose up -d --scale api=3
# Stop all services
docker-compose down
# Stop and remove volumes
docker-compose down -v
Real-World Hosting Examples
These examples demonstrate practical hosting scenarios you'll encounter when deploying applications using Docker Compose on Ubuntu servers.
WordPress with MySQL and Redis
version: '3.8'
services:
wordpress:
image: wordpress:latest
restart: unless-stopped
ports:
- "80:80"
environment:
WORDPRESS_DB_HOST: mysql
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: ${MYSQL_PASSWORD}
WORDPRESS_DB_NAME: wordpress
volumes:
- wordpress_data:/var/www/html
depends_on:
- mysql
- redis
mysql:
image: mysql:8.0
restart: unless-stopped
environment:
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
volumes:
- mysql_data:/var/lib/mysql
command: '--default-authentication-plugin=mysql_native_password'
redis:
image: redis:alpine
restart: unless-stopped
command: redis-server --appendonly yes
volumes:
- redis_data:/data
volumes:
wordpress_data:
mysql_data:
redis_data:
Development Stack with Hot Reloading
version: '3.8'
services:
frontend:
build:
context: ./frontend
dockerfile: Dockerfile.dev
ports:
- "3000:3000"
volumes:
- ./frontend:/app
- /app/node_modules
environment:
- REACT_APP_API_URL=http://localhost:8000
backend:
build:
context: ./backend
dockerfile: Dockerfile.dev
ports:
- "8000:8000"
volumes:
- ./backend:/app
environment:
- DEBUG=1
- DATABASE_URL=postgresql://dev:dev@postgres:5432/devdb
depends_on:
- postgres
postgres:
image: postgres:13
environment:
POSTGRES_DB: devdb
POSTGRES_USER: dev
POSTGRES_PASSWORD: dev
volumes:
- postgres_dev_data:/var/lib/postgresql/data
volumes:
postgres_dev_data:
Performance Optimization and Best Practices
Optimizing Docker Compose deployments involves several considerations that directly impact application performance and resource utilization.
Optimization Area | Default Behavior | Optimized Approach | Performance Impact |
---|---|---|---|
Image Size | Full OS images | Alpine-based images | 50-80% size reduction |
Build Caching | No cache optimization | Multi-stage builds | 60-90% faster builds |
Resource Limits | Unlimited resources | CPU/Memory limits | Better resource allocation |
Network Mode | Bridge networking | Host networking (when appropriate) | 10-15% network performance |
Key optimization techniques:
- Use multi-stage Dockerfiles to minimize final image size
- Implement health checks for better service management
- Configure resource limits to prevent resource exhaustion
- Use named volumes for persistent data instead of bind mounts in production
- Implement proper logging drivers to manage log file growth
# Example optimized service configuration
services:
web:
image: nginx:alpine
restart: unless-stopped
deploy:
resources:
limits:
memory: 256M
cpus: '0.5'
reservations:
memory: 128M
cpus: '0.25'
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/health"]
interval: 30s
timeout: 10s
retries: 3
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
Common Issues and Troubleshooting
Docker Compose deployments frequently encounter specific issues that can disrupt service availability. Understanding these problems and their solutions will save significant debugging time.
Permission and Volume Issues
Volume mounting problems often arise from incorrect permissions or ownership conflicts:
# Fix common permission issues
# Check current ownership
ls -la /path/to/volume
# Fix ownership for web applications
sudo chown -R www-data:www-data /path/to/web/files
sudo chmod -R 755 /path/to/web/files
# For database volumes
sudo chown -R 999:999 /path/to/postgres/data
# Set proper SELinux context if enabled
sudo chcon -Rt svirt_sandbox_file_t /path/to/volume
Network Connectivity Problems
Services unable to communicate often indicate network configuration issues:
# Debug network connectivity
docker-compose exec web ping api
docker-compose exec api nslookup database
# List networks
docker network ls
# Inspect specific network
docker network inspect $(docker-compose ps -q | head -1 | xargs docker inspect --format='{{range .NetworkSettings.Networks}}{{.NetworkID}}{{end}}')
# Manual network creation for complex setups
docker network create --driver bridge my-network
Resource Exhaustion Issues
Monitor and address resource constraints that can cause service failures:
# Monitor resource usage
docker stats
# Check disk usage by containers
docker system df
# Clean up unused resources
docker system prune -a
# Remove unused volumes
docker volume prune
# Identify resource-heavy containers
docker-compose top
Environment-Specific Configuration
Managing different environments requires structured approaches to configuration management. Use environment files and override configurations for flexibility:
# Create .env file for sensitive data
cat > .env << EOF
MYSQL_ROOT_PASSWORD=super_secure_root_password
MYSQL_PASSWORD=secure_app_password
REDIS_PASSWORD=redis_secure_password
DOMAIN_NAME=yourdomain.com
EOF
# Production override file (docker-compose.prod.yml)
version: '3.8'
services:
web:
restart: unless-stopped
deploy:
replicas: 2
resources:
limits:
memory: 512M
logging:
driver: "syslog"
options:
syslog-address: "tcp://logs.yourdomain.com:514"
database:
restart: unless-stopped
volumes:
- /backup/mysql:/backup:ro
# Deploy using override
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
Integration with CI/CD and Hosting Platforms
Docker Compose integrates seamlessly with continuous integration workflows and hosting environments. For VPS deployments, automated deployment scripts can significantly streamline your workflow:
#!/bin/bash
# deploy.sh - Automated deployment script
set -e
# Pull latest changes
git pull origin main
# Build and deploy with zero downtime
docker-compose pull
docker-compose up --build -d --remove-orphans
# Clean up unused images
docker image prune -f
# Verify deployment
docker-compose ps
curl -f http://localhost/health || exit 1
echo "Deployment completed successfully"
For more resource-intensive applications requiring dedicated hardware, dedicated server hosting provides the performance and isolation necessary for production Docker Compose deployments.
Security Considerations and Hardening
Securing Docker Compose deployments requires attention to multiple layers, from container isolation to network security:
- Never store secrets in docker-compose.yml files; use environment variables or Docker secrets
- Run containers with non-root users whenever possible
- Use specific image tags instead of 'latest' for production deployments
- Implement network segmentation using custom networks
- Regularly update base images to patch security vulnerabilities
- Enable Docker Content Trust for image signature verification
# Example security-hardened service
services:
app:
image: myapp:1.2.3 # Specific version, not 'latest'
user: "1000:1000" # Non-root user
read_only: true # Read-only filesystem
tmpfs:
- /tmp
- /var/cache
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE
security_opt:
- no-new-privileges:true
networks:
- frontend
secrets:
- db_password
secrets:
db_password:
file: ./secrets/db_password.txt
networks:
frontend:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/24
Docker Compose on Ubuntu 24 provides a robust foundation for containerized application deployment. The installation process is straightforward, but success depends on understanding the underlying concepts, following security best practices, and implementing proper monitoring and maintenance procedures. Regular updates, resource monitoring, and backup strategies ensure reliable long-term operation of your containerized services.
For additional information and advanced configuration options, consult the official Docker Compose documentation and the Docker Engine installation guide for Ubuntu.

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.