What is Docker?
Docker is an open-source platform that packages applications and their dependencies into lightweight, portable containers. Think of a container as a self-contained unit that runs the same way on any machine — your laptop, a colleague's workstation, or a production server.
Before containers, teams wrestled with the classic "it works on my machine" problem. Docker solves this by bundling your application code, runtime, system tools, and libraries into a single image that runs consistently everywhere.
Core Concepts
Understanding Docker means grasping a few key concepts:
- Image — A read-only template containing the instructions to build a container. Think of it as a class in object-oriented programming.
- Container — A running instance of an image. Multiple containers can run from the same image, each with its own isolated state.
- Dockerfile — A text file with instructions that Docker reads to build an image automatically.
- Registry — A storage and distribution site for Docker images. Docker Hub is the default public registry.
Your First Dockerfile
Create a file called Dockerfile in your project root:
# Use an official Python runtime as the base image
FROM python:3.12-slim
# Set the working directory inside the container
WORKDIR /app
# Copy the requirements file and install dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy the rest of the application code
COPY . .
# Expose the port your app listens on
EXPOSE 8000
# Define the command to run your application
CMD ["python", "app.py"]
Building and Running
With a Dockerfile in place, the workflow is straightforward:
# Build the image (the dot means "use the current directory as build context")
docker build -t my-app:latest .
# Run the container
docker run -d -p 8000:8000 --name my-container my-app:latest
# View running containers
docker ps
# View logs
docker logs my-container
# Stop and remove the container
docker stop my-container
docker rm my-container
Docker Compose for Multi-Container Apps
Most real-world applications need more than one container — an app server, a database, a cache, and so on. Docker Compose lets you define and run multi-container setups with a single YAML file.
version: '3.8'
services:
web:
build: .
ports:
- "8000:8000"
environment:
- DATABASE_URL=postgresql://user:pass@db:5432/mydb
depends_on:
- db
db:
image: postgres:16
volumes:
- pgdata:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD=pass
volumes:
pgdata:
Run it with docker compose up -d and your entire stack starts with one command.
Best Practices for Beginners
- Use multi-stage builds to keep images small — build artifacts in one stage, copy only what's needed into the final image.
- Pin image versions — avoid
latestin production; use specific tags likepython:3.12.4-slim. - Don't run as root — create a non-root user in your Dockerfile for security.
- Leverage
.dockerignore— excludenode_modules,.git, and other unnecessary files from the build context. - Scan your images — use tools like
trivyordocker scoutto check for known vulnerabilities.
Conclusion
Docker lowers the barrier to consistent, reproducible deployments. Start with a simple Dockerfile, experiment with docker compose, and gradually adopt best practices as your projects grow. The investment pays off quickly when you eliminate environment-related bugs and speed up onboarding for new team members.