🟒 Verifying Offline Frappe/ERPNext Is Working (and Fixing Frontend Issues)

After loading Docker images from a .tar file and starting services with Docker Compose without internet, the final and most common hurdle is getting the frontend (nginx) container running correctly.

This section explains how to diagnose, fix, and verify a successful offline setup.


βœ… Expected Healthy State

Run:

docker compose -f pwd.yml ps

A healthy system looks like this:

backend        Up
db             Up (healthy)
redis-cache    Up
redis-queue    Up
queue-short    Up
queue-long     Up
scheduler      Up
websocket      Up
frontend       Up (port exposed)

Example:

frappe_docker-frontend-1   Up   0.0.0.0:8081->8080/tcp

If frontend is missing or restarting, your site will not be accessible.


❌ Common Error: Frontend Restart Loop

Frontend logs may show:

host not found in upstream "backend:8000"

Or Docker may fail with:

failed to bind host port 0.0.0.0:8080: address already in use

What this means

  • Docker could not bind port 8080 on the host
  • Frontend container never fully starts
  • Nginx cannot resolve backend because the container exits immediately

This is not a Frappe bug β€” it’s a Docker port conflict.


Edit pwd.yml:

frontend:
  ports:
    - "8081:8080"

Why this works:

  • 8080 is commonly already in use
  • Internal nginx still listens on 8080
  • Host exposes 8081 instead

πŸ”„ Restart Cleanly

docker compose -f pwd.yml down
docker compose -f pwd.yml up -d --pull=never

Then confirm:

docker compose -f pwd.yml ps

Frontend must be Up.


🌐 Accessing the Site (Important)

Frappe uses host-based routing.

If your site is named:

test.local

You must send the Host header.

CLI test

curl -H "Host: test.local" http://localhost:8081

Expected output:

<title>Login</title>

🌍 Browser Access

Add to /etc/hosts (host machine):

127.0.0.1 test.local

Then open:

http://test.local:8081

You should see the ERPNext login page.


πŸ”Ž Extra Verification Commands

Confirm site exists

docker compose -f pwd.yml exec backend ls sites

Expected:

test.local

Confirm backend config

docker compose -f pwd.yml exec backend \
  cat sites/test.local/site_config.json

You should see:

"db_host": "db"

🧠 Key Takeaways (Offline Deployments)

  • Docker images must be saved together:

    • frappe/erpnext
    • mariadb
    • redis
  • Use:

    docker compose up --pull=never
    
  • Frontend issues are almost always port conflicts

  • Backend running β‰  site accessible

  • Frappe requires Host headers, even locally