docs: reorganize container setup information into new subfolder docs/container-setup (#1720)
This commit is contained in:
47
docs/container-setup/01-overview.md
Normal file
47
docs/container-setup/01-overview.md
Normal file
@@ -0,0 +1,47 @@
|
||||
The purpose of this document is to give you an overview of how the Frappe Docker containers are structured.
|
||||
|
||||
# 🐳 Images
|
||||
|
||||
There are **four predefined Dockerfiles** available in the `/images` directory.
|
||||
|
||||
| Dockerfile | Ingredients | Purpose & Use Case |
|
||||
| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **bench** | Sets up only the Bench CLI. | Used for **development** or debugging. Provides the command-line tooling but does not include runtime services. |
|
||||
| **custom** | Multi-purpose Python backend built from a plain Python image. Includes everything needed to run a Frappe instance via a Compose setup. Installs apps defined in `apps.json`. | Suitable for **production** and **testing**. Ideal when you need control over dependencies (e.g. trying new Python or Node versions). |
|
||||
| **layered** | Final contents are the same as `custom`, but it is based on **prebuilt images from [Docker Hub](https://hub.docker.com/u/frappe)**. | Great for **production builds** when you’re fine with the dependency versions managed by Frappe. Builds much faster since the base layers are already prepared. |
|
||||
| **production** | Similar to `custom` (built from a Python base image), but installs **only Frappe and ERPNext**. Not customizable with `apps.json`. | Best for **quick starts** or exploration. For real deployments or CI/CD pipelines, `custom` or `layered` are preferred because they offer more flexibility. |
|
||||
|
||||
---
|
||||
|
||||
These images include everything needed to run all processes required by the Frappe framework
|
||||
(see [Bench Procfile reference](https://frappeframework.com/docs/v14/user/en/bench/resources/bench-procfile)).
|
||||
|
||||
- The `bench` image only sets up the CLI tool.
|
||||
- The other images (`custom`, `layered`, and `production`) go further — enabling a nearly **plug-and-play** setup for ERPNext and custom apps.
|
||||
|
||||
> We use [multi-stage builds](https://docs.docker.com/develop/develop-images/multistage-build/) and [Docker Buildx](https://docs.docker.com/engine/reference/commandline/buildx/) to maximize layer reuse and make our builds more efficient.
|
||||
|
||||
# 🏗️ Compose
|
||||
|
||||
Once images are built, containers are orchestrated using a [compose file](https://docs.docker.com/compose/compose-file/). The main compose.yaml provides core services, networking, and volumes for any Frappe setup.
|
||||
|
||||
## 🛠️ Services
|
||||
|
||||
| Service | Role | Purpose |
|
||||
| ---------------- | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **configurator** | Setup | Updates `common_site_config.json` so Frappe knows how to access db and redis. It is executed on every `docker-compose up` (and exited immediately). Other services start after this container exits successfully |
|
||||
| **backend** | Runtime | [Werkzeug server](https://werkzeug.palletsprojects.com/en/2.0.x/) |
|
||||
| **frontend** | Proxy | [nginx](https://www.nginx.com) server that serves JS/CSS assets and routes incoming requests |
|
||||
| **websocket** | Real-time | Node server that runs [Socket.IO](https://socket.io) |
|
||||
| **queue-\_** | Background Jobs | Python servers that run job queues using [rq](https://python-rq.org) |
|
||||
| **scheduler** | Task Automation | Python server that runs tasks on schedule using [schedule](https://schedule.readthedocs.io/en/stable/) |
|
||||
|
||||
## 🧩 Overrides
|
||||
|
||||
Additional functionality can be added using [overrides](https://docs.docker.com/compose/extends/). These files modify existing services or add new ones without changing the main `compose.yaml`.
|
||||
|
||||
Example: The main compose file has no database service, but `compose.mariadb.yaml` adds MariaDB. See [overrider.md](overrider.md) for the complete list of available overrides and how to use them.
|
||||
|
||||
---
|
||||
|
||||
**Next:** [Build Setup →](02-build-setup.md)
|
||||
121
docs/container-setup/02-build-setup.md
Normal file
121
docs/container-setup/02-build-setup.md
Normal file
@@ -0,0 +1,121 @@
|
||||
This guide walks you through building Frappe images from the repository resources.
|
||||
|
||||
# Prerequisites
|
||||
|
||||
- git
|
||||
- docker or podman
|
||||
- docker compose v2 or podman compose
|
||||
|
||||
> Install containerization software according to the official maintainer documentation. Avoid package managers when not recommended, as they frequently cause compatibility issues.
|
||||
|
||||
# Clone this repo
|
||||
|
||||
```bash
|
||||
git clone https://github.com/frappe/frappe_docker
|
||||
cd frappe_docker
|
||||
```
|
||||
|
||||
# Define custom apps
|
||||
|
||||
If you dont want to install specific apps to the image skip this section.
|
||||
|
||||
To include custom apps in your image, create an `apps.json` file in the repository root:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"url": "https://github.com/frappe/erpnext",
|
||||
"branch": "version-15"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/frappe/hrms",
|
||||
"branch": "version-15"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/frappe/helpdesk",
|
||||
"branch": "main"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
Then generate a base64-encoded string from this file:
|
||||
|
||||
```bash
|
||||
export APPS_JSON_BASE64=$(base64 -w 0 apps.json)
|
||||
```
|
||||
|
||||
# Build the image
|
||||
|
||||
Choose the appropriate build command based on your container runtime and desired image type. This example builds the `layered` image with the custom `apps.json` you created.
|
||||
|
||||
`Docker`:
|
||||
|
||||
```bash
|
||||
docker build \
|
||||
--build-arg=FRAPPE_PATH=https://github.com/frappe/frappe \
|
||||
--build-arg=FRAPPE_BRANCH=version-15 \
|
||||
--build-arg=APPS_JSON_BASE64=$APPS_JSON_BASE64 \
|
||||
--tag=custom:15 \
|
||||
--file=images/layered/Containerfile .
|
||||
```
|
||||
|
||||
`Podman`:
|
||||
|
||||
```bash
|
||||
podman build \
|
||||
--build-arg=FRAPPE_PATH=https://github.com/frappe/frappe \
|
||||
--build-arg=FRAPPE_BRANCH=version-15 \
|
||||
--build-arg=APPS_JSON_BASE64=$APPS_JSON_BASE64 \
|
||||
--tag=custom:15 \
|
||||
--file=images/layered/Containerfile .
|
||||
```
|
||||
|
||||
## Build args
|
||||
|
||||
| Arg | Purpose |
|
||||
| -------------------- | --------------------------------------------------------------------------------------------- |
|
||||
| **Frappe Framework** | |
|
||||
| FRAPPE_PATH | Repository URL for Frappe framework source code. Defaults to https://github.com/frappe/frappe |
|
||||
| FRAPPE_BRANCH | Branch to use for Frappe framework. Defaults to version-15 |
|
||||
| **Custom Apps** | |
|
||||
| APPS_JSON_BASE64 | Base64-encoded JSON string from apps.json defining apps to install |
|
||||
| **Dependencies** | |
|
||||
| PYTHON_VERSION | Python version for the base image |
|
||||
| NODE_VERSION | Node.js version |
|
||||
| WKHTMLTOPDF_VERSION | wkhtmltopdf version |
|
||||
| **bench only** | |
|
||||
| DEBIAN_BASE | Debian base version for the bench image, defaults to `bookworm` |
|
||||
| WKHTMLTOPDF_DISTRO | use the specified distro for debian package. Default is `bookworm` |
|
||||
|
||||
# env file
|
||||
|
||||
The compose file requires several environment variables. You can either export them on your system or create a `.env` file.
|
||||
|
||||
```bash
|
||||
cp example.env custom.env
|
||||
```
|
||||
|
||||
Edit `custom.env` to customize variables for your setup. The template includes common variables, but you can add, modify, or remove any as needed. See [env-variables.md](env-variables.md) for detailed descriptions of all available variables.
|
||||
|
||||
# Creating the final compose file
|
||||
|
||||
Combine the base compose file with appropriate overrides for your use case. This example adds MariaDB, Redis, and exposes ports on `:8080`:
|
||||
|
||||
```bash
|
||||
docker compose --env.file example.env \
|
||||
-f compose.yaml \
|
||||
-f overrides/compose.mariadb.yaml \
|
||||
-f overrides/compose.redis.yaml \
|
||||
-f overrides/compose.noproxy.yaml \
|
||||
config > compose.custom.yaml
|
||||
```
|
||||
|
||||
This generates `compose.custom.yaml`, which you'll use to start all containers. Customize the overrides and environment variables according to your requirements.
|
||||
|
||||
> **NOTE**: podman compose is just a wrapper, it uses docker-compose if it is available or podman-compose if not. podman-compose have an issue reading .env files ([Issue](https://github.com/containers/podman-compose/issues/475)) and might create an issue when running the containers.
|
||||
|
||||
---
|
||||
|
||||
**Next:** [Start Setup →](03-start-setup.md)
|
||||
|
||||
**Back:** [Container Overview ←](01-overview.md)
|
||||
42
docs/container-setup/03-start-setup.md
Normal file
42
docs/container-setup/03-start-setup.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# start Container
|
||||
|
||||
Once your compose file is ready, start all containers with a single command:
|
||||
|
||||
```bash
|
||||
docker compose -p frappe -f compose.custom.yaml up -d
|
||||
```
|
||||
|
||||
```bash
|
||||
podman-compose --in-pod=1 --project-name frappe -f compose.custom.yaml up -d
|
||||
```
|
||||
|
||||
The `-p` (or `--project-name`) flag names the project `frappe`, allowing you to easily reference and manage all containers together.
|
||||
|
||||
# Create a site and install apps
|
||||
|
||||
Frappe is now running, but it's not yet configured. You need to create a site and install your apps.
|
||||
|
||||
```bash
|
||||
docker compose -p frappe exec backend bench new-site <sitename> --mariadb-user-host-login-scope='172.%.%.%'
|
||||
docker compose -p frappe exec backend bench --site <sitename> install-app erpnext
|
||||
```
|
||||
|
||||
```bash
|
||||
podman exec -ti erpnext_backend_1 /bin/bash
|
||||
bench new-site <sitename> --mariadb-user-host-login-scope='172.%.%.%'
|
||||
bench --site <sitename> install-app erpnext
|
||||
```
|
||||
|
||||
Replace `<sitename>` with your desired site name.
|
||||
|
||||
> ## Understanding the MariaDB User Scope
|
||||
>
|
||||
> The flag --mariadb-user-host-login-scope='172.%.%.%' allows database connections from any IP address within the 172.0.0.0/8 range. This includes all containers and virtual machines running on your machine.
|
||||
>
|
||||
> **Why is this necessary?** Docker and Podman assign dynamic IP addresses to containers. If you set a fixed IP address instead, database connections will fail when the container restarts and receives a new IP. The wildcard pattern ensures connections always work, regardless of IP changes.
|
||||
>
|
||||
> **Security note:** This scope is sufficient because only the backend container accesses the database. If you need external database access, adjust the scope accordingly, but be cautious with overly permissive settings.
|
||||
|
||||
---
|
||||
|
||||
**Back:** [Build Setup →](02-build-setup.md)
|
||||
112
docs/container-setup/env-variables.md
Normal file
112
docs/container-setup/env-variables.md
Normal file
@@ -0,0 +1,112 @@
|
||||
# Environment Variables Reference
|
||||
|
||||
Environment variables configure your Frappe Docker setup. They can be set directly in the container or defined in a `.env` file referenced by Docker Compose.
|
||||
|
||||
**Getting Started:**
|
||||
|
||||
```bash
|
||||
cp example.env .env
|
||||
```
|
||||
|
||||
Then edit `.env` and set variables according to your needs.
|
||||
|
||||
---
|
||||
|
||||
## Required Variables
|
||||
|
||||
| Variable | Purpose | Example | Notes |
|
||||
| ----------------- | ------------------------------------------------ | -------------------------------- | ---------------------------------------------------------------- |
|
||||
| `FRAPPE_PATH` | Frappe framework path | https://github.com/frappe/frappe | |
|
||||
| `FRAPPE_BRANCH` | Frappe Branch | `version-15` | See [Frappe releases](https://github.com/frappe/frappe/releases) |
|
||||
| `ERPNEXT_VERSION` | ERPNext release version | `v15.67.0` | Required although its never used |
|
||||
| `DB_PASSWORD` | Password for database root (MariaDB or Postgres) | `secure_password_123` | Not needed if using `DB_PASSWORD_SECRETS_FILE` |
|
||||
|
||||
---
|
||||
|
||||
## Database Configuration
|
||||
|
||||
| Variable | Purpose | Default | When to Set |
|
||||
| -------------------------- | ----------------------------------------- | ------------------------------------ | ---------------------------------- |
|
||||
| `DB_PASSWORD` | Database root user password | 123 | Always (unless using secrets file) |
|
||||
| `DB_PASSWORD_SECRETS_FILE` | Path to file containing database password | — | Setup mariadb-secrets overrider |
|
||||
| `DB_HOST` | Database hostname or IP | `db` (service name) | Only if using external database |
|
||||
| `DB_PORT` | Database port | `3306` (MariaDB) / `5432` (Postgres) | Only if using external database |
|
||||
|
||||
---
|
||||
|
||||
## Redis Configuration
|
||||
|
||||
| Variable | Purpose | Default | When to Set |
|
||||
| ------------- | --------------------------------------------------- | ---------------------------- | ------------------------------------- |
|
||||
| `REDIS_CACHE` | Redis hostname for caching | `redis-cache` (service name) | Only if using external Redis instance |
|
||||
| `REDIS_QUEUE` | Redis hostname for job queues and real-time updates | `redis-queue` (service name) | Only if using external Redis instance |
|
||||
|
||||
---
|
||||
|
||||
## HTTPS & SSL Configuration
|
||||
|
||||
| Variable | Purpose | Default | When to Set |
|
||||
| ------------------- | ------------------------------------------------ | ------- | ---------------------------------------- |
|
||||
| `LETSENCRYPT_EMAIL` | Email for Let's Encrypt certificate registration | — | Required if using HTTPS override |
|
||||
| `SITES` | List of domains for SSL certificates | — | Required if using reverse proxy override |
|
||||
|
||||
**Format for `SITES`:**
|
||||
|
||||
```bash
|
||||
# Single site
|
||||
SITES=`mysite.example.com`
|
||||
|
||||
# Wildcard (any subdomain)
|
||||
SITES=`{any:.+}`
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Site Configuration
|
||||
|
||||
| Variable | Purpose | Default | When to Set |
|
||||
| ------------------------- | -------------------------------- | ---------------------------------------- | ----------------------------------------------- |
|
||||
| `FRAPPE_SITE_NAME_HEADER` | Site name for multi-tenant setup | `$host` (resolved from request hostname) | When accessing by IP or need explicit site name |
|
||||
|
||||
**Examples:**
|
||||
|
||||
If your site is named `mysite` but you want to access it via `127.0.0.1`:
|
||||
|
||||
```bash
|
||||
FRAPPE_SITE_NAME_HEADER=mysite
|
||||
```
|
||||
|
||||
If your site is named `example.com` and you access it via that domain, no need to set this (defaults to hostname).
|
||||
|
||||
---
|
||||
|
||||
## Image Configuration
|
||||
|
||||
| Variable | Purpose | Default | Notes |
|
||||
| ---------------- | ------------------------------ | --------------------- | ------------------------------------------------------- |
|
||||
| `CUSTOM_IMAGE` | Custom Docker image repository | Frappe official image | Leave empty to use default |
|
||||
| `CUSTOM_TAG` | Custom Docker image tag | Latest stable | Corresponds to `FRAPPE_VERSION` |
|
||||
| `PULL_POLICY` | Image pull behavior | `always` | Options: `always`, `never`, `if-not-present` |
|
||||
| `RESTART_POLICY` | Container restart behavior | `unless-stopped` | Options: `no`, `always`, `unless-stopped`, `on-failure` |
|
||||
|
||||
---
|
||||
|
||||
## Nginx Proxy Configuration
|
||||
|
||||
| Variable | Purpose | Default | Allowed Values |
|
||||
| ---------------------- | ---------------------------------- | -------------- | -------------------------------------------- |
|
||||
| `BACKEND` | Backend service address and port | `0.0.0.0:8000` | `{host}:{port}` |
|
||||
| `SOCKETIO` | Socket.IO service address and port | `0.0.0.0:9000` | `{host}:{port}` |
|
||||
| `HTTP_PUBLISH_PORT` | Published HTTP port | `8080` | Any available port |
|
||||
| `PROXY_READ_TIMEOUT` | Upstream request timeout | `120s` | Any nginx timeout value (e.g., `300s`, `5m`) |
|
||||
| `CLIENT_MAX_BODY_SIZE` | Maximum upload file size | `50m` | Any nginx size value (e.g., `100m`, `1g`) |
|
||||
|
||||
### Real IP Configuration (Behind Proxy)
|
||||
|
||||
Use these variables when running behind a reverse proxy or load balancer:
|
||||
|
||||
| Variable | Purpose | Default |
|
||||
| ---------------------------- | ------------------------------------------------- | ----------------- |
|
||||
| `UPSTREAM_REAL_IP_ADDRESS` | Trusted upstream IP address for real IP detection | `127.0.0.1` |
|
||||
| `UPSTREAM_REAL_IP_HEADER` | Request header containing client IP | `X-Forwarded-For` |
|
||||
| `UPSTREAM_REAL_IP_RECURSIVE` | Enable recursive IP search | `off` |
|
||||
27
docs/container-setup/overrider.md
Normal file
27
docs/container-setup/overrider.md
Normal file
@@ -0,0 +1,27 @@
|
||||
Overrides extend the base compose.yaml with additional services or modify existing behavior. Include them in your compose command using multiple -f flags.
|
||||
|
||||
```bash
|
||||
docker compose -f compose.yaml -f overrides/compose.mariadb.yaml -f overrides/compose.redis.yaml config > compose.custom.yaml
|
||||
```
|
||||
|
||||
| Overrider | Purpose | Additional Info |
|
||||
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
|
||||
| **Database** | | |
|
||||
| compose.mariadb.yaml | Adds MariaDB database service | set `DB_PASSWORD` or default Password will be used |
|
||||
| compose.mariadb-secrets.yaml | Adds MariaDB with password from a secret file instead of environment variable | Set `DB_PASSWORD_SECRETS_FILE` to the path of your secret file |
|
||||
| compose.mariadb-shared.yaml | Makes MariaDB available on a shared network (mariadb-network) for other services | set `DB_PASSWORD` |
|
||||
| compose.postgres.yaml | Uses PostgreSQL instead of MariaDB as the database | set `DB_PASSWORD` |
|
||||
| **Proxy** | | |
|
||||
| compose.noproxy.yaml | Exposes the application directly on port `:8080` without a reverse proxy | |
|
||||
| compose.proxy.yaml | Uses Traefik as HTTP reverse proxy on port `:80` | You can change the published port by setting `HTTP_PUBLISH_PORT` |
|
||||
| compose.https.yaml | Uses Traefik as HTTPS reverse proxy on Port `:443` with automatic HTTP-to-HTTPS redirect | `SITES` and `LETSENCRYPT_EMAIL` must be set. `HTTP_PUBLISH_PORT` and `HTTPS_PUBLISH_PORT` can be set. |
|
||||
| **Redis** | | |
|
||||
| compose.redis.yaml | Adds Redis service for caching and background job queuing |
|
||||
| **TBD** | **The following overrides are available but lack documentation. If you use them and understand their purpose, please consider contributing to this documentation.** |
|
||||
| compose.backup-cron.yaml | | |
|
||||
| compose.custom-domain-ssl.yaml | | |
|
||||
| compose.custom-domain.yaml | | |
|
||||
| compose.multi-bench-ssl.yaml | | |
|
||||
| compose.multi-bench.yaml | | |
|
||||
| compose.traefik-ssl.yaml | | |
|
||||
| compose.traefik.yaml | | |
|
||||
Reference in New Issue
Block a user