BuildKit has been the default builder since Docker Engine 23.0 (Feb 2023), so prefixing the example build commands with DOCKER_BUILDKIT=1 is redundant on any supported install. Replace the prefix with an explicit prerequisite note so the requirement lives with the user's environment, not the example. The build relies on BuildKit secret mounts (--secret) to keep apps.json tokens out of image layers, which is why a real BuildKit-default engine is mandatory rather than merely recommended. Addresses review feedback on PR #1861.
6.4 KiB
| title |
|---|
| Single Server Example |
Single Server Example (nginx-proxy + acme-companion)
This guide demonstrates a single-server setup using nginx-proxy and acme-companion for HTTPS. It is best for a small number of hostnames and a single bench. If you need multiple benches or advanced routing, use the Traefik-based example instead.
We will setup the following:
- Install Docker and Docker Compose v2 on a Linux server.
- Use nginx-proxy + acme-companion for HTTPS (Let's Encrypt).
- Install MariaDB and Redis via containers.
- Setup one project called
erpnextwith siteserp.your-domain.comandcrm.your-domain.com.
Requirements
- A server that can run Docker Engine v23.0+ (recommended: 2 vCPU, 4 GB RAM, 50 GB SSD). The custom-image build below uses BuildKit secrets, which require BuildKit as the default builder (Docker Engine 23.0+).
- A public domain with DNS control.
- Two subdomains pointing to your server IP (A/AAAA records):
erp.your-domain.comcrm.your-domain.com
- Ports 80 and 443 reachable from the internet (required for Let's Encrypt HTTP-01).
Install Docker
Docker can be installed on a variety of systems. The easiest way to do this is with the convenience script.
| Platform | Convenience script | Using repository |
|---|---|---|
| CentOS | Link | Link |
| Debian | Link | Link |
| Ubuntu | Link | Link |
| Fedora | Link | Link |
Then do the post-installation steps. This will ensure that the permissions are easier to use and that Docker will start up with the System. Post-Installation Steps
Prepare
Clone frappe_docker and change the current working directory to the repo.
git clone https://github.com/frappe/frappe_docker
cd frappe_docker
Create a configuration directory:
mkdir ~/gitops
Optional: Build a custom image
If you need extra apps (beyond Frappe/ERPNext), build a custom image. Otherwise, skip this section and use the default images.
Create apps.json (each entry is a Git repo + branch):
cat > ~/gitops/apps.json <<'EOF'
[
{
"url": "https://github.com/frappe/erpnext",
"branch": "version-16"
},
{
"url": "https://github.com/frappe/payments",
"branch": "version-16"
}
]
EOF
Example for CRM only:
cat > ~/gitops/apps.json <<'EOF'
[
{
"url": "https://github.com/frappe/crm",
"branch": "main"
}
]
EOF
Build the image, passing apps.json as a BuildKit secret so that private repo tokens are never stored in image layers. This requires Docker Engine v23.0+, where BuildKit is the default builder:
docker build \
--build-arg=FRAPPE_PATH=https://github.com/frappe/frappe \
--build-arg=FRAPPE_BRANCH=version-16 \
--secret=id=apps_json,src=$HOME/gitops/apps.json \
--tag=my-erpnext-prod-image:16.0.0 \
--file=images/layered/Containerfile .
Configure environment
Create an environment file for the bench:
cp example.env ~/gitops/erpnext.env
sed -i 's/DB_PASSWORD=123/DB_PASSWORD=changeit/g' ~/gitops/erpnext.env
echo 'NGINX_PROXY_HOSTS=erp.your-domain.com,crm.your-domain.com' >> ~/gitops/erpnext.env
echo 'LETSENCRYPT_EMAIL=admin@your-domain.com' >> ~/gitops/erpnext.env
Notes:
- Replace
changeitwith a strong password. - Replace domains and email with your production values.
NGINX_PROXY_HOSTSis a comma-separated list without spaces.- If you built a custom image, add:
echo "CUSTOM_IMAGE=my-erpnext-prod-image" >> ~/gitops/erpnext.env
echo "CUSTOM_TAG=16.0.0" >> ~/gitops/erpnext.env
Generate compose config
Create the rendered compose file:
docker compose --project-name erpnext \
--env-file ~/gitops/erpnext.env \
-f compose.yaml \
-f overrides/compose.mariadb.yaml \
-f overrides/compose.redis.yaml \
-f overrides/compose.nginxproxy.yaml \
-f overrides/compose.nginxproxy-ssl.yaml config > ~/gitops/erpnext.yaml
Start the stack:
docker compose --project-name erpnext -f ~/gitops/erpnext.yaml up -d
This starts MariaDB and Redis containers as part of the same stack.
Create sites
# erp.your-domain.com
docker compose --project-name erpnext exec backend \
bench new-site --mariadb-user-host-login-scope=% --db-root-password changeit --install-app erpnext --admin-password changeit erp.your-domain.com
# crm.your-domain.com
docker compose --project-name erpnext exec backend \
bench new-site --mariadb-user-host-login-scope=% --db-root-password changeit --install-app erpnext --admin-password changeit crm.your-domain.com
Notes
- Let's Encrypt requires ports 80 and 443 to be reachable from the internet.
- If you cannot expose these ports (LAN-only), omit
compose.nginxproxy-ssl.yamland use HTTP or a local TLS proxy like Caddy. - Replace
changeitwith a strong DB root password and set a strong admin password per site.
Site operations
Refer: site operations
Troubleshooting (ACME / certificates)
- No certificate issued: Verify DNS points to the server IP and ports 80/443 are reachable from the internet.
- ACME errors in logs: Check
acme-companionlogs for the exact challenge error. - Wrong hostname: Ensure the domain is included in
NGINX_PROXY_HOSTSand that you restarted the stack after edits.