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

Explore DeployBase

Related features and resources for this topic

Ready to Get Started?

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