Running ERPNext Docker deployment with frappe_docker: when it fits and what is harder than it looks
Teams that want ERPNext on their own infrastructure in containers usually start with the frappe_docker repository, which provides production Docker images and Compose files for ERPNext and other Frappe apps. The work is not a single container. It is building and operating a multi-service stack that includes MariaDB, Redis, background workers, the scheduler, a Socket.io service and Nginx, and it still needs an operator who understands how Frappe benches, sites and apps behave. The repository's single-file demo setup is marked for short-lived evaluation only, so it should not become the production foundation by default. This approach fits when your team already runs containers in its own cloud accounts, data centers or air-gapped network, and wants version control, repeatable builds and a clear separation between the platform and its data. It also fits when you need custom apps that must ship in the same image as ERPNext. It is a weaker choice if your team has no one who can troubleshoot a failed queue, a stuck scheduler or a migration error, because those problems surface inside the stack rather than at the container boundary. Frappe Cloud, bench installs and partner-managed hosting are alternatives to weigh against it. The first hard part is the image build. A custom app must be included when the image is built, pinned to a compatible ERPNext branch, and rebuilt whenever ERPNext or the app changes. Ask who owns that pipeline, how builds are tested before release, and how a failed build is rolled back. The second hard part is persistence. Site files, the database volume and any private files must survive container replacement, and backup jobs must capture them consistently. Confirm where each volume lives, how it is snapped or dumped, and whether a restore has ever been tested on a separate host. The third and fourth hard parts are background processes and upgrades. Workers and the scheduler run jobs such as email queues, recurring documents and integrations, and a stopped worker often fails silently until someone notices a backlog. Monitor queue depth and scheduler health as well as web response. For upgrades, each supported Frappe version receives frequent minor releases, so the team needs a staging stack, a repeatable migrate step and a tested rollback before any production change. Plan for these as recurring operating work, not as one-time setup.
Decision checkpoint: before choosing this path, confirm which ERPNext major version you will run, who will build and sign off images, who restores backups in a drill, and who answers when a Frappe-specific error appears in the logs.
Which frappe_docker services an ERPNext stack needs
A production ERPNext stack from frappe_docker is a set of cooperating containers, and each one has a clear job. This section covers the six services the repository provides and what each needs from you. Confirm exact service names and file layout against the frappe_docker version your team pins.
MariaDB database
MariaDB holds every ERPNext site's data: documents, ledgers, stock movements and settings. Each site is a separate database, so the database service must exist before any site is created. If it goes down, pages fail to load and background jobs error out, and a damaged data volume can lose accounting history. Confirm which MariaDB version the pinned frappe_docker release expects, place its data directory on a volume with tested backups, and keep the database port off public networks so that only the application containers can reach it.
Redis cache and queue
Redis serves ERPNext in two roles: caching metadata and holding the queues that background jobs read from. When Redis stops, the web application may slow or fail, and queued work such as email and report generation stops moving. Check whether your pinned Compose file runs Redis for cache and queue as one service or as separate instances, and confirm that memory limits and persistence settings match how heavily your processes depend on queued work. Keep Redis on the internal network only, and set a password if the Compose file supports one.
Background workers
Workers run long and scheduled tasks outside the web request cycle, including emails, report builds, imports and integrations. Each worker consumes jobs from a queue, so the number of worker containers sets how many jobs can run in parallel. If workers stop, pages still respond, but submitted jobs sit unprocessed and users see delayed emails or stalled imports. Size the worker count against your heaviest job, such as large Data Import batches, and confirm that worker containers use the same image tag as the web containers.
Scheduler
The scheduler triggers periodic jobs defined by ERPNext and installed apps, such as recurring tasks and cleanup routines. Run it as a single instance per bench, because duplicate schedulers can execute the same job twice. If the scheduler stops, recurring tasks stop without any visible error on the user screens, so check its status after each deployment and after any change to scheduler settings. Confirm in the pinned repository how the scheduler is enabled and started in your Compose file.
Socket.io realtime service
The Socket.io service delivers realtime updates to the browser, such as notifications and live document changes. It depends on Redis and on the same site configuration as the web application, so a misconfigured Redis connection affects it too. If the service is down, pages still load but realtime notifications stop, and users may work from stale document views. Confirm which port it listens on in the pinned Compose file, route its WebSocket traffic through Nginx, and make sure the proxy passes the upgrade headers that keep those connections open.
Nginx reverse proxy
Nginx is the only service that should face users. It serves static assets, forwards requests to the web and Socket.io containers, and terminates TLS unless a load balancer in front of it does that job. A misconfiguration here can make the whole site unreachable or expose internal services directly. Set the public hostname and site routing through the environment settings the image reads, mount certificates with restricted file permissions, and confirm which host port is published. Test routing for every site before go-live.
Decide demo or production Compose, and where the image is built
This table compares the five deployment choices that shape ERPNext on frappe_docker, from the single-file demo to where the image is built and how Nginx is exposed. Read each row for the operational cost it adds, such as rebuild effort, patching ownership and data safety, and pick the option that matches how long the system must run.
| Decision | Option | When it fits | Operational cost |
|---|---|---|---|
| Setup file | Single-file demo setup | Short evaluations, demos and throwaway test sites where no business data is entered | Marked for short-lived evaluation only. Not suitable for data you need to keep or upgrade later |
| Setup file | Production Compose files | Any site that holds live accounting, stock or production records | You own volumes, backups, restarts and upgrade steps, and must maintain the Compose configuration yourself |
| Image source | Published official images | Standard ERPNext with no custom apps, or apps available in the published images | Lowest build effort, but custom apps must be added at runtime, which needs a rebuild path to repeat reliably |
| Image source | Custom image with custom apps baked in | Sites that depend on custom Frappe apps, integrations or third-party apps | You rebuild and retag on every app or ERPNext update, test the image, and own the registry and its access controls |
| Host layout | Single host for all services | Small user groups, pilot environments, or sites where a short outage during maintenance is acceptable | One failure takes down database, cache, workers and web together. Capacity is shared, so heavy jobs can slow the web tier |
| Host layout | Services split across hosts | Larger user counts, heavy background jobs, or a requirement to scale or replace individual services | More network paths, secrets and firewall rules to manage, and more hosts to patch and monitor |
| Database | MariaDB inside the Compose stack | Test environments and small sites where the team accepts running the database container | Backups, storage and version upgrades of MariaDB stay with your team. Volume loss is a data loss event |
| Database | External managed MariaDB | Organizations with an existing database service, backup policy and DBA support | Connection, parameter and version compatibility must be confirmed with the provider before cutover. Costs recur with the service |
| Ingress | Nginx exposed directly on the host | Single-site internal deployments or sites where the host is the only entry point | You manage TLS certificates, HTTP hardening and rate limits at the same layer that serves ERPNext |
| Ingress | Nginx behind an existing edge load balancer | Environments with an approved edge service handling TLS, WAF and access logs | You must confirm forwarded headers, timeouts for long requests and Socket.io WebSocket support at the edge |
How to build a production ERPNext stack with frappe_docker
This sequence takes a self-hosted ERPNext site from the choice of version to a production container stack that your team can rebuild, verify and roll back. Each step ends with a check you can run and record. The order matters because the version decision sets the image, and the pinned app inputs define what gets rebuilt later.
Confirm the ERPNext version and support window
Your product owner and platform lead choose the ERPNext major version before any image is selected. Version 14 reached end of life on January 31, 2026, according to Frappe's supported versions page, so it should not be the base for a new build. Version 15 is planned to be supported until the end of 2027 and version 16 until the end of 2029, per the same page. Confirm the current dates there, and if you want Frappe warranty coverage, confirm your version is listed and matches your support plan. The step is done when the target version and its end-of-support date are written into the project record.
Prepare the host and persistent storage
Your infrastructure team sizes the Docker host and creates storage for the database, site files and backups. Volumes must live outside the container filesystem so they survive image rebuilds and container replacement. Confirm the Docker and Compose versions your team supports, and confirm that the database volume sits on storage with tested backup access. Restart the container host once and check that each data directory still holds its contents. The step is done when a test file written to each volume is still present after the restart.
Move secrets out of the Compose file
Your platform engineer moves database credentials, Redis settings and site secrets into environment files or a secrets store that your team controls. The Compose file stays in version control with no passwords in it. Use separate values for each environment and restrict read access on the host. Check the frappe_docker documentation for which variables each service reads, because names can change between releases. The step is done when the rendered Compose configuration contains no password strings, which you can confirm with a search of that output.
Build a custom image with pinned apps
Your developers build a custom image using the frappe_docker build process and add the custom apps your processes need. Pin each app to a tagged release or commit that has been tested against your ERPNext version, and do not build from moving branches. Record the Frappe and ERPNext versions in the build inputs. Run the build in a CI pipeline your team controls so the same inputs produce the same image. The step is done when inspecting the built image lists each app with its pinned version and the build fails when a pin is missing.
Start the stack and create the first site
Your platform engineer starts the full stack from the Compose configuration and creates the first site with the bench tooling inside the backend container. Install ERPNext and each custom app on that site. Use a site name that matches the public domain you will publish. Confirm the containers report healthy and the site responds on its internal address. The step is done when you can log in with the administrator account on the internal address, open the ERPNext desk, and see every custom app in the installed apps list.
Configure the public domain and TLS
Your network or platform team points the public domain at the Nginx edge and installs TLS certificates there, from your certificate authority or an automated issuer your team already runs. Set the site host name so generated links use the public address. Restrict direct access to internal services so that only the edge is reachable from outside. The step is done when the site loads over HTTPS from outside your network, the certificate chain validates, and a document link in a test email uses the public domain.
Start workers and scheduler, then verify jobs
Your platform engineer starts the background workers, the scheduler and the Socket.io service alongside the web processes. Background jobs handle work such as email, scheduled tasks and long reports, so they must run before users depend on the system. Check each service's logs for errors after startup. Then trigger a test job, such as a scheduled email or a queued report, and watch it move through the queue. The step is done when the test job completes and the scheduler log shows regular activity.
Record image digests and app versions
Your release manager records the exact image digests, the Frappe and ERPNext tags or commits, and the version of each custom app in the build record. Include the site name and the database and Redis versions in use. Store this record with the Compose configuration in version control so a rebuild or rollback uses the same inputs. The step is done when someone who did not run the build can use the record to rebuild an identical image, and the digests reported by the running containers match the recorded values.
What drives the effort of a containerized ERPNext deployment
This table lists the factors that change how much work a containerized ERPNext deployment takes, how each one moves the effort, and what to put in place to keep it contained. Read it before requesting a quote, because each driver should appear as a line item or an explicit assumption in the written scope. The main takeaway is that the image build, the number of environments and the compliance evidence usually weigh more than the container setup itself.
| Driver | Effect on effort | How to keep it down |
|---|---|---|
| Number and size of sites on one stack | More sites share the same workers, scheduler and MariaDB, so sizing, load testing and backup windows grow with each site added | Agree the site count and expected user load in writing, and separate tenants or large sites onto their own stack where the business requires it |
| Number and complexity of custom apps built into the image | Each custom app must be compiled into the image, pinned to a Frappe and ERPNext version, and retested on every upgrade | Keep custom apps few and well-scoped, prefer standard customizations where they work, and pin versions in the build definition |
| Integrations that need network paths or webhooks | Firewall rules, DNS, TLS certificates, webhook endpoints and retry handling must be built and tested for each external system | List every integration with its direction, protocol and owner before scoping, and confirm which network paths the client can open |
| Number of environments that must match | Development, staging and production need the same image tags, app versions and configuration, which multiplies build, deploy and test steps | Use one image build promoted through environments, and keep environment differences limited to secrets and hostnames |
| Storage and backup volume | Larger databases and file stores lengthen backup, restore and copy times, and they require capacity planning for volumes and snapshots | Confirm expected data growth and attachment volume, and test a full restore on a copy of production before go-live |
| Compliance evidence produced from the stack | Access records, change logs, backup proof, vulnerability scans and configuration baselines must be generated and kept, which adds design and operating work | Define the evidence list with the assessor or internal audit first, then build logging, retention and reports into the deployment from the start |
| Internal team skill with Frappe and Docker | Teams without bench or Compose experience need more design review, handover and support, while experienced teams can run routine changes themselves | State the team's current skills in the scope, agree a handover plan with named roles, and ask the partner to document runbooks as part of delivery |
How the deployment model changes the work
On one host, the frappe_docker Compose files run the web, database, cache, worker, scheduler and Socket.io services side by side, so the platform team manages one set of containers, one set of volumes and one network. The single-file demo setup is marked for short-lived evaluation only, so a production run uses the production Compose configuration with persistent volumes and a plan for TLS in front of Nginx.
- Build: Custom apps are built into an image from your own app sources, and the same image runs every service that needs that code.
- Storage: MariaDB, site files and Redis data sit on volumes on that host, so disk sizing and snapshot schedules are the main storage decisions.
- Networking: Services communicate over the Compose network, and only the Nginx entry point is published to users.
- Operations: One host means one maintenance window for patching, upgrades and restarts, and the host itself is a single point of failure.
Confirm with your platform team which host, disk layout and backup tooling they will support, and whether a single host meets your recovery expectations.
Moving MariaDB and the background workers onto separate hosts changes the network path more than the images. Workers reach the database and Redis across the network, so latency, firewall rules and credentials become part of the design, and the scheduler and Socket.io services must still reach the same sites.
- Build: The same image tags must run on every host, because version drift between hosts causes failures that are hard to trace.
- Storage: The database host needs durable storage and its own backup routine, and every web and worker container must be able to reach the shared site files, which requires a decision on shared storage.
- Networking: Database and Redis ports should accept traffic only from the application hosts, and encryption between hosts needs an explicit decision.
- Operations: Each additional host adds patching, monitoring and access reviews, and scaling workers becomes a capacity decision for each host.
Confirm with your network and database teams how traffic, certificates and shared file storage will be handled before the topology is fixed.
Kubernetes and similar orchestrators replace Compose with scheduling, service discovery and rolling restarts, but the ERPNext services and their dependencies stay the same. Whether a community chart or hand-written manifests fit depends on the tooling your platform team has chosen. This page does not confirm chart or manifest support, so check it against your chosen tooling before planning around it.
- Build: Image builds and promotion move into the cluster's delivery pipeline, and each app release needs a registry the cluster can pull from.
- Storage: Persistent volumes, storage classes and backup integration for MariaDB and site files must be designed deliberately, since stateful services behave differently under rescheduling.
- Networking: Ingress, internal service names and network policies replace Compose networking, and Socket.io connections must work behind load balancing.
- Operations: Cluster upgrades, role-based access, secrets management and monitoring become shared responsibilities across teams.
- Air-gapped networks: Images, app sources and chart packages must be moved into the isolated network through an approved transfer path and mirrored into an internal registry.
Confirm with your platform team which orchestrator, chart or manifest tooling, storage class and registry they support before choosing this model.
Securing secrets, the Nginx edge and Server Scripts in containers
The controls below decide how exposed an ERPNext container deployment is before application hardening starts: where secrets live, which ports are reachable, how traffic is encrypted, who holds privileged accounts, and who can run code. Each card names a check to run against your own environment. Application-level hardening is covered in the separate security hardening topic.
Keep secrets out of images and Compose files
Database passwords, the Administrator password and API keys should reach containers at runtime, not inside custom images built with your apps or in Compose files committed to Git. Check that no value appears in image layers, build arguments or the repository, and that environment files or a secret store are excluded from version control. Confirm which variables the frappe_docker release you deploy expects, because names can change between releases.
Limit the ports that reach the network
Only the proxy that serves ERPNext should publish a port on a host interface. Review the published ports in your Compose file and with docker compose ps, and confirm that MariaDB, Redis, the workers, the scheduler and Socket.io are reachable only on the internal container network. Enforce the same rule at the host firewall and the cloud security group, because a port published by mistake stays exposed even when the application is locked down.
Terminate TLS at Nginx
The Nginx service in frappe_docker is where HTTPS should end for users and where plain HTTP should redirect. Decide who issues and renews certificates, and confirm that the proxy forwards WebSocket connections to the Socket.io service, which realtime features depend on. Test from outside your network, and confirm that the site URL in ERPNext matches the public HTTPS address so generated links use it.
Set up administrator and operator accounts
Replace the initial Administrator password on first start and store it in a password manager, not in a ticket or chat. Give each operator a named account with only the roles their job needs, and avoid shared logins. Record who holds the Administrator credential, since it carries full access and is a common target. Single sign-on options for operator accounts are covered in the identity integration topic.
Decide on Server Scripts deliberately
Server Scripts run Python on document events or as API endpoints, so they execute code inside the application server. From version 15 they are disabled by default and run only after the server_script_enabled setting is turned on. Frappe Cloud public shared benches do not allow them, so a team that needs them must host ERPNext where it controls the settings. If you enable them, limit who can create them and review each script before it goes live.
Keep demo setups away from production
The single-file demo setup in frappe_docker is marked for short-lived evaluation only, so it should never hold business data or face the internet. Confirm which Compose file your team started from and that the production setup, with its separate services, is the one deployed. Remove demo volumes and test accounts before go-live, and record the choice in your change log so reviewers can see it.
How to verify the stack and confirm it fails safely
A frappe_docker deployment is proven only when a defined set of checks passes after a restart and when controlled failures show the stack degrades in a known way. Start with the services that frappe_docker provides: MariaDB, Redis, the background workers, the scheduler, the Socket.io service and Nginx. After a full restart, every container should report healthy, and the logs for each one should show no repeated errors. Then confirm the scheduler is actually running jobs by checking the scheduled job log inside ERPNext for recent entries, and confirm that queued background jobs complete. A container that is up but idle is not evidence that the scheduler works.
Real-time updates are the check most often skipped. Log in with two separate browser sessions as different users, open the same document in both, and change a field in one session. The second session should show the update without a page reload. If it does not, check that the Socket.io service is reachable through Nginx and that the proxy passes the websocket upgrade headers. Next, confirm that file uploads persist. Attach a file to a record, recreate the application containers without removing volumes, and confirm the file still downloads with the same content. Confirm which volume holds the sites directory so you know exactly what must survive a recreation.
The restore test should run into a second, isolated stack with its own project name, volumes and network. Restore the most recent database backup and the matching files, then compare record counts, a sample of attachments and a few reports against the source. Use separate credentials and disable outgoing email in the second stack so restored data cannot reach users. For failure tests, stop one worker container while jobs are queued, confirm that the jobs wait and then complete when the worker returns, and check for duplicated postings. Remove an application container with Compose while leaving volumes in place, then bring it back and confirm the data is intact.
Rolling back to the previous image is the test most likely to surprise a team. Pin the earlier image tag in the Compose configuration and redeploy, then check whether the site starts cleanly. Image rollback does not reverse database migrations applied by a newer version, so confirm with your ERPNext version and its upgrade notes whether a restore from backup is the only safe path after a schema change. Record which path applies to your version before you need it.
Keep an evidence record for internal audit or external assessors: image names with digests, the Compose files and environment inventory with secrets removed, the date and operator of each test, command output, screenshots of the real-time and upload checks, backup and restore reports, and the outcome of each failure test. DeployOpen can prepare this evidence and the controls behind it, but independent auditors and certification bodies issue any assessment. The demo single-file setup is intended for short-lived evaluation only, so do not use it to generate evidence for a production system.
Questions teams ask before running ERPNext in Docker
How much does an outside ERPNext Docker deployment cost?
The cost follows the written scope, and DeployOpen quotes from that scope rather than from a price list. The main components are the discovery of your environment, building and hardening the frappe_docker setup on your infrastructure, building images that include any custom apps, data migration, backup and restore testing, handover documentation, and any ongoing support. Most of these are one-time costs. Hosting, backup storage, monitoring and internal admin time recur. Costs rise with the number of custom apps, the number of environments (staging, production, demo), integrations, and how much of your team will be trained. Ask any provider for a quote that lists each component separately, states what is excluded, and names who pays for hosting. Self-hosting ERPNext itself is free under GPL-3.0, so the quote covers labor and infrastructure, not a license.
How long does it take to deploy ERPNext with Docker?
No fixed duration applies to every team, so the schedule follows the agreed scope and your readiness. A setup with a single standard app, existing servers and a clear owner for decisions moves faster than one that needs new cloud accounts, custom app code, a migration from another system, or approval from several departments. Ask for a timeline tied to named milestones: environment access, a working staging stack, the first custom image build, a restore test, and production cutover. Also ask which of these depend on your team's responses, since delays usually come from waiting on access, decisions or test sign-off rather than from the Docker work itself.
Can our team run ERPNext on Docker without an outside partner?
Yes, a team with solid Docker and Compose skills and some familiarity with Frappe can run frappe_docker in production. The gaps teams most often hit are the image build pipeline for custom apps, and the upgrade cycle. ERPNext and Frappe release minor versions frequently, so someone must own the routine of rebuilding images, running bench migrate in staging, checking custom apps against the new version, and rolling back if needed. Also check that someone can operate MariaDB backups, Redis, the scheduler and the Socket.io service during an incident. If those responsibilities are clear and staffed, an internal team can own the deployment; if not, a partner can close the gaps for a defined period.
What do we need to provide before a Docker deployment starts?
The work depends on access and decisions from your side. Expect to provide access to the target cloud accounts, virtual machines or data center hosts, and a network path for DNS, TLS certificates and any identity provider. You need separate environments for staging and production, and ideally a demo or test site for training. If you use custom apps, provide the source code, its repository access and the list of Frappe versions it supports. Name a backup target with retention requirements and a restore owner. Finally, assign people who can decide on domain names, data retention, user roles and go-live timing, because open decisions are the most common cause of delay.
Is ERPNext free to self-host?
Yes. ERPNext is free and open source under GPL-3.0, and the ERPNext pricing page states that self-hosting costs nothing in software fees. Running it still has costs. You pay for servers or cloud resources, the deployment work, custom app development and maintenance, upgrades, backups, and any support contract you choose. The pricing page also lists Frappe Cloud as a hosted option, with shared site and server plans starting at published amounts, and it notes that implementation is available through certified partners. Compare self-hosting and hosted options on total yearly cost, including staff time, rather than on the license line alone.
Which Frappe version should we pick for a new Docker deployment?
Pick a version that is still in its support window at go-live and plan the upgrade path before you commit. Frappe's supported versions page lists version 14 as end of life, with version 15 supported until the end of 2027 and version 16 until the end of 2029. Check the current status on that page before you start, because support dates can change. Confirm that every custom app you plan to use supports the same major version. A new deployment on an older major version creates an upgrade project within a few years, so ask your implementer to show the plan for moving to the next major release.
Can the frappe_docker demo setup be used in production?
No. The frappe_docker single-file demo setup is intended for short-lived evaluation only. A production stack separates MariaDB, Redis, background workers, the scheduler, the Socket.io service and Nginx into their own services, with persistent volumes, backups, TLS and monitoring. Use the demo to learn the layout and to test ERPNext features, then build the production Compose configuration and images from the official frappe_docker files. Ask the implementer to show which settings differ between the demo and production, and to document how the environments are rebuilt.
How DeployOpen works on this
DeployOpen plans, builds, hardens and supports self-hosted ERPNext inside your own cloud accounts, data centers or air-gapped networks. For Docker deployments, we start from the official frappe_docker images and Compose files, add your custom apps, and agree the scope in writing before work begins. The result is a deployment your team can run, document and upgrade.
How we scope
- The written scope names which ERPNext version, apps and sites the Docker deployment will run.
- It sets out the hosts, container runtime, database and Redis layout, and where the images are hosted.
- Engagements are fixed-scope, so deliverables and timelines are agreed in writing before work starts.
How we build
- Choose between the production frappe_docker setup and the single-file demo, which is for short-lived evaluation only.
- Build custom app images from your pinned repositories, then test them against the same ERPNext version before go-live.
- Verify MariaDB, Redis, worker, scheduler and Socket.io services start, connect and recover cleanly after a container restart.
How we hand over
- Deliver documentation for images, Compose files, environment variables, volumes and the bench command sequence used.
- Walk your operations team through backups, restores, image rebuilds and how to read service logs.
- Provide a written handover covering access paths, secret storage locations and open items.
How we support
- Ongoing support, upgrades and continuous testing are available as retainers, scoped separately from the build.
- Retainer work can cover image rebuilds for ERPNext minor releases and bench update and migrate runs in staging.
- Confirm with Frappe whether your ERPNext version is listed and whether a matching Frappe Cloud support plan applies.

