"It works on my machine." If you've ever said or heard this, Docker is the solution. Docker packages your application and all its dependencies into a standardized unit called a container, ensuring it runs the same everywhere — your laptop, your teammate's machine, staging, and production.
In this guide, we'll cover everything you need to get started with Docker as a web developer.
What Is Docker?
Docker is a platform that uses containerization to package applications. Unlike virtual machines (which emulate entire operating systems), containers share the host OS kernel and isolate only the application layer. This makes them:
- Lightweight: Containers start in seconds, not minutes
- Portable: Run anywhere Docker is installed
- Consistent: Same environment from dev to production
- Efficient: Use a fraction of the resources of VMs
Installing Docker
macOS/Windows: Download Docker Desktop — it includes everything you need.
Linux:
# Ubuntu/Debian sudo apt update sudo apt install docker.io docker-compose-v2 sudo systemctl start docker sudo usermod -aG docker $USER Verify installation:
docker --version docker compose version Core Concepts
Images vs Containers
- Image: A read-only template (like a class in programming)
- Container: A running instance of an image (like an object)
You build images, then run containers from them. Multiple containers can run from the same image.
Dockerfile
A Dockerfile is the recipe for building an image. Here's one for a Node.js app:
# Start from Node.js base image FROM node:20-alpine # Set working directory WORKDIR /app # Copy package files first (for better caching) COPY package*.json ./ # Install dependencies RUN npm ci --only=production # Copy application code COPY . . # Expose port EXPOSE 3000 # Start the app CMD ["node", "server.js"] Build and run it:
# Build the image docker build -t my-app . # Run a container docker run -p 3000:3000 my-app Your app is now running at http://localhost:3000.
Common Dockerfile for PHP/Laravel
FROM php:8.3-fpm-alpine RUN docker-php-ext-install pdo pdo_mysql WORKDIR /var/www/html COPY . . RUN composer install --no-dev --optimize-autoloader EXPOSE 9000 CMD ["php-fpm"] Docker Compose: Multi-Container Apps
Most web apps need more than one service — an app server, a database, maybe Redis. Docker Compose lets you define and run multi-container setups.
Create a docker-compose.yml:
version: '3.8' services: app: build: . ports: - "3000:3000" environment: - DATABASE_URL=postgres://user:pass@db:5432/myapp - REDIS_URL=redis://cache:6379 depends_on: - db - cache volumes: - .:/app # Mount code for live reloading - /app/node_modules # Preserve node_modules db: image: postgres:16-alpine environment: POSTGRES_USER: user POSTGRES_PASSWORD: pass POSTGRES_DB: myapp ports: - "5432:5432" volumes: - pgdata:/var/lib/postgresql/data cache: image: redis:7-alpine ports: - "6379:6379" volumes: pgdata: Run everything:
# Start all services docker compose up -d # View logs docker compose logs -f app # Stop everything docker compose down Essential Docker Commands
# Images docker images # List images docker pull nginx # Download an image docker rmi my-app # Remove an image # Containers docker ps # List running containers docker ps -a # List all containers (including stopped) docker stop <container> # Stop a container docker rm <container> # Remove a container docker logs <container> # View container logs # Execute commands in running container docker exec -it <container> sh # Open shell docker exec -it <container> npm test # Run tests # Cleanup docker system prune # Remove unused data docker volume prune # Remove unused volumes Development Workflow with Docker
Hot Reloading
For development, mount your source code as a volume so changes are reflected immediately:
services: app: build: . volumes: - ./src:/app/src # Changes sync instantly command: npm run dev # Use dev server with hot reload Environment-Specific Compose Files
# Development docker compose -f docker-compose.yml -f docker-compose.dev.yml up # Production docker compose -f docker-compose.yml -f docker-compose.prod.yml up Database Seeding
# Run migrations docker compose exec app npm run migrate # Seed database docker compose exec app npm run seed .dockerignore
Just like .gitignore, create a .dockerignore to keep your images small:
node_modules .git .env *.md docker-compose*.yml .dockerignore Dockerfile Common Patterns for Web Apps
WordPress with Docker
services: wordpress: image: wordpress:latest ports: - "8080:80" environment: WORDPRESS_DB_HOST: db WORDPRESS_DB_NAME: wordpress WORDPRESS_DB_USER: wp WORDPRESS_DB_PASSWORD: secret volumes: - wp_data:/var/www/html db: image: mysql:8 environment: MYSQL_DATABASE: wordpress MYSQL_USER: wp MYSQL_PASSWORD: secret MYSQL_ROOT_PASSWORD: rootsecret volumes: - db_data:/var/lib/mysql volumes: wp_data: db_data: Python/Django
FROM python:3.12-slim WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt COPY . . CMD ["gunicorn", "myproject.wsgi:application", "--bind", "0.0.0.0:8000"] Docker in Production
When you're ready to deploy:
- Build a production image (no dev dependencies, no volume mounts)
- Use environment variables for configuration
- Don't run as root — add a non-root user in your Dockerfile
- Use multi-stage builds to minimize image size:
# Build stage FROM node:20-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build # Production stage FROM node:20-alpine WORKDIR /app COPY --from=builder /app/dist ./dist COPY --from=builder /app/node_modules ./node_modules USER node CMD ["node", "dist/server.js"] Deploy with Confidence
Docker eliminates the "works on my machine" problem by ensuring consistency across all environments. Start with Docker Compose for local development, and you'll have a solid foundation for production deployment.
At DeployBase, your apps run in managed containers, with no Docker for you to install or operate. Deploy your applications in minutes with our optimized infrastructure and email support. Whether you're running a single container or orchestrating a multi-service architecture, we've got the hosting to match.