Frappe Docker Setup (Custom Image + App)
Based on frappe_docker
This guide walks through deploying a custom Frappe app using Docker — from cloning frappe_docker and building a custom image with your app baked in, to spinning up containers and creating the first site. It also covers offline/air-gapped deployment for servers without internet access.
1. Clone Repository
mkdir frappe-wiki
cd frappe-wiki
git clone --depth 1 https://github.com/frappe/frappe_docker .2. Define Apps (apps.json)
[
{
"url": "https://github.com/frappe/wiki",
"branch": "develop"
}
]3. Build Custom Image
Recommended (BuildKit)
docker build \
--build-arg=FRAPPE_PATH=https://github.com/frappe/frappe \
--build-arg=FRAPPE_BRANCH=version-16 \
--secret=id=apps_json,src=apps.json \
--tag=custom:16 \
--file=images/layered/Containerfile .For Older Docker Versions
export APPS_JSON_BASE64=$(base64 -w 0 apps.json)
docker build \
--build-arg=FRAPPE_PATH=https://github.com/frappe/frappe \
--build-arg=FRAPPE_BRANCH=version-16 \
--build-arg=APPS_JSON_BASE64=$APPS_JSON_BASE64 \
--tag=custom:16 \
--file=images/layered/Containerfile .4. Environment Configuration (custom.env)
ERPNEXT_VERSION=v16.13.0
DB_PASSWORD=123
FRAPPE_SITE_NAME_HEADER=wiki.localhost
HTTP_PUBLISH_PORT=8072
CUSTOM_IMAGE=custom
CUSTOM_TAG=16
PULL_POLICY=missing5. Generate Compose File
docker compose --env-file custom.env \
-f compose.yaml \
-f overrides/compose.mariadb.yaml \
-f overrides/compose.redis.yaml \
-f overrides/compose.noproxy.yaml \
config > compose.custom.yamlOffline / Air-Gapped Setup
Steps 1–5 can be done locally (if server doesn’t have internet connection).
-
Export and compress image
docker save -o container_image.tar custom:16 zip container_image.tar.zip container_image.tar -
Copy to server Copy
container_image.tar.zip,custom.env, andcompose.custom.yamlto a project-named folder on the server. -
Verify files
ls # compose.custom.yaml container_image.tar.zip custom.env -
Load image on server
unzip container_image.tar.zip docker load -i container_image.tar
6. Reset Existing Deployment (if Exists)
docker compose -p frappe-wiki -f compose.custom.yaml downAvoid
-v— this destroys volumes with all container data.-p frappe-wikiis the project name; each project should have a unique name.
7. Start Containers
docker compose -p frappe-wiki -f compose.custom.yaml up -d8. Verify Containers
docker ps | grep frappe-wikiExpected: containers running with port mapping 8072 → 8080
9. Setup Site and Install App
Enter Backend Container
docker compose -p frappe-wiki -f compose.custom.yaml exec backend bashCreate Site
bench new-site wiki.localhostWhen prompted:
MariaDB root user: root
Password: 123
(db password from custom.env)
Set Default Site
bench use wiki.localhostInstall App
bench install-app wikiRestart
bench restart10. Access Application
Test locally:
curl localhost:8072 | head -10If response shows "does not exist":
curl -H "Host: wiki.localhost" localhost:8072 | head -1011. Network Access
curl <public_or_network_ip>:8072 | head -10or
curl -H "Host: wiki.localhost" <public_or_network_ip>:8072 | head -10Examples: 172.18.x.x, 10.x.x.x
12. Open Firewall (RHEL/CentOS)
sudo firewall-cmd --zone=public --add-port=8072/tcp --permanent
sudo firewall-cmd --reloadTroubleshooting
Site Not Resolving
Use Host header:
curl -H "Host: wiki.localhost" localhost:8072Database Connection Issues
Run inside backend container:
bench new-site wiki.localhost \
--db-host mariadb \
--mariadb-root-password 123 \
--admin-password admin_password_hereIf Still Not Working
- Verify containers are running
- Check logs:
docker compose -p frappe-wiki -f compose.custom.yaml logs - Ensure port
8072is open