DevOps

Docker for Developers: A Practical Guide

Docker for Developers: A Practical Guide

Docker has become essential for modern development. It eliminates 'works on my machine' problems by packaging your application with all its dependencies into containers. This guide covers everything you need to get productive with Docker.

📦 Docker ensures your development environment matches production. No more debugging environment-specific issues.

Core Concepts

Before diving in, let's understand the key concepts:

  • Image: A read-only template containing instructions for creating a container. Think of it as a class.
  • Container: A runnable instance of an image. Think of it as an object instantiated from the class.
  • Dockerfile: A script of instructions to build an image. It defines your environment.
  • Docker Compose: A tool for defining and running multi-container applications with a YAML file.
  • Volume: Persistent storage that survives container restarts. Essential for databases.
  • Network: Virtual networks that allow containers to communicate with each other.

Your First Dockerfile

A Dockerfile defines how to build your image. Here's a production-ready example for a Python web app:

dockerfile
# Use an official Python runtime as the base image
FROM python:3.12-slim

# Set environment variables
ENV PYTHONDONTWRITEBYTECODE=1 \
    PYTHONUNBUFFERED=1 \
    PIP_NO_CACHE_DIR=1

# Set work directory
WORKDIR /app

# Install system dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
    gcc \
    libpq-dev \
    && rm -rf /var/lib/apt/lists/*

# Install Python dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Copy application code
COPY . .

# Create non-root user for security
RUN adduser --disabled-password --gecos '' appuser
USER appuser

# Expose port and define startup command
EXPOSE 8000
CMD ["gunicorn", "config.wsgi:application", "-b", "0.0.0.0:8000"]
Why these settings?
PYTHONDONTWRITEBYTECODE=1 - Prevents Python from writing .pyc files

PYTHONUNBUFFERED=1 - Ensures Python output is sent straight to terminal (useful for logs)

--no-install-recommends - Minimizes image size by skipping optional packages

rm -rf /var/lib/apt/lists/* - Cleans up apt cache to reduce image size

Non-root user - Security best practice; never run containers as root in production

Docker Compose for Development

Docker Compose lets you define your entire stack in a single file. Here's a complete development setup with a web app, database, and cache:

yaml
# docker-compose.yml
services:
  web:
    build: .
    ports:
      - "8000:8000"
    volumes:
      - .:/app                    # Mount code for hot reload
      - /app/.venv                # Exclude virtualenv
    environment:
      - DEBUG=true
      - DATABASE_URL=postgres://postgres:postgres@db:5432/app
      - REDIS_URL=redis://redis:6379/0
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started
    command: python manage.py runserver 0.0.0.0:8000

  db:
    image: postgres:16
    volumes:
      - postgres_data:/var/lib/postgresql/data
    environment:
      - POSTGRES_DB=app
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 5

  redis:
    image: redis:7-alpine
    volumes:
      - redis_data:/data

volumes:
  postgres_data:
  redis_data:

Essential Commands

These are the commands you'll use daily:

bash
# Build and start all services
docker compose up --build

# Start in background (detached mode)
docker compose up -d

# View logs (follow mode)
docker compose logs -f web

# Run a command in a running container
docker compose exec web python manage.py migrate
docker compose exec web python manage.py shell

# Run a one-off command (creates new container)
docker compose run --rm web python manage.py test

# Stop all services
docker compose down

# Stop and remove volumes (WARNING: deletes data)
docker compose down -v

# Rebuild a specific service
docker compose build web

# View running containers
docker compose ps

Debugging Tips

bash
# Get a shell inside a running container
docker compose exec web bash

# Inspect container details
docker inspect <container_id>

# View container resource usage
docker stats

# Check why a container exited
docker compose logs web --tail=100

# Remove all stopped containers
docker container prune

# Remove unused images
docker image prune -a

# Nuclear option: clean everything
docker system prune -a --volumes
🧹 Use docker system prune regularly to reclaim disk space. Docker images and build cache can consume tens of gigabytes over time.

Common Issues & Solutions

Click to expand troubleshooting guide
Port already in use
Check what's using it: lsof -i :8000 or netstat -tulpn | grep 8000
Kill the process or change the port mapping in docker-compose.yml

Container can't connect to database
Make sure you're using the service name (e.g., db) not localhost
Check that depends_on and healthcheck are configured correctly

Changes not reflected after code edit
Ensure your volume mount is correct and not being overridden
For some frameworks, you may need to restart the container

Build cache not updating
Use docker compose build --no-cache web

Out of disk space
Run docker system prune -a to clean up unused resources

Best Practices

  1. Use specific image tags (python:3.12-slim not python:latest)
  2. Order Dockerfile commands from least to most frequently changing for better caching
  3. Use .dockerignore to exclude files from the build context
  4. Never store secrets in images - use environment variables or secrets management
  5. Use multi-stage builds for smaller production images
  6. Run containers as non-root users
  7. Use health checks to ensure services are ready
  8. Pin your Docker Compose version for reproducibility

Related Posts

Go Language Fundamentals

A comprehensive introduction to the Go programming language. Learn the syntax, patterns, and idioms that make Go unique.

1 min read

PostgreSQL Performance Tuning

Optimize your PostgreSQL database for better performance. Learn configuration tuning, query analysis, and indexing strategies.

1 min read

Comments

Log in to leave a comment.

Log In

Loading comments...