Set up a complete Docker development environment with Docker Compose for containerized application development. Install Docker Engine, configure user permissions, and establish efficient development workflows.
Prerequisites
- Root or sudo access
- Internet connection for package downloads
- At least 4GB RAM recommended
- 20GB free disk space
What this solves
This tutorial sets up a complete Docker development environment on Linux with Docker Compose for containerized application development. You'll install Docker Engine, configure proper user permissions, and establish efficient development workflows for building and testing applications locally.
Step-by-step installation
Update system packages
Start by updating your package manager to ensure you get the latest versions and dependencies.
sudo apt update && sudo apt upgrade -y
Install required dependencies
Install packages needed for Docker repository setup and HTTPS transport.
sudo apt install -y ca-certificates curl gnupg lsb-release
Add Docker repository
Add the official Docker repository to get the latest stable version.
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /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
Install Docker Engine, CLI tools, containerd runtime, and Docker Compose plugin.
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Start and enable Docker service
Enable Docker to start automatically on boot and start it immediately.
sudo systemctl enable --now docker
sudo systemctl status docker
Add user to docker group
Add your user to the docker group to run Docker commands without sudo. This avoids permission issues in development workflows.
sudo usermod -aG docker $USER
newgrp docker in your current session.Apply group changes
Apply the new group membership without logging out.
newgrp docker
Configure development environment
Create development directory structure
Set up a organized directory structure for your Docker projects.
mkdir -p ~/docker-projects/{web,databases,services}
cd ~/docker-projects
Create a sample development stack
Create a sample Docker Compose file for a typical web development environment with a database.
version: '3.8'
services:
web:
image: nginx:alpine
container_name: dev-web
ports:
- "8080:80"
volumes:
- ./web:/usr/share/nginx/html
depends_on:
- db
networks:
- dev-network
db:
image: postgres:15-alpine
container_name: dev-db
environment:
POSTGRES_DB: devdb
POSTGRES_USER: developer
POSTGRES_PASSWORD: devpass123
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- dev-network
redis:
image: redis:7-alpine
container_name: dev-redis
ports:
- "6379:6379"
networks:
- dev-network
volumes:
postgres_data:
networks:
dev-network:
driver: bridge
Create sample web content
Create a simple HTML file to test the web server container.
mkdir -p ~/docker-projects/web
Docker Development Environment
Welcome to your Docker development environment!
Your containerized stack is running successfully.
- Web server: Nginx
- Database: PostgreSQL
- Cache: Redis
Configure Docker daemon settings
Optimize Docker daemon for development with improved logging and resource limits.
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
},
"storage-driver": "overlay2",
"default-address-pools": [
{
"base": "172.30.0.0/16",
"size": 24
}
]
}
Restart Docker to apply configuration
Restart the Docker service to apply the new configuration settings.
sudo systemctl restart docker
sudo systemctl status docker
Set up development workflow
Create development helper scripts
Create convenient scripts for common development tasks.
#!/bin/bash
echo "Starting development environment..."
docker compose up -d
echo "Development stack is running!"
echo "Web: http://localhost:8080"
echo "Database: localhost:5432"
echo "Redis: localhost:6379"
chmod +x ~/docker-projects/dev-start.sh
Create cleanup script
Create a script to cleanly stop and remove development containers.
#!/bin/bash
echo "Stopping development environment..."
docker compose down
echo "Cleaning up unused containers and images..."
docker system prune -f
echo "Development environment stopped and cleaned."
chmod +x ~/docker-projects/dev-stop.sh
Create database backup script
Create a script to backup your development database.
#!/bin/bash
BACKUP_DIR="./backups"
BACKUP_FILE="devdb-$(date +%Y%m%d-%H%M%S).sql"
mkdir -p $BACKUP_DIR
echo "Creating database backup..."
docker compose exec -T db pg_dump -U developer devdb > "$BACKUP_DIR/$BACKUP_FILE"
echo "Backup created: $BACKUP_DIR/$BACKUP_FILE"
chmod +x ~/docker-projects/backup-db.sh
Set up development aliases
Add convenient aliases to your shell configuration for common Docker commands.
# Docker development aliases
alias dcu='docker compose up -d'
alias dcd='docker compose down'
alias dcl='docker compose logs -f'
alias dce='docker compose exec'
alias dcp='docker compose ps'
alias dcr='docker compose restart'
Docker cleanup aliases
alias docker-clean='docker system prune -af'
alias docker-clean-volumes='docker volume prune -f'
alias docker-clean-all='docker system prune -af --volumes'
source ~/.bashrc
Verify your setup
Test that Docker and Docker Compose are working correctly with your development stack.
# Check Docker installation
docker --version
docker compose version
Test Docker without sudo
docker run --rm hello-world
Start your development stack
cd ~/docker-projects
./dev-start.sh
Check running containers
docker compose ps
Test web server
curl http://localhost:8080
Test database connection
docker compose exec db psql -U developer -d devdb -c "SELECT version();"
Check logs
docker compose logs web
Common issues
| Symptom | Cause | Fix |
|---|---|---|
| Permission denied when running docker commands | User not in docker group or group changes not applied | newgrp docker or log out and back in |
| Cannot connect to the Docker daemon | Docker service not running | sudo systemctl start docker |
| Port already in use errors | Another service using the same port | Change ports in docker-compose.yml or stop conflicting service |
| Container startup failures | Resource constraints or image pull failures | Check logs with docker compose logs [service] |
| Volume mount permission errors | Incorrect file ownership or permissions | sudo chown -R $USER:$USER ./web and ensure correct permissions |
Next steps
- Deploy FastAPI applications with Docker Compose and production optimization
- Implement container security with AppArmor and seccomp profiles
- Configure container resource limits with Docker and systemd for production workloads
- Set up Docker container monitoring with Prometheus and Grafana
- Configure Docker Compose for multi-environment development workflows
Running this in production?
Automated install script
Run this to automate the entire setup
#!/usr/bin/env bash
set -euo pipefail
# Docker Development Environment Setup Script
# Supports Ubuntu, Debian, AlmaLinux, Rocky Linux, CentOS, RHEL, Oracle Linux, Fedora, Amazon Linux
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# Global variables
SCRIPT_NAME="$(basename "$0")"
USER_NAME="${1:-$USER}"
DOCKER_DIR="$HOME/docker-projects"
# Usage message
usage() {
echo "Usage: $SCRIPT_NAME [username]"
echo " username: User to add to docker group (default: current user)"
exit 1
}
# Logging functions
log_info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# Cleanup function for error handling
cleanup() {
local exit_code=$?
if [ $exit_code -ne 0 ]; then
log_error "Installation failed. Cleaning up..."
sudo systemctl stop docker 2>/dev/null || true
sudo systemctl disable docker 2>/dev/null || true
if [ "$PKG_MGR" = "apt" ]; then
sudo apt remove -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin 2>/dev/null || true
sudo rm -f /etc/apt/sources.list.d/docker.list /etc/apt/keyrings/docker.gpg
else
sudo $PKG_INSTALL remove -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin 2>/dev/null || true
sudo rm -f /etc/yum.repos.d/docker-ce.repo
fi
sudo gpasswd -d "$USER_NAME" docker 2>/dev/null || true
sudo rm -rf /etc/docker/daemon.json
fi
exit $exit_code
}
trap cleanup ERR
# Check prerequisites
check_prerequisites() {
if [ "$EUID" -eq 0 ]; then
log_error "Do not run this script as root. Use a regular user with sudo privileges."
exit 1
fi
if ! command -v sudo >/dev/null 2>&1; then
log_error "sudo is required but not installed."
exit 1
fi
if ! sudo -n true 2>/dev/null; then
log_error "This script requires sudo privileges."
exit 1
fi
if [ "$#" -gt 1 ]; then
usage
fi
if ! id "$USER_NAME" >/dev/null 2>&1; then
log_error "User '$USER_NAME' does not exist."
exit 1
fi
}
# Detect Linux distribution
detect_distro() {
if [ ! -f /etc/os-release ]; then
log_error "Cannot detect Linux distribution. /etc/os-release not found."
exit 1
fi
. /etc/os-release
case "$ID" in
ubuntu|debian)
PKG_MGR="apt"
PKG_INSTALL="apt install -y"
PKG_UPDATE="apt update"
DISTRO_FAMILY="debian"
;;
almalinux|rocky|centos|rhel|ol|fedora)
PKG_MGR="dnf"
PKG_INSTALL="dnf install -y"
PKG_UPDATE="dnf update -y"
DISTRO_FAMILY="rhel"
;;
amzn)
PKG_MGR="yum"
PKG_INSTALL="yum install -y"
PKG_UPDATE="yum update -y"
DISTRO_FAMILY="rhel"
;;
*)
log_error "Unsupported distribution: $ID"
exit 1
;;
esac
log_info "Detected distribution: $PRETTY_NAME"
}
# Update system packages
update_system() {
echo "[1/8] Updating system packages..."
sudo $PKG_UPDATE
log_info "System packages updated successfully"
}
# Install dependencies
install_dependencies() {
echo "[2/8] Installing required dependencies..."
if [ "$DISTRO_FAMILY" = "debian" ]; then
sudo $PKG_INSTALL ca-certificates curl gnupg lsb-release
else
sudo $PKG_INSTALL dnf-plugins-core
fi
log_info "Dependencies installed successfully"
}
# Add Docker repository
add_docker_repo() {
echo "[3/8] Adding Docker repository..."
if [ "$DISTRO_FAMILY" = "debian" ]; then
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/$ID/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/$ID $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
else
if [ "$PKG_MGR" = "yum" ]; then
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
else
sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
fi
fi
log_info "Docker repository added successfully"
}
# Install Docker
install_docker() {
echo "[4/8] Installing Docker Engine and Docker Compose..."
sudo $PKG_INSTALL docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
log_info "Docker Engine and Docker Compose installed successfully"
}
# Configure Docker service
configure_docker_service() {
echo "[5/8] Configuring Docker service..."
sudo systemctl enable docker
sudo systemctl start docker
# Add user to docker group
sudo usermod -aG docker "$USER_NAME"
log_info "Docker service configured and user added to docker group"
}
# Configure Docker daemon
configure_docker_daemon() {
echo "[6/8] Configuring Docker daemon settings..."
sudo mkdir -p /etc/docker
cat << 'EOF' | sudo tee /etc/docker/daemon.json > /dev/null
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
},
"storage-driver": "overlay2",
"default-address-pools": [
{
"base": "172.80.0.0/12",
"size": 24
}
]
}
EOF
sudo systemctl restart docker
log_info "Docker daemon configured successfully"
}
# Create development environment
create_dev_environment() {
echo "[7/8] Setting up development environment..."
# Create directory structure
mkdir -p "$DOCKER_DIR"/{web,databases,services}
# Create docker-compose.yml
cat << 'EOF' > "$DOCKER_DIR/docker-compose.yml"
version: '3.8'
services:
web:
image: nginx:alpine
container_name: dev-web
ports:
- "8080:80"
volumes:
- ./web:/usr/share/nginx/html:ro
depends_on:
- db
networks:
- dev-network
db:
image: postgres:15-alpine
container_name: dev-db
environment:
POSTGRES_DB: devdb
POSTGRES_USER: developer
POSTGRES_PASSWORD: devpass123
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- dev-network
redis:
image: redis:7-alpine
container_name: dev-redis
ports:
- "6379:6379"
networks:
- dev-network
volumes:
postgres_data:
networks:
dev-network:
driver: bridge
EOF
# Create sample web content
mkdir -p "$DOCKER_DIR/web"
cat << 'EOF' > "$DOCKER_DIR/web/index.html"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Docker Development Environment</title>
<style>
body { font-family: Arial, sans-serif; margin: 40px; background: #f5f5f5; }
.container { background: white; padding: 30px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
h1 { color: #2196F3; }
.services { background: #e3f2fd; padding: 20px; border-radius: 5px; margin: 20px 0; }
ul { list-style-type: none; padding: 0; }
li { padding: 10px; background: white; margin: 5px 0; border-radius: 5px; }
</style>
</head>
<body>
<div class="container">
<h1>Docker Development Environment</h1>
<p>Welcome to your Docker development environment!</p>
<p>Your containerized stack is running successfully.</p>
<div class="services">
<h3>Available Services:</h3>
<ul>
<li><strong>Web server:</strong> Nginx (http://localhost:8080)</li>
<li><strong>Database:</strong> PostgreSQL (localhost:5432)</li>
<li><strong>Cache:</strong> Redis (localhost:6379)</li>
</ul>
</div>
</div>
</body>
</html>
EOF
# Set proper permissions
chmod 755 "$DOCKER_DIR"
chmod 755 "$DOCKER_DIR/web"
chmod 644 "$DOCKER_DIR/docker-compose.yml"
chmod 644 "$DOCKER_DIR/web/index.html"
log_info "Development environment created successfully"
}
# Verify installation
verify_installation() {
echo "[8/8] Verifying installation..."
# Test Docker version
if ! sudo -u "$USER_NAME" docker --version >/dev/null 2>&1; then
log_error "Docker installation verification failed"
exit 1
fi
# Test Docker Compose
if ! sudo -u "$USER_NAME" docker compose version >/dev/null 2>&1; then
log_error "Docker Compose installation verification failed"
exit 1
fi
# Test Docker service
if ! systemctl is-active --quiet docker; then
log_error "Docker service is not running"
exit 1
fi
log_info "Installation verified successfully"
}
# Main installation function
main() {
log_info "Starting Docker development environment installation..."
check_prerequisites "$@"
detect_distro
update_system
install_dependencies
add_docker_repo
install_docker
configure_docker_service
configure_docker_daemon
create_dev_environment
verify_installation
log_info "Docker development environment installed successfully!"
echo ""
log_warn "IMPORTANT: You need to log out and back in (or run 'newgrp docker') for group changes to take effect."
echo ""
echo "To test your environment:"
echo " cd $DOCKER_DIR"
echo " docker compose up -d"
echo " curl http://localhost:8080"
echo ""
echo "To stop the environment:"
echo " docker compose down"
}
main "$@"
Review the script before running. Execute with: bash install.sh