Skip to main content
Docker deployment provides a containerized, production-ready setup with isolated services and easy scaling.

Overview

The Docker setup includes:
  • Backend container: FastAPI server with Playwright
  • Frontend container: Next.js web client
  • Volume mounts: Persistent PDF storage
  • Automatic restarts: Service resilience

Prerequisites

1

Install Docker

2

Install Docker Compose

Docker Compose is included with Docker Desktop. For Linux:
sudo apt-get install docker-compose-plugin
3

Verify installation

docker --version
docker compose version

Quick start

1

Clone or navigate to project directory

cd /path/to/universal-manga-downloader
2

Create environment file

cp .env.example .env
Edit .env if needed:
.env
# Optional: Google API key for enhanced scraping
GOOGLE_API_KEY=your_api_key_here
3

Launch with Docker Compose

docker compose up -d
This will:
  1. Build the backend image
  2. Build the frontend image
  3. Start both containers in detached mode
  4. Create volume mounts for PDF storage
4

Access the application

Open your browser to:
http://localhost:3000
The -d flag runs containers in the background. Omit it to see real-time logs.

Docker Compose configuration

The docker-compose.yml file defines the multi-container setup:
docker-compose.yml
version: '3.8'

services:
  backend:
    build: .
    container_name: manga_backend
    ports:
      - "8000:8000"
    volumes:
      - ./PDF:/app/PDF
      - ./.env:/app/.env
    restart: unless-stopped
    command: python web_server.py

  frontend:
    build:
      context: ./web_client_next
      dockerfile: Dockerfile
    container_name: manga_frontend
    ports:
      - "3000:3000" # Next.js exposed on port 3000
    depends_on:
      - backend
    restart: unless-stopped
    environment:
      - NODE_ENV=production

Service breakdown

Backend service

backend:
  build: .                    # Use Dockerfile in project root
  container_name: manga_backend
  ports:
    - "8000:8000"             # Expose FastAPI server
  volumes:
    - ./PDF:/app/PDF          # Persistent PDF storage
    - ./.env:/app/.env        # Environment variables
  restart: unless-stopped     # Auto-restart on failure
  command: python web_server.py
The backend container runs web_server.py which starts the FastAPI server on port 8000.

Frontend service

frontend:
  build:
    context: ./web_client_next
    dockerfile: Dockerfile
  container_name: manga_frontend
  ports:
    - "3000:3000"             # Expose Next.js app
  depends_on:
    - backend                  # Wait for backend to start
  restart: unless-stopped
  environment:
    - NODE_ENV=production

Dockerfile

The backend Dockerfile sets up the Python environment:
Dockerfile
# Python base image
FROM python:3.10-slim

WORKDIR /app

# Install system dependencies
RUN apt-get update && apt-get install -y \
    wget \
    gnupg \
    && rm -rf /var/lib/apt/lists/*

COPY requirements.txt .

# Install Python deps
RUN pip install --no-cache-dir -r requirements.txt

# Install Playwright browsers
RUN playwright install chromium
RUN playwright install-deps

# Copy app code
COPY . .

# Expose port (FastAPI default)
EXPOSE 8000

# Run the server
CMD ["python", "web_server.py"]

Key components

LayerPurpose
python:3.10-slimLightweight Python base image
apt-get installSystem dependencies for Playwright
pip installPython packages from requirements.txt
playwright installDownload Chromium browser
COPY . .Application code
EXPOSE 8000Document port usage
CMDDefault startup command
The Playwright browser installation (playwright install chromium) adds ~200MB to the image. This is necessary for web scraping functionality.

Volume mounts

PDF storage

volumes:
  - ./PDF:/app/PDF
This mounts the host’s PDF/ directory to /app/PDF in the container, ensuring:
  • PDFs persist after container restarts
  • Files are accessible from the host system
  • No data loss during updates

Environment variables

volumes:
  - ./.env:/app/.env
Mounts the .env file for configuration without rebuilding the image.
You can also use Docker Compose’s env_file directive:
env_file:
  - .env

Port mappings

ServiceContainer PortHost PortConfigurable
Backend80008000Yes
Frontend30003000Yes

Changing ports

To change the exposed ports, modify docker-compose.yml:
ports:
  - "8080:8000"  # Backend accessible on host port 8080
ports:
  - "3001:3000"  # Frontend accessible on host port 3001
If you change the backend port, update the frontend’s API endpoint configuration to match.

Managing containers

Start services

docker compose up -d

Stop services

docker compose down

View logs

docker compose logs -f

Restart services

docker compose restart

Rebuild images

After code changes:
docker compose up -d --build
Use --build to force rebuild of images when you update application code or dependencies.

Remove containers and volumes

docker compose down -v
The -v flag deletes volumes, including PDF files. Omit it to preserve data.

Production considerations

Environment variables

For production, use Docker secrets or external secret management:
services:
  backend:
    environment:
      - DISCORD_TOKEN=${DISCORD_TOKEN}
      - GOOGLE_API_KEY=${GOOGLE_API_KEY}

Resource limits

Add resource constraints to prevent memory exhaustion:
services:
  backend:
    deploy:
      resources:
        limits:
          cpus: '2.0'
          memory: 2G
        reservations:
          cpus: '1.0'
          memory: 1G
Adjust limits based on your server capacity and expected load. Image processing is memory-intensive.

Health checks

Add health checks for better reliability:
services:
  backend:
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/pdfs/"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

Logging

Configure log rotation to prevent disk space issues:
services:
  backend:
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

Networks

Create a custom network for service isolation:
services:
  backend:
    networks:
      - manga-network

  frontend:
    networks:
      - manga-network

networks:
  manga-network:
    driver: bridge

Reverse proxy

For production, use Nginx or Traefik as a reverse proxy:
docker-compose.yml
services:
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./ssl:/etc/nginx/ssl:ro
    depends_on:
      - backend
      - frontend
    restart: unless-stopped
Use Traefik for automatic SSL certificate management with Let’s Encrypt.

Scaling

Multiple backend instances

Scale the backend for higher throughput:
docker compose up -d --scale backend=3
Combine with a load balancer:
services:
  backend:
    deploy:
      replicas: 3
Scaling the backend requires shared PDF storage (NFS, S3, etc.) and session management.

Troubleshooting

Build fails with Playwright errors

Issue: Playwright browser installation fails Solution: Increase Docker memory allocation (Docker Desktop → Settings → Resources → Memory → 4GB+)

Container exits immediately

Issue: Missing dependencies or configuration errors Solution: Check logs:
docker compose logs backend

“Port already in use” error

Issue: Another service is using port 8000 or 3000 Solution:
  • Stop the conflicting service
  • Or change the port mapping in docker-compose.yml

PDFs not persisting

Issue: Volume mount not configured correctly Solution: Verify the mount in docker-compose.yml:
docker compose config  # Validate configuration
ls -la ./PDF           # Check host directory exists

Frontend can’t connect to backend

Issue: Network configuration or CORS policy Solution:
  1. Verify both containers are on the same network:
    docker network inspect universal-manga-downloader_default
    
  2. Update CORS policy in web_server.py to include the frontend container name
  3. Check that depends_on is correctly set in frontend service

Out of disk space

Issue: Docker images and logs consuming disk space Solution: Clean up unused resources:
docker system prune -a --volumes
This removes all unused containers, networks, images, and volumes. Use with caution.

Performance optimization

Image size reduction

Optimize the Dockerfile for smaller images:
# Multi-stage build example
FROM python:3.10-slim as builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir --user -r requirements.txt

FROM python:3.10-slim
WORKDIR /app
COPY --from=builder /root/.local /root/.local
COPY . .
ENV PATH=/root/.local/bin:$PATH
CMD ["python", "web_server.py"]

Build caching

Order Dockerfile commands to maximize cache hits:
  1. System dependencies (rarely change)
  2. Python dependencies (change occasionally)
  3. Application code (change frequently)

Shared volumes for efficiency

volumes:
  pdf-storage:
    driver: local

services:
  backend:
    volumes:
      - pdf-storage:/app/PDF

Security

Non-root user

Run containers as non-root:
RUN useradd -m -u 1000 appuser
USER appuser

Read-only filesystem

services:
  backend:
    read_only: true
    tmpfs:
      - /tmp
      - /app/PDF

Secret management

Use Docker secrets for sensitive data:
secrets:
  discord_token:
    file: ./secrets/discord_token.txt

services:
  backend:
    secrets:
      - discord_token
Docker secrets are only available in Swarm mode. For Compose-only deployments, use environment variables with caution.

Comparison with other deployment methods

AspectDockerWeb App (Manual)Desktop App
Setup timeMediumHighLow
PortabilityExcellentPoorPoor
IsolationYesNoNo
UpdatesEasy (rebuild)ManualManual
Resource usageHigherLowerLower
Multi-serverEasy (orchestration)ComplexN/A
Production readyYesRequires setupNo
Docker is ideal for production deployments, development consistency, and multi-environment setups.

Build docs developers (and LLMs) love