Tutorials

How to Dockerize Your Web Application: A Beginner's Production Guide

Muhammad SaadMay 10, 20266 min read
How to Dockerize Your Web Application: A Beginner's Production Guide

If you've ever heard "it works on my machine" or spent hours debugging environment differences between development and production, Docker for web applications solves that problem completely. Docker packages your app with its exact dependencies, configuration, and runtime into a portable container that runs identically everywhere — your laptop, a staging server, or production VPS.

This guide walks you through containerizing a real web application, from first Dockerfile to production deployment.

What Docker Actually Does

Docker creates isolated, lightweight environments called containers. Unlike virtual machines, containers share the host OS kernel, making them fast to start (seconds, not minutes) and efficient with resources.

Think of it this way: a VM is like renting an entire apartment building. A container is like renting just the apartment you need — same isolation, fraction of the overhead.

Without Docker:
  Your App → Different OS → Different PHP version → Different config → 🔥 Bugs

With Docker:
  Your App → Same container everywhere → ✅ Works identically

Installing Docker

Ubuntu/Debian

# Remove old versions
sudo apt remove docker docker-engine docker.io containerd runc

# Install Docker
curl -fsSL https://get.docker.com | sudo sh

# Add your user to the docker group (no sudo needed for docker commands)
sudo usermod -aG docker $USER

# Verify installation
docker --version
docker compose version

macOS

Download Docker Desktop from docker.com — it includes everything you need.

Docker for Web Applications: Your First Dockerfile

A Dockerfile is a recipe that tells Docker how to build your container image. Here's a practical example for a Node.js application:

# Use official Node.js image as base
FROM node:20-alpine

# Set working directory inside the container
WORKDIR /app

# Copy dependency files first (better caching)
COPY package*.json ./

# Install production dependencies
RUN npm ci --only=production

# Copy application code
COPY . .

# Expose the port your app listens on
EXPOSE 3000

# Start the application
CMD ["node", "server.js"]

Build and run it:

# Build the image
docker build -t myapp .

# Run the container
docker run -d -p 3000:3000 --name myapp myapp

Your app is now running in a container, accessible at http://localhost:3000.

Dockerizing Common Web Stacks

PHP/Laravel Application

FROM php:8.3-fpm-alpine

RUN docker-php-ext-install pdo pdo_mysql opcache

WORKDIR /var/www/html

COPY composer.json composer.lock ./
RUN composer install --no-dev --optimize-autoloader

COPY . .

RUN php artisan config:cache && \
    php artisan route:cache && \
    php artisan view:cache

EXPOSE 9000
CMD ["php-fpm"]

Python/Django Application

FROM python:3.12-slim

WORKDIR /app

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

COPY . .

RUN python manage.py collectstatic --noinput

EXPOSE 8000
CMD ["gunicorn", "myproject.wsgi:application", "--bind", "0.0.0.0:8000"]

WordPress with Custom Theme

FROM wordpress:6.7-php8.3-fpm

COPY wp-content/themes/mytheme /var/www/html/wp-content/themes/mytheme
COPY wp-content/plugins/myplugin /var/www/html/wp-content/plugins/myplugin

Docker Compose: Multi-Container Applications

Most web applications need more than one container — your app, a database, maybe Redis for caching. Docker Compose orchestrates multiple containers together.

docker-compose.yml for a Typical Web App

version: '3.8'

services:
  app:
    build: .
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - DATABASE_URL=postgres://user:pass@db:5432/myapp
      - REDIS_URL=redis://redis:6379
    depends_on:
      - db
      - redis
    restart: unless-stopped

  db:
    image: postgres:16-alpine
    environment:
      - POSTGRES_DB=myapp
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=pass
    volumes:
      - pgdata:/var/lib/postgresql/data
    restart: unless-stopped

  redis:
    image: redis:7-alpine
    restart: unless-stopped

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      - app
    restart: unless-stopped

volumes:
  pgdata:

Start everything with one command:

docker compose up -d

All four services start together, connected on an internal Docker network where they can reach each other by service name (db, redis, app).

Dockerfile Best Practices

Use Multi-Stage Builds

Reduce your final image size by separating build and runtime stages:

# Stage 1: Build
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Stage 2: Production
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
EXPOSE 3000
CMD ["node", "dist/server.js"]

This produces a much smaller image because build tools and dev dependencies stay in the builder stage.

Use .dockerignore

Just like .gitignore, a .dockerignore file prevents unnecessary files from being copied into your image:

node_modules
.git
.env
*.md
.github
tests
coverage

Don't Run as Root

# Create a non-root user
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser

Layer Caching

Docker caches each layer. Put things that change frequently (your code) after things that change rarely (dependencies):

# Dependencies change less often — cached
COPY package*.json ./
RUN npm ci

# Code changes often — rebuilds from here
COPY . .

Deploying Docker Containers to a VPS

Once your app is containerized, deploying to a VPS becomes straightforward. If you've been following our guide on staging environment setup, Docker makes staging even easier — identical containers across all environments.

Step 1: Push Your Image to a Registry

# Tag your image
docker tag myapp registry.example.com/myapp:latest

# Push to Docker Hub or a private registry
docker push registry.example.com/myapp:latest

Step 2: Pull and Run on Your VPS

# On your VPS
docker pull registry.example.com/myapp:latest
docker compose up -d

Step 3: Set Up Automated Deployments

Combine Docker with CI/CD for push-to-deploy workflows:

# GitHub Actions example
name: Deploy
on:
  push:
    branches: [main]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Build and push Docker image
        run: |
          docker build -t myapp:latest .
          docker save myapp:latest | ssh user@vps 'docker load'
      - name: Restart on VPS
        run: ssh user@vps 'cd /app && docker compose up -d'

Monitoring Docker Containers

Keep your containers healthy in production:

# Check running containers
docker ps

# View logs
docker logs myapp --tail 100 -f

# Resource usage
docker stats

# Restart a container
docker compose restart app

When your app needs to scale horizontally, Docker makes it simple — spin up more container instances behind a load balancer.

FAQ

Is Docker overkill for a simple website?

For a static site or basic WordPress blog, Docker adds unnecessary complexity. Docker shines when you need reproducible environments, run multiple services, or deploy across different servers consistently.

Does Docker replace my web hosting?

No. Docker runs on top of your hosting. You still need a VPS or server to run your containers. Docker simplifies what runs on that server and how you deploy updates.

How much memory does Docker use?

Docker itself uses minimal resources. Each container adds the memory your application actually needs — typically 50-200MB for a web app. A 2GB VPS can comfortably run 3-5 containers.

Can I use Docker with shared hosting?

No. Docker requires root access and a Linux kernel, which shared hosting doesn't provide. You need a VPS or dedicated server.

Containerize Your Stack with DeployBase

Docker for web applications eliminates deployment headaches by ensuring your app runs identically in development, staging, and production. Once containerized, you can deploy with confidence knowing there are no environment surprises.

At DeployBase, our VPS plans come with Docker pre-available, full root access, and NVMe SSD storage for fast container builds and pulls. Starting at $5/month with 24/7 support, you get the infrastructure your containerized applications need.

Get your VPS at DeployBase → — deploy containers with confidence.

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.