Jump to content

ERPNext v15 Docker Setup Guide

From MediawikiCIT

FORCETOC

ERPNext v15 — Docker Setup Guide

Based on the original tutorial by Rein Simacon. Updated 2025 | ERPNext v15.31.3 | Docker Compose v2

Purpose

This guide walks you through running ERPNext v15 on your local machine using Docker. A Docker-based setup starts faster and uses fewer resources than a virtual machine — making it ideal for:

  • Students exploring ERPNext, database design, REST APIs, and webhooks in a live environment
  • IT staff and evaluators testing ERPNext before committing to a full deployment
  • Thin-client demos — ERPNext v15 can comfortably serve companies under 50 users on modest hardware

If you break something, you can tear it all down and start fresh in minutes.

Default Credentials

Field Value
URL http://localhost:8080
Username Administrator
Password admin

⚠ These are for local testing only. Never expose this setup to the internet without changing passwords and adding HTTPS.

Minimum Hardware Requirements

Resource Minimum Recommended
RAM 4 GB 8 GB
CPU 2 cores 4 cores
Disk 10 GB free 20 GB free

RAM is the critical constraint. ERPNext runs multiple services simultaneously (MariaDB, Redis ×2, backend workers, scheduler, websocket, nginx). Less than 4 GB will cause containers to crash-loop.

Architecture Overview

ERPNext in Docker is composed of several services that work together:

Service Role
frontend Nginx reverse proxy — serves the web UI on port 8080
backend Frappe/ERPNext Python application server
websocket Node.js Socket.IO server for real-time updates
queue-long Background worker for long-running jobs (imports, reports)
queue-short Background worker for short jobs (emails, notifications)
scheduler Cron-like service for scheduled tasks
db MariaDB 10.6 database
redis-cache In-memory cache for session and page data
redis-queue Message broker for the job queues
configurator One-time setup container (runs once, then exits)
create-site One-time site creation container (runs once, then exits)

Step 1 — Install Docker

Install Docker Engine and the Docker Compose plugin (v2).

Windows

Download and install Docker Desktop: docker.com/products/docker-desktop

Docker Desktop bundles both Docker Engine and the Compose plugin.

Ubuntu / Debian Linux

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

# Add your user to the docker group (so you don't need sudo every time)
sudo usermod -aG docker $USER

# Log out and back in, then verify
docker --version
docker compose version

Note: This guide uses docker compose (v2, no hyphen). The older docker-compose (v1) is deprecated. If your system only has v1, replace docker compose with docker-compose in all commands below.

Useful References

Step 2 — Create a Working Directory

mkdir -p ~/docker/erpnext
cd ~/docker/erpnext

Step 3 — Create the Docker Compose File

Create a file named pwd.yml:

nano pwd.yml

Paste the following content:

services:
  backend:
    image: frappe/erpnext:v15.31.3
    deploy:
      restart_policy:
        condition: on-failure
    volumes:
      - sites:/home/frappe/frappe-bench/sites
      - logs:/home/frappe/frappe-bench/logs

  configurator:
    image: frappe/erpnext:v15.31.3
    deploy:
      restart_policy:
        condition: none
    entrypoint:
      - bash
      - -c
    command:
      - >
        ls -1 apps > sites/apps.txt;
        bench set-config -g db_host $$DB_HOST;
        bench set-config -gp db_port $$DB_PORT;
        bench set-config -g redis_cache "redis://$$REDIS_CACHE";
        bench set-config -g redis_queue "redis://$$REDIS_QUEUE";
        bench set-config -g redis_socketio "redis://$$REDIS_QUEUE";
        bench set-config -gp socketio_port $$SOCKETIO_PORT;
    environment:
      DB_HOST: db
      DB_PORT: "3306"
      REDIS_CACHE: redis-cache:6379
      REDIS_QUEUE: redis-queue:6379
      SOCKETIO_PORT: "9000"
    volumes:
      - sites:/home/frappe/frappe-bench/sites
      - logs:/home/frappe/frappe-bench/logs

  create-site:
    image: frappe/erpnext:v15.31.3
    deploy:
      restart_policy:
        condition: none
    volumes:
      - sites:/home/frappe/frappe-bench/sites
      - logs:/home/frappe/frappe-bench/logs
    entrypoint:
      - bash
      - -c
    command:
      - >
        wait-for-it -t 120 db:3306;
        wait-for-it -t 120 redis-cache:6379;
        wait-for-it -t 120 redis-queue:6379;
        export start=`date +%s`;
        until [[ -n `grep -hs ^ sites/common_site_config.json | jq -r ".db_host // empty"` ]] && \
          [[ -n `grep -hs ^ sites/common_site_config.json | jq -r ".redis_cache // empty"` ]] && \
          [[ -n `grep -hs ^ sites/common_site_config.json | jq -r ".redis_queue // empty"` ]];
        do
          echo "Waiting for sites/common_site_config.json to be created";
          sleep 5;
          if (( `date +%s`-start > 120 )); then
            echo "could not find sites/common_site_config.json with required keys";
            exit 1
          fi
        done;
        echo "sites/common_site_config.json found";
        bench new-site --no-mariadb-socket --admin-password=admin --db-root-password=admin --install-app erpnext --set-default frontend;

  db:
    image: mariadb:10.6
    healthcheck:
      test: mysqladmin ping -h localhost --password=admin
      interval: 1s
      retries: 15
    deploy:
      restart_policy:
        condition: on-failure
    command:
      - --character-set-server=utf8mb4
      - --collation-server=utf8mb4_unicode_ci
      - --skip-character-set-client-handshake
      - --skip-innodb-read-only-compressed
    environment:
      MYSQL_ROOT_PASSWORD: admin
    volumes:
      - db-data:/var/lib/mysql

  frontend:
    image: frappe/erpnext:v15.31.3
    depends_on:
      - websocket
    deploy:
      restart_policy:
        condition: on-failure
    command:
      - nginx-entrypoint.sh
    environment:
      BACKEND: backend:8000
      FRAPPE_SITE_NAME_HEADER: frontend
      SOCKETIO: websocket:9000
      UPSTREAM_REAL_IP_ADDRESS: 127.0.0.1
      UPSTREAM_REAL_IP_HEADER: X-Forwarded-For
      UPSTREAM_REAL_IP_RECURSIVE: "off"
      PROXY_READ_TIMEOUT: 120
      CLIENT_MAX_BODY_SIZE: 50m
    volumes:
      - sites:/home/frappe/frappe-bench/sites
      - logs:/home/frappe/frappe-bench/logs
    ports:
      - "8080:8080"

  queue-long:
    image: frappe/erpnext:v15.31.3
    deploy:
      restart_policy:
        condition: on-failure
    command:
      - bench
      - worker
      - --queue
      - long,default,short
    volumes:
      - sites:/home/frappe/frappe-bench/sites
      - logs:/home/frappe/frappe-bench/logs

  queue-short:
    image: frappe/erpnext:v15.31.3
    deploy:
      restart_policy:
        condition: on-failure
    command:
      - bench
      - worker
      - --queue
      - short,default
    volumes:
      - sites:/home/frappe/frappe-bench/sites
      - logs:/home/frappe/frappe-bench/logs

  redis-queue:
    image: redis:6.2-alpine
    deploy:
      restart_policy:
        condition: on-failure
    volumes:
      - redis-queue-data:/data

  redis-cache:
    image: redis:6.2-alpine
    deploy:
      restart_policy:
        condition: on-failure
    volumes:
      - redis-cache-data:/data

  scheduler:
    image: frappe/erpnext:v15.31.3
    deploy:
      restart_policy:
        condition: on-failure
    command:
      - bench
      - schedule
    volumes:
      - sites:/home/frappe/frappe-bench/sites
      - logs:/home/frappe/frappe-bench/logs

  websocket:
    image: frappe/erpnext:v15.31.3
    deploy:
      restart_policy:
        condition: on-failure
    command:
      - node
      - /home/frappe/frappe-bench/apps/frappe/socketio.js
    volumes:
      - sites:/home/frappe/frappe-bench/sites
      - logs:/home/frappe/frappe-bench/logs

volumes:
  db-data:
  redis-queue-data:
  redis-cache-data:
  sites:
  logs:

Save and exit: Ctrl+O, Enter, Ctrl+X.

Tip: You can always get the latest version of this file from the official Frappe Docker repository: frappe/frappe_docker — pwd.yml

Step 4 — Start ERPNext

From inside your working directory (~/docker/erpnext), run:

docker compose -p pwd -f pwd.yml up -d

This will:

  1. Pull all required images from Docker Hub (~1–2 GB total on first run)
  2. Create the named volumes for data persistence
  3. Start all services in the background
  4. Run configurator and create-site once to initialize the database and site

First startup takes 3–10 minutes depending on your internet speed and hardware. The create-site container must complete before the UI becomes available.

Step 5 — Verify the Containers

docker ps -a

Expected output — you should see containers for frontend, backend, websocket, queue-long, queue-short, scheduler, db, redis-cache, and redis-queue.

The configurator and create-site containers will show Exited (0) — this is normal and expected. They are one-time setup containers.

If any persistent service shows Restarting, check its logs:

docker logs <container_name>

Step 6 — Allow Port 8080 (Linux Firewall)

If you are running on a Linux server with ufw enabled:

sudo ufw allow 8080/tcp

If you are running on a cloud VM (GCP, AWS, Azure), also open port 8080 in your cloud firewall/security group settings.

Step 7 — Access ERPNext in Your Browser

Open your browser and go to:

http://localhost:8080

If accessing from another machine on the same network, replace localhost with the host machine's IP address:

http://192.168.x.x:8080

Step 8 — Log In

Field Value
Username Administrator
Password admin

After logging in, you will be prompted to complete initial setup (site name, language, timezone, etc.).

To verify the installed version: click Help (top-right) → About.

Day-to-Day Operations

Stop ERPNext

Always stop containers cleanly before shutting down your machine or taking a backup:

docker compose -p pwd -f pwd.yml stop

To stop all running containers system-wide (use with caution):

docker stop $(docker ps -q)

Start ERPNext Again

docker compose -p pwd -f pwd.yml up -d

Use up -d to restart, not start. The up command ensures all dependencies and network links are re-established correctly.

View Live Logs

docker compose -p pwd -f pwd.yml logs -f

To follow logs for a specific service only (e.g., the backend):

docker compose -p pwd -f pwd.yml logs -f backend

Data Persistence

All your ERPNext data (database records, uploaded files, site configuration) is stored in Docker named volumes, not inside the containers. This means:

  • Stopping or restarting containers does not delete your data
  • Deleting containers with docker rm does not delete your data
  • Only explicitly removing volumes will delete data

To list volumes:

docker volume ls

To back up the database volume:

docker exec pwd-db-1 mysqldump -u root -padmin --all-databases > erpnext_backup_$(date +%Y%m%d).sql

Nuclear Reset (Start Fresh)

If your setup is broken and you want to wipe everything and start over:

# Stop and remove all containers
docker compose -p pwd -f pwd.yml down

# Remove all containers, volumes, and images (DESTROYS ALL DATA)
docker compose -p pwd -f pwd.yml down -v --rmi all

Or to remove all Docker containers on the system (use with caution):

docker rm -v -f $(docker ps -qa)

After a full reset, rerun Step 4 to start fresh.

Troubleshooting

Symptom Likely Cause Fix
Browser shows "connection refused" Containers still starting up Wait 3–5 more minutes, recheck docker ps
frontend container keeps restarting Not enough RAM Free up memory or add swap
create-site exited with error DB not ready in time Run docker compose -p pwd -f pwd.yml down -v then up -d again
Login works but page is blank Browser cache issue Hard refresh (Ctrl+Shift+R)
Changes not saving Disk full Check with df -h

Next Steps for Students

Once your ERPNext instance is running, here are good things to explore:


Original tutorial by Rein Simacon. Updated and expanded 2025.