Tutorials

Docker Basics for Web Developers: A Practical Introduction

Muhammad SaadApril 17, 20265 min read
Docker Basics for Web Developers: A Practical Introduction

"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:

  1. Build a production image (no dev dependencies, no volume mounts)
  2. Use environment variables for configuration
  3. Don't run as root — add a non-root user in your Dockerfile
  4. 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, our VPS plans come with Docker pre-installed and ready to go. Deploy your containerized applications in minutes with our optimized infrastructure, automated backups, and 24/7 support. Whether you're running a single container or orchestrating a multi-service architecture, we've got the hosting to match.

Get started with DeployBase →

Share this article

Muhammad Saad

Muhammad Saad

DeployBase Team

Ready to Get Started?

Join thousands of developers who trust DeployBase for their hosting needs.

View Plans