Services Work About Team Blog Tutorials FAQ 💬 Chat on WhatsApp

Home / Blog / Frappe: Production Install of Custom Apps with Docker (Easy Step-by-Step Guide)

FrappeERPNextDockerProductionDevOpsTutorial

Frappe: Production Install of Custom Apps with Docker (Easy Step-by-Step Guide)

Moving from a local Frappe development environment to a live Docker production setup can feel daunting. In production, you aren’t simply running bench get-app inside a live container—ephemeral containers mean any changes made inside an active container will disappear upon restart!

To deploy custom apps in production, your custom apps must be baked directly into the custom Docker image and orchestrated via Docker Compose alongside Redis, MariaDB, and Traefik reverse proxies.

Here is the straightforward, production-grade guide to deploying custom Frappe apps with Docker.


The Production Docker Workflow

Unlike monolithic bench installs, production Docker deployments use separated microservice containers:

  • backend (Gunicorn Python WSGI)
  • frontend (Nginx serving static assets and proxying requests)
  • websocket (Node.js socketio service)
  • queue-default, queue-short, queue-long (Background Celery workers)
  • scheduler (Cron tasks)

All these services share the same custom image containing your app code and static assets.


Step 1: Bake Your Custom App into the Production Image

In your deployment repository:

  1. Create a compose.yaml and reference your custom Dockerfile or pre-built image tag.
  2. Ensure your custom image includes both your custom app and official apps like ERPNext or HRMS.
  3. Build and tag your image locally or via GitHub Actions:
docker compose build

Step 2: Running the Database Migrations

Once your containers are started:

docker compose up -d

You must run migrations to create the custom DocTypes, fields, and permissions in your MariaDB database:

docker compose exec backend bench --site yourdomain.com install-app your_custom_app
docker compose exec backend bench --site yourdomain.com migrate

Step 3: Rebuilding Assets for Production Nginx

If your custom app includes client scripts, custom web views, or bundled Vue/React bundles:

docker compose exec backend bench build --app your_custom_app
docker compose exec backend bench --site yourdomain.com clear-cache

Restart the frontend and backend services to ensure Gunicorn workers reload python bytecode:

docker compose restart backend frontend websocket

Key Production Gotchas

  1. Volume Persistence: Never store custom app code in ephemeral root directories. Persistent files, logs, and private/public uploads must be mounted to named Docker volumes (sites).
  2. Database Backups: Always run bench --site yourdomain.com backup --with-files before executing migrations on live production databases.
  3. Environment Variables: Keep secret database passwords and encryption keys in .env files with restricted 600 file permissions.

Summary

Containerizing Frappe apps for production ensures seamless horizontal scaling, instant rollbacks, and zero host dependency conflicts.

Looking for dedicated Frappe & ERPNext cloud deployment, server migration, or custom ERP development? Connect with the engineers at Klickspell.

Technical Blog

Explore more engineering articles

All Articles ↗

Looking for custom
Shopify engineering craft?

Let's build
your store right.

Let's start with a free 30-minute call. No commitment, no templates, no compromises.

Free 30-min call. No commitment. No templates.

Book your free call →

The craft in every click.