Docker for Web Developers

Docker for Web Developers

A practical guide to using Docker to streamline your web development workflow and improve deployment consistency.

Gerrad Zhang
Wuhan, China
2 min read

Why Web Developers Should Learn Docker

Docker has become an essential tool for modern web development, offering numerous benefits:

  • Consistent Environments: “It works on my machine” becomes a problem of the past
  • Simplified Onboarding: New team members can set up development environments in minutes
  • Isolation: Each project can have its own dependencies without conflicts
  • Production Parity: Development environments closely mirror production
  • Simplified Deployment: Package everything your application needs to run in a single container

Docker Fundamentals for Web Developers

Key Concepts

  • Images: Read-only templates containing an OS, application code, and dependencies
  • Containers: Running instances of images
  • Dockerfile: Instructions for building an image
  • Volumes: Persistent storage for containers
  • Networks: How containers communicate
  • Docker Compose: Tool for defining and running multi-container applications

Your First Dockerfile

Here’s a simple Dockerfile for a Node.js application:

# Use an official Node.js runtime as a base image
FROM node:16-alpine

# Set the working directory
WORKDIR /app

# Copy package.json and package-lock.json
COPY package*.json ./

# Install dependencies
RUN npm install

# Copy the rest of the application code
COPY . .

# Expose port 3000
EXPOSE 3000

# Command to run the application
CMD ["npm", "start"]

Building and Running

# Build an image
docker build -t my-node-app .

# Run a container
docker run -p 3000:3000 my-node-app

Docker Compose for Multi-Container Applications

Most web applications require multiple services (web server, database, cache, etc.). Docker Compose simplifies managing these with a single configuration file:

# docker-compose.yml
version: '3'

services:
  # Node.js application
  web:
    build: .
    ports:
      - "3000:3000"
    volumes:
      - ./:/app
      - /app/node_modules
    environment:
      - NODE_ENV=development
      - DB_HOST=db
      - DB_USER=postgres
      - DB_PASSWORD=example
    depends_on:
      - db
      - redis

  # PostgreSQL database
  db:
    image: postgres:13
    ports:
      - "5432:5432"
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: example
      POSTGRES_DB: myapp
    volumes:
      - postgres_data:/var/lib/postgresql/data

  # Redis cache
  redis:
    image: redis:6-alpine
    ports:
      - "6379:6379"

volumes:
  postgres_data:

To start all services:

docker-compose up

Development Workflow with Docker

Hot Reloading

For a smoother development experience, configure your application for hot reloading:

# Development Dockerfile
FROM node:16-alpine

WORKDIR /app

COPY package*.json ./
RUN npm install

# Don't copy code - we'll use a volume mount instead

EXPOSE 3000

# Use nodemon for auto-reloading
CMD ["npm", "run", "dev"]

Then in your docker-compose.yml:

services:
  web:
    build: .
    volumes:
      - ./:/app
      - /app/node_modules  # This is a trick to use node_modules from the container
    # other configuration...

Debugging

For Node.js applications, enable the inspector:

services:
  web:
    command: ["node", "--inspect=0.0.0.0:9229", "server.js"]
    ports:
      - "3000:3000"
      - "9229:9229"  # Expose debug port

Common Tasks

# View logs
docker-compose logs -f web

# Open a shell in a running container
docker-compose exec web sh

# Run tests
docker-compose exec web npm test

# Restart a service
docker-compose restart web

Docker for Different Web Stacks

React Applications

# Build stage
FROM node:16-alpine as build
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

# Production stage
FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

Python Django Applications

FROM python:3.9-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]

PHP Laravel Applications

FROM php:8.0-fpm

WORKDIR /var/www/html

# Install dependencies
RUN apt-get update && apt-get install -y \
    libpng-dev \
    libjpeg-dev \
    libfreetype6-dev \
    zip \
    unzip

# Configure and install PHP extensions
RUN docker-php-ext-install pdo_mysql

# Install Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

COPY . .

RUN composer install

CMD ["php", "artisan", "serve", "--host=0.0.0.0"]

Best Practices

Security

  • Use specific image versions instead of latest
  • Never store secrets in images
  • Run containers as non-root users when possible
  • Use multi-stage builds to reduce image size
  • Scan images for vulnerabilities

Performance

  • Use .dockerignore to exclude unnecessary files
  • Layer your Dockerfile efficiently
  • Use Alpine-based images for smaller footprints
  • Leverage build caching

Deployment Considerations

Container Registries

Store your images in a registry like Docker Hub, GitHub Container Registry, or AWS ECR:

# Tag image for a registry
docker tag my-app:latest username/my-app:latest

# Push to registry
docker push username/my-app:latest

Orchestration

For production deployments, consider using:

  • Docker Swarm: Simple built-in orchestration
  • Kubernetes: Advanced orchestration for complex applications
  • AWS ECS/EKS: Managed container services

Conclusion

Comments

Link copied to clipboard!