The "It Works on My Machine" Problem

Every developer has experienced it: code that runs perfectly locally crashes in staging. The culprit is usually an environment difference — a different OS, a different version of a runtime, a missing environment variable. Docker solves this by packaging your application and everything it needs into a single, portable unit called a container.

What Is Docker?

Docker is a platform for building, running, and sharing containers. A container is a lightweight, isolated process that includes the application code, runtime, libraries, and configuration — but shares the host OS kernel. This makes containers:

  • Portable: Runs the same everywhere — laptop, CI server, cloud
  • Fast to start: Seconds, not minutes like a VM
  • Consistent: Eliminates environment drift between machines
  • Lightweight: Multiple containers share one OS

Core Concepts You Need to Know

  • Image: A read-only blueprint for a container (think: a recipe)
  • Container: A running instance of an image (think: the dish you cooked)
  • Dockerfile: A text file with instructions to build an image
  • Registry: A storage service for images (Docker Hub is the public default)
  • docker-compose: A tool for running multiple containers together

Step 1: Install Docker

Download and install Docker Desktop from docker.com. It includes the Docker engine, CLI, and Docker Compose. Verify the install:

docker --version
docker run hello-world

If hello-world prints a success message, Docker is working.

Step 2: Write a Dockerfile

Create a simple Python Flask app and a Dockerfile side by side:

# app.py
from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello():
    return "Hello from Docker!"

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)
# Dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 5000
CMD ["python", "app.py"]

Your requirements.txt should contain: flask

Step 3: Build and Run Your Container

# Build the image, tag it "my-flask-app"
docker build -t my-flask-app .

# Run it, mapping port 5000 on host to 5000 in container
docker run -p 5000:5000 my-flask-app

Visit http://localhost:5000 — your app is running inside a container.

Step 4: Use Docker Compose for Multi-Container Apps

Real apps often need a database alongside the app. Docker Compose manages this with a single file:

# docker-compose.yml
version: '3.8'
services:
  web:
    build: .
    ports:
      - "5000:5000"
    depends_on:
      - db
  db:
    image: postgres:15
    environment:
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: myapp

Start everything with: docker compose up. Tear it down with: docker compose down.

Essential Docker Commands

  • docker ps — List running containers
  • docker images — List local images
  • docker logs <container> — View container output
  • docker exec -it <container> bash — Open a shell inside a container
  • docker stop <container> — Stop a running container

Next Steps

Once you're comfortable with the basics, explore multi-stage builds for smaller images, Docker volumes for persistent data, and orchestration with Kubernetes for production deployments. Docker is a foundational skill in modern DevOps — invest time here and it pays dividends across every project.