mirror of
https://github.com/frappe/frappe_docker.git
synced 2026-06-17 13:55:08 +00:00
Compare commits
55 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
825536a998 | ||
|
|
91fc59a134 | ||
|
|
f5eae9dffc | ||
|
|
7ef1d3e664 | ||
|
|
55cbf8e31f | ||
|
|
a1d4499fae | ||
|
|
1e3d40fa65 | ||
|
|
f60da9b964 | ||
|
|
25477c9e08 | ||
|
|
b7a0badaf0 | ||
|
|
3fccc2f9e7 | ||
|
|
6fccccf6d1 | ||
|
|
6526ab8cd4 | ||
|
|
c7da80ea3f | ||
|
|
4e5a578801 | ||
|
|
6695bb7b03 | ||
|
|
8c47ee9eb5 | ||
|
|
6377a34c61 | ||
|
|
e64251a86a | ||
|
|
cb0eda5214 | ||
|
|
0cb8df1631 | ||
|
|
930d44603a | ||
|
|
08d765c413 | ||
|
|
c710eef89e | ||
|
|
33f24b2645 | ||
|
|
640b761a3d | ||
|
|
73b029945b | ||
|
|
38ca8d2316 | ||
|
|
48764b21c1 | ||
|
|
19259e9d02 | ||
|
|
6e1117bbbc | ||
|
|
2c44349a0f | ||
|
|
5097115d08 | ||
|
|
cfd280eff3 | ||
|
|
aafc25bc76 | ||
|
|
e31bcceac1 | ||
|
|
eeb487e5e6 | ||
|
|
cec5b93546 | ||
|
|
d07d805436 | ||
|
|
5abd3c0f95 | ||
|
|
004b27a5a7 | ||
|
|
37e91a2db2 | ||
|
|
c363f459a4 | ||
|
|
09fcd3e83b | ||
|
|
8f4130b5d3 | ||
|
|
93ade44c6b | ||
|
|
f2d96ab8eb | ||
|
|
c7ac6b7666 | ||
|
|
0a04e5ecd2 | ||
|
|
c302af9dd5 | ||
|
|
d24093469d | ||
|
|
2af7b06f8d | ||
|
|
5d9f2e41a0 | ||
|
|
373e6c1e20 | ||
|
|
edfd8f0755 |
22 changed files with 452 additions and 95 deletions
4
.github/workflows/core-build-bench.yml
vendored
4
.github/workflows/core-build-bench.yml
vendored
|
|
@ -38,7 +38,7 @@ jobs:
|
|||
run: echo "LATEST_BENCH_RELEASE=$(curl -s 'https://api.github.com/repos/frappe/bench/releases/latest' | jq -r '.tag_name')" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Build and test
|
||||
uses: docker/bake-action@v7.1.0
|
||||
uses: docker/bake-action@v7.2.0
|
||||
with:
|
||||
source: .
|
||||
targets: bench-test
|
||||
|
|
@ -52,7 +52,7 @@ jobs:
|
|||
|
||||
- name: Push
|
||||
if: ${{ github.repository == 'frappe/frappe_docker' && github.event_name != 'pull_request' }}
|
||||
uses: docker/bake-action@v7.1.0
|
||||
uses: docker/bake-action@v7.2.0
|
||||
with:
|
||||
targets: bench
|
||||
push: true
|
||||
|
|
|
|||
2
.github/workflows/core-build-test-images.yml
vendored
2
.github/workflows/core-build-test-images.yml
vendored
|
|
@ -87,7 +87,7 @@ jobs:
|
|||
echo "NODE_VERSION=${{ inputs.node_version }}" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Build
|
||||
uses: docker/bake-action@v7.1.0
|
||||
uses: docker/bake-action@v7.2.0
|
||||
with:
|
||||
source: .
|
||||
push: true
|
||||
|
|
|
|||
4
.github/workflows/core-publish-images.yml
vendored
4
.github/workflows/core-publish-images.yml
vendored
|
|
@ -70,7 +70,7 @@ jobs:
|
|||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Push Docker Hub images
|
||||
uses: docker/bake-action@v7.1.0
|
||||
uses: docker/bake-action@v7.2.0
|
||||
with:
|
||||
push: true
|
||||
set: "*.platform=linux/amd64,linux/arm64"
|
||||
|
|
@ -83,7 +83,7 @@ jobs:
|
|||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Push GHCR base images
|
||||
uses: docker/bake-action@v7.1.0
|
||||
uses: docker/bake-action@v7.2.0
|
||||
with:
|
||||
targets: base-images
|
||||
push: true
|
||||
|
|
|
|||
1
.github/workflows/stale.yml
vendored
1
.github/workflows/stale.yml
vendored
|
|
@ -16,3 +16,4 @@ jobs:
|
|||
stale-pr-message: This PR has been automatically marked as stale. You have a week to explain why you believe this is an error.
|
||||
stale-issue-label: no-issue-activity
|
||||
stale-pr-label: no-pr-activity
|
||||
exempt-issue-labels: keep-open
|
||||
|
|
|
|||
|
|
@ -46,6 +46,10 @@ services:
|
|||
backend:
|
||||
<<: *backend_defaults
|
||||
platform: linux/amd64
|
||||
environment:
|
||||
GUNICORN_THREADS: ${GUNICORN_THREADS:-4}
|
||||
GUNICORN_WORKERS: ${GUNICORN_WORKERS:-2}
|
||||
GUNICORN_TIMEOUT: ${GUNICORN_TIMEOUT:-120}
|
||||
|
||||
frontend:
|
||||
<<: *customizable_image
|
||||
|
|
|
|||
|
|
@ -10,7 +10,9 @@
|
|||
"grapecity.gc-excelviewer",
|
||||
"mtxr.sqltools",
|
||||
"mtxr.sqltools-driver-mysql",
|
||||
"visualstudioexptteam.vscodeintellicode"
|
||||
"vue.volar",
|
||||
"esbenp.prettier-vscode",
|
||||
"charliermarsh.ruff"
|
||||
],
|
||||
"settings": {
|
||||
"terminal.integrated.profiles.linux": {
|
||||
|
|
|
|||
|
|
@ -35,11 +35,11 @@ This allows you to:
|
|||
|
||||
Installing apps into a running container is **not supported**.
|
||||
|
||||
`bench get-app` is an examples of an common but unsupported action.
|
||||
`bench get-app` and `bench build` are examples of an common but unsupported actions.
|
||||
|
||||
### Why?
|
||||
|
||||
- Apps are part of the **Docker image**
|
||||
- Apps and assets are part of the **Docker image**
|
||||
- Runtime changes are lost on container recreation
|
||||
- This ensures reproducibility and stability
|
||||
|
||||
|
|
|
|||
|
|
@ -29,8 +29,8 @@ here is the example pwd.yml file:
|
|||
```yml
|
||||
services:
|
||||
backend:
|
||||
image: frappe/erpnext:v15
|
||||
platform: linux/amd64
|
||||
image: frappe/erpnext:v16.19.1
|
||||
platform: linux/arm64
|
||||
deploy:
|
||||
restart_policy:
|
||||
condition: on-failure
|
||||
|
|
@ -39,8 +39,8 @@ services:
|
|||
- logs:/home/frappe/frappe-bench/logs
|
||||
|
||||
configurator:
|
||||
image: frappe/erpnext:v15
|
||||
platform: linux/amd64
|
||||
image: frappe/erpnext:v16.19.1
|
||||
platform: linux/arm64
|
||||
deploy:
|
||||
restart_policy:
|
||||
condition: none
|
||||
|
|
@ -68,8 +68,8 @@ services:
|
|||
- logs:/home/frappe/frappe-bench/logs
|
||||
|
||||
create-site:
|
||||
image: frappe/erpnext:v15
|
||||
platform: linux/amd64
|
||||
image: frappe/erpnext:v16.19.1
|
||||
platform: linux/arm64
|
||||
deploy:
|
||||
restart_policy:
|
||||
condition: none
|
||||
|
|
@ -101,7 +101,7 @@ services:
|
|||
|
||||
db:
|
||||
image: mariadb:11.8
|
||||
platform: linux/amd64
|
||||
platform: linux/arm64
|
||||
healthcheck:
|
||||
test: mysqladmin ping -h localhost --password=admin
|
||||
interval: 1s
|
||||
|
|
@ -119,8 +119,8 @@ services:
|
|||
- db-data:/var/lib/mysql
|
||||
|
||||
frontend:
|
||||
image: frappe/erpnext:v15
|
||||
platform: linux/amd64
|
||||
image: frappe/erpnext:v16.19.1
|
||||
platform: linux/arm64
|
||||
depends_on:
|
||||
- websocket
|
||||
deploy:
|
||||
|
|
@ -144,8 +144,8 @@ services:
|
|||
- "8080:8080"
|
||||
|
||||
queue-long:
|
||||
image: frappe/erpnext:v15
|
||||
platform: linux/amd64
|
||||
image: frappe/erpnext:v16.19.1
|
||||
platform: linux/arm64
|
||||
deploy:
|
||||
restart_policy:
|
||||
condition: on-failure
|
||||
|
|
@ -159,8 +159,8 @@ services:
|
|||
- logs:/home/frappe/frappe-bench/logs
|
||||
|
||||
queue-short:
|
||||
image: frappe/erpnext:v15
|
||||
platform: linux/amd64
|
||||
image: frappe/erpnext:v16.19.1
|
||||
platform: linux/arm64
|
||||
deploy:
|
||||
restart_policy:
|
||||
condition: on-failure
|
||||
|
|
@ -175,7 +175,7 @@ services:
|
|||
|
||||
redis-queue:
|
||||
image: redis:6.2-alpine
|
||||
platform: linux/amd64
|
||||
platform: linux/arm64
|
||||
deploy:
|
||||
restart_policy:
|
||||
condition: on-failure
|
||||
|
|
@ -184,14 +184,14 @@ services:
|
|||
|
||||
redis-cache:
|
||||
image: redis:6.2-alpine
|
||||
platform: linux/amd64
|
||||
platform: linux/arm64
|
||||
deploy:
|
||||
restart_policy:
|
||||
condition: on-failure
|
||||
|
||||
scheduler:
|
||||
image: frappe/erpnext:v15
|
||||
platform: linux/amd64
|
||||
image: frappe/erpnext:v16.19.1
|
||||
platform: linux/arm64
|
||||
deploy:
|
||||
restart_policy:
|
||||
condition: on-failure
|
||||
|
|
@ -203,8 +203,8 @@ services:
|
|||
- logs:/home/frappe/frappe-bench/logs
|
||||
|
||||
websocket:
|
||||
image: frappe/erpnext:v15
|
||||
platform: linux/amd64
|
||||
image: frappe/erpnext:v16.19.1
|
||||
platform: linux/arm64
|
||||
deploy:
|
||||
restart_policy:
|
||||
condition: on-failure
|
||||
|
|
|
|||
|
|
@ -96,6 +96,7 @@ See [Automated Builds and Deployment](../03-production/06-automated-builds-and-d
|
|||
| PYTHON_VERSION | Python version for the base image |
|
||||
| NODE_VERSION | Node.js version |
|
||||
| WKHTMLTOPDF_VERSION | wkhtmltopdf version |
|
||||
| INSTALL_CHROMIUM | Configure chromium installation, defaults to `true` - needed for Frappe Workbench version >15 |
|
||||
| **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` |
|
||||
|
|
|
|||
|
|
@ -122,6 +122,16 @@ If your site is named `example.com` and you access it via that domain, no need t
|
|||
|
||||
---
|
||||
|
||||
## Backend (Gunicorn) Configuration
|
||||
|
||||
| Variable | Purpose | Default | When to Set / Allowed Values |
|
||||
| :----------------- | :------------------------------------------------------------- | :------ | :------------------------------------------------------------------------------- |
|
||||
| `GUNICORN_WORKERS` | Number of worker processes handling web requests | `2` | Scale up for multi-core CPUs. Formula: `(2 x Cores) + 1` |
|
||||
| `GUNICORN_THREADS` | Number of concurrent threads per worker process | `4` | Increase to handle more simultaneous I/O-bound requests without high memory cost |
|
||||
| `GUNICORN_TIMEOUT` | Max time a worker can spend on a single request before restart | `120` | Increase if long-running reports or data imports time out |
|
||||
|
||||
---
|
||||
|
||||
## Frontend Nginx Configuration (inside the frontend container)
|
||||
|
||||
| Variable | Purpose | Default | Allowed Values |
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ docker compose --project-name erpnext exec backend \
|
|||
|
||||
# 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
|
||||
bench new-site --mariadb-user-host-login-scope=% --db-root-password changeit --install-app crm --admin-password changeit crm.your-domain.com
|
||||
```
|
||||
|
||||
### Notes
|
||||
|
|
|
|||
254
docs/05-development/04-alternate-setup.md
Normal file
254
docs/05-development/04-alternate-setup.md
Normal file
|
|
@ -0,0 +1,254 @@
|
|||
---
|
||||
title: Docker Development Setup
|
||||
---
|
||||
|
||||
# Docker Development Setup
|
||||
|
||||
A complete guide for setting up a Frappe development environment on x86 and ARM based computers running UNIX based OSes by running containers directly and working inside them via the terminal. No VS Code Dev Containers extension needed.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Devcontainers are the intended development setup for Frappe Framework but in case you don't want to use that method follow these instructions to use the CLI directly instead
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- **Docker Desktop** (Applicable only for MacOS) — [download here](https://www.docker.com/products/docker-desktop/)
|
||||
- **Git**
|
||||
- A terminal (iTerm2, or the built-in Terminal.app)
|
||||
|
||||
### Docker Desktop Resource Allocation (Critical)
|
||||
|
||||
1. Open Docker Desktop → **Settings** → **Resources**
|
||||
2. **Memory**: at least **6 GB** (8 GB recommended)
|
||||
3. **CPUs**: at least **4**
|
||||
4. **Disk image size**: at least **60 GB**
|
||||
5. Click **Apply & Restart**
|
||||
|
||||
---
|
||||
|
||||
## Step 1 — Set ARM64 as Default Platform (ONLY FOR ARM BASED SYSTEMS)
|
||||
|
||||
```bash
|
||||
export DOCKER_DEFAULT_PLATFORM=linux/arm64
|
||||
```
|
||||
|
||||
Make it permanent:
|
||||
|
||||
```bash
|
||||
echo 'export DOCKER_DEFAULT_PLATFORM=linux/arm64' >> ~/.zshrc
|
||||
source ~/.zshrc
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 2 — Clone the Repo
|
||||
|
||||
```bash
|
||||
git clone https://github.com/frappe/frappe_docker.git
|
||||
cd frappe_docker
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 3 — Set Up the Dev Container Config
|
||||
|
||||
The `devcontainer-example/` folder contains a ready-made `docker-compose.yml` for development. Copy it into place:
|
||||
|
||||
```bash
|
||||
cp -R devcontainer-example .devcontainer
|
||||
```
|
||||
|
||||
This gives you `.devcontainer/docker-compose.yml` which defines all the services you need:
|
||||
|
||||
- `frappe` — the main development container (Debian, Python, Node, bench)
|
||||
- `mariadb` — the database
|
||||
- `redis-cache` — cache layer
|
||||
- `redis-queue` — background job queue
|
||||
|
||||
---
|
||||
|
||||
## Step 4 — Add ARM64 Platform to All Services
|
||||
|
||||
Open `.devcontainer/docker-compose.yml` in any editor and add `platform: linux/arm64` to every service block. It should look like this:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
frappe:
|
||||
image: frappe/bench:latest
|
||||
platform: linux/arm64
|
||||
# ... rest of config
|
||||
|
||||
mariadb:
|
||||
image: mariadb:10.8
|
||||
platform: linux/arm64
|
||||
# ...
|
||||
|
||||
redis-cache:
|
||||
image: redis:6.2-alpine
|
||||
platform: linux/arm64
|
||||
# ...
|
||||
|
||||
redis-queue:
|
||||
image: redis:6.2-alpine
|
||||
platform: linux/arm64
|
||||
# ...
|
||||
```
|
||||
|
||||
> Without this, Docker may pull amd64 images and emulate them via Rosetta — things will work but be noticeably slower.
|
||||
|
||||
---
|
||||
|
||||
## Step 5 — Start the Containers
|
||||
|
||||
```bash
|
||||
docker compose -f .devcontainer/docker-compose.yml up -d
|
||||
```
|
||||
|
||||
Verify everything is running:
|
||||
|
||||
```bash
|
||||
docker compose -f .devcontainer/docker-compose.yml ps
|
||||
```
|
||||
|
||||
You should see all services with status `Up`.
|
||||
|
||||
In case you get any errors along the lines of,
|
||||
|
||||
```log
|
||||
Error response from daemon: failed to set up container networking: driver failed programming external connectivity on endpoint devcontainer-frappe-1 (44b337b68d100e914fab0ce446ed08d791cc73aaffb05cf47c347c00ff88f567): Bind for 0.0.0.0:9001 failed: port is already allocated
|
||||
```
|
||||
|
||||
- Check if the port is being used by another service with `lsof -i :PORT`
|
||||
> Usually on MacOS ports 8000 and 9000 are usually reserved for system use
|
||||
- Go to line 60 and 61 under the `frappe` service and change the ports
|
||||
|
||||
Eg:
|
||||
|
||||
```
|
||||
ports:
|
||||
- 8001-8005:8001-8005
|
||||
- 9002-9005:9002-9005
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 6 — Enter the Development Container
|
||||
|
||||
```bash
|
||||
docker exec -e "TERM=xterm-256color" -w /workspace/development -it devcontainer-frappe-1 bash
|
||||
```
|
||||
|
||||
> The container name is typically `devcontainer-frappe-1`. If it differs, check with `docker ps` and use the actual name shown.
|
||||
|
||||
You are now inside the container as the `frappe` user. All subsequent commands in this guide run **inside the container** unless noted otherwise.
|
||||
|
||||
---
|
||||
|
||||
## Step 7 — Initialize a Bench
|
||||
|
||||
```bash
|
||||
bench init --skip-redis-config-generation --frappe-branch version-16 frappe-bench
|
||||
cd frappe-bench
|
||||
```
|
||||
|
||||
Use `version-16` for the latest stable release. Swap for `version-15` if needed.
|
||||
|
||||
This creates:
|
||||
|
||||
```
|
||||
development/
|
||||
└── frappe-bench/
|
||||
├── apps/ ← All Frappe apps live here
|
||||
├── sites/ ← Your sites (databases, uploaded files)
|
||||
├── env/ ← Python virtualenv
|
||||
├── logs/
|
||||
└── Procfile
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 8 — Configure Service Hosts
|
||||
|
||||
Tell bench to use the containerised services (not localhost):
|
||||
|
||||
```bash
|
||||
bench set-config -g db_host mariadb
|
||||
bench set-config -g redis_cache redis://redis-cache:6379
|
||||
bench set-config -g redis_queue redis://redis-queue:6379
|
||||
bench set-config -g redis_socketio redis://redis-queue:6379
|
||||
```
|
||||
|
||||
If any command fails, edit the file directly:
|
||||
|
||||
```bash
|
||||
nano sites/common_site_config.json
|
||||
```
|
||||
|
||||
Paste:
|
||||
|
||||
```json
|
||||
{
|
||||
"db_host": "mariadb",
|
||||
"redis_cache": "redis://redis-cache:6379",
|
||||
"redis_queue": "redis://redis-queue:6379",
|
||||
"redis_socketio": "redis://redis-queue:6379"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 9 — Fix the Procfile
|
||||
|
||||
Redis runs in separate containers, so remove it from Honcho's Procfile to avoid conflicts:
|
||||
|
||||
```bash
|
||||
sudo sed -i '/redis/d' ./Procfile
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 10 — Create a Site
|
||||
|
||||
```bash
|
||||
bench new-site \
|
||||
--db-root-password 123 \
|
||||
--admin-password admin \
|
||||
--mariadb-user-host-login-scope=% \
|
||||
development.localhost
|
||||
```
|
||||
|
||||
- MariaDB root password: `123` (set in the docker-compose defaults)
|
||||
- Admin password: `admin` (change this to whatever you want)
|
||||
- Site name **must end in `.localhost`**
|
||||
|
||||
---
|
||||
|
||||
## Step 11 — Enable Developer Mode
|
||||
|
||||
```bash
|
||||
bench --site development.localhost set-config developer_mode 1
|
||||
bench --site development.localhost clear-cache
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 12 — Add development.localhost to /etc/hosts (on your Mac)
|
||||
|
||||
Run this **on your Mac** (not inside the container):
|
||||
|
||||
```bash
|
||||
echo "127.0.0.1 development.localhost" | sudo tee -a /etc/hosts
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 13 — Start the Dev Server
|
||||
|
||||
```bash
|
||||
bench build # (optional)
|
||||
bench start
|
||||
```
|
||||
|
||||
Open your browser at **http://development.localhost:8000**
|
||||
Login: `Administrator` / `admin`
|
||||
62
docs/08-reference/07-how-assets-are-handled.md
Normal file
62
docs/08-reference/07-how-assets-are-handled.md
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
---
|
||||
title: How Assets are handled
|
||||
---
|
||||
|
||||
# Assets Reference
|
||||
|
||||
## Problem
|
||||
|
||||
The `sites` directory contains both persistent data (site config, uploaded files, etc.) and build-time artifacts (`sites/assets`). Mounting the entire `sites` directory as a Docker volume causes assets to be persisted alongside config, which leads to:
|
||||
|
||||
- Stale assets surviving image updates
|
||||
- Asset/manifest mismatches after rebuilds
|
||||
- Assets being tied to the volume lifecycle rather than the image lifecycle
|
||||
|
||||
## Solution
|
||||
|
||||
Assets are moved out of the `sites` volume during the build process and replaced with a **symlink** later on. This means assets are always served from the image layer, while the rest of `sites` remains persistent.
|
||||
|
||||
### How it works
|
||||
|
||||
During the image build (`Containerfile`), the following is done:
|
||||
|
||||
```dockerfile
|
||||
RUN cp -r /home/frappe/frappe-bench/sites/assets /home/frappe/frappe-bench/assets && \
|
||||
rm -rf /home/frappe/frappe-bench/sites/assets
|
||||
```
|
||||
|
||||
This runs **before** the `VOLUME` declaration, so the **`sites` volume does not contain any assets at all**.
|
||||
|
||||
Additionally an `ENTRYPOINT` is added to the images which adds a **symlink** from `assets` to `site\assets`.
|
||||
|
||||
> This is implemented in the entrypoint instead of baking the symlink directly into the image so it also works with pre-existing or already-initialized `sites` volumes.
|
||||
> Since mounting a volume over `/home/frappe/frappe-bench/sites` hides the image contents at that path, any symlink created during the image build would not be visible inside the mounted volume. The entrypoint recreates the symlink at container startup, ensuring it always exists and automatically repairing older volumes that may not already contain it.
|
||||
|
||||
At runtime:
|
||||
|
||||
```
|
||||
/home/frappe/frappe-bench/
|
||||
├── assets/ ← image layer (ephemeral, always matches the image)
|
||||
├── sites/
|
||||
│ ├── assets -> /home/frappe/frappe-bench/assets ← symlink
|
||||
│ ├── common_site_config.json ← persisted in volume
|
||||
│ └── <site>/ ← persisted in volume
|
||||
└── logs/ ← persisted in volume
|
||||
```
|
||||
|
||||
### Volume behavior
|
||||
|
||||
| Path | Persistent | Source |
|
||||
| -------------------------- | ----------------------- | ---------------------- |
|
||||
| `sites/` (except assets) | ✅ Yes | Named volume (`sites`) |
|
||||
| `sites/assets` (symlink) | ✅ Yes (symlink itself) | Named volume (`sites`) |
|
||||
| `assets/` (symlink target) | ❌ No | Image layer |
|
||||
| `logs/` | ✅ Yes | Unnamed volume |
|
||||
|
||||
The `sites/assets` symlink is stored inside the persistent `sites` volume, but its target (`/home/frappe/frappe-bench/assets`) comes from the container image. When the container is recreated or upgraded, the assets directory is recreated from the new image, ensuring assets always stay in sync with the running version.
|
||||
|
||||
## Important: `bench build` at runtime
|
||||
|
||||
Running `bench build` inside a running container will write new assets and eventually cause a mismatch between `assets.json` and the actual assets, breaking the UI. This can be recovered by recreating the containers
|
||||
|
||||
> Note: restarting the containers is not sufficient — they need to be recreated to discard the writable layer.
|
||||
|
|
@ -15,7 +15,7 @@ importers:
|
|||
devDependencies:
|
||||
vitepress:
|
||||
specifier: 2.0.0-alpha.16
|
||||
version: 2.0.0-alpha.16(postcss@8.5.8)
|
||||
version: 2.0.0-alpha.16(postcss@8.5.15)
|
||||
vitepress-sidebar:
|
||||
specifier: 1.33.1
|
||||
version: 1.33.1
|
||||
|
|
@ -408,6 +408,7 @@ packages:
|
|||
|
||||
'@ungap/structured-clone@1.3.0':
|
||||
resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==}
|
||||
deprecated: Potential CWE-502 - Update to 1.3.1 or higher
|
||||
|
||||
'@vitejs/plugin-vue@6.0.5':
|
||||
resolution: {integrity: sha512-bL3AxKuQySfk1iGcBsQnoRVexTPJq0Z/ixFVM8OhVJAP6ZXXXLtM7NFKWhLl30Kg7uTBqIaPXbh+nuQCuBDedg==}
|
||||
|
|
@ -707,8 +708,8 @@ packages:
|
|||
minisearch@7.2.0:
|
||||
resolution: {integrity: sha512-dqT2XBYUOZOiC5t2HRnwADjhNS2cecp9u+TJRiJ1Qp/f5qjkeT5APcGPjHw+bz89Ms8Jp+cG4AlE+QZ/QnDglg==}
|
||||
|
||||
nanoid@3.3.11:
|
||||
resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==}
|
||||
nanoid@3.3.12:
|
||||
resolution: {integrity: sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==}
|
||||
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
|
||||
hasBin: true
|
||||
|
||||
|
|
@ -739,8 +740,8 @@ packages:
|
|||
resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
postcss@8.5.8:
|
||||
resolution: {integrity: sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==}
|
||||
postcss@8.5.15:
|
||||
resolution: {integrity: sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==}
|
||||
engines: {node: ^10 || ^12 || >=14}
|
||||
|
||||
property-information@7.1.0:
|
||||
|
|
@ -1214,7 +1215,7 @@ snapshots:
|
|||
'@vue/shared': 3.5.30
|
||||
estree-walker: 2.0.2
|
||||
magic-string: 0.30.21
|
||||
postcss: 8.5.8
|
||||
postcss: 8.5.15
|
||||
source-map-js: 1.2.1
|
||||
|
||||
'@vue/compiler-ssr@3.5.30':
|
||||
|
|
@ -1491,7 +1492,7 @@ snapshots:
|
|||
|
||||
minisearch@7.2.0: {}
|
||||
|
||||
nanoid@3.3.11: {}
|
||||
nanoid@3.3.12: {}
|
||||
|
||||
oniguruma-parser@0.12.1: {}
|
||||
|
||||
|
|
@ -1516,9 +1517,9 @@ snapshots:
|
|||
|
||||
picomatch@4.0.4: {}
|
||||
|
||||
postcss@8.5.8:
|
||||
postcss@8.5.15:
|
||||
dependencies:
|
||||
nanoid: 3.3.11
|
||||
nanoid: 3.3.12
|
||||
picocolors: 1.1.1
|
||||
source-map-js: 1.2.1
|
||||
|
||||
|
|
@ -1671,7 +1672,7 @@ snapshots:
|
|||
esbuild: 0.27.4
|
||||
fdir: 6.5.0(picomatch@4.0.4)
|
||||
picomatch: 4.0.4
|
||||
postcss: 8.5.8
|
||||
postcss: 8.5.15
|
||||
rollup: 4.59.0
|
||||
tinyglobby: 0.2.15
|
||||
optionalDependencies:
|
||||
|
|
@ -1683,7 +1684,7 @@ snapshots:
|
|||
gray-matter: 4.0.3
|
||||
qsu: 1.10.4
|
||||
|
||||
vitepress@2.0.0-alpha.16(postcss@8.5.8):
|
||||
vitepress@2.0.0-alpha.16(postcss@8.5.15):
|
||||
dependencies:
|
||||
'@docsearch/css': 4.6.0
|
||||
'@docsearch/js': 4.6.0
|
||||
|
|
@ -1705,7 +1706,7 @@ snapshots:
|
|||
vite: 7.3.2
|
||||
vue: 3.5.30
|
||||
optionalDependencies:
|
||||
postcss: 8.5.8
|
||||
postcss: 8.5.15
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
- async-validator
|
||||
|
|
|
|||
13
example.env
13
example.env
|
|
@ -1,6 +1,6 @@
|
|||
# Reference: https://github.com/frappe/frappe_docker/blob/main/docs/02-setup/04-env-variables.md
|
||||
|
||||
ERPNEXT_VERSION=v16.16.0
|
||||
ERPNEXT_VERSION=v16.23.0
|
||||
|
||||
DB_PASSWORD=123
|
||||
|
||||
|
|
@ -15,6 +15,17 @@ DB_PORT=
|
|||
REDIS_CACHE=
|
||||
REDIS_QUEUE=
|
||||
|
||||
|
||||
# The number of threads per Gunicorn worker process for handling concurrent requests.
|
||||
GUNICORN_THREADS=4
|
||||
|
||||
# The number of worker processes for handling requests.
|
||||
# A typical formula is (2 x number of CPU cores) + 1.
|
||||
GUNICORN_WORKERS=2
|
||||
|
||||
# Workers exceeding this timeout (in seconds) will be killed and restarted.
|
||||
GUNICORN_TIMEOUT=120
|
||||
|
||||
# Only with HTTPS override
|
||||
LETSENCRYPT_EMAIL=mail@example.com
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ LABEL author=frappé
|
|||
|
||||
ARG GIT_REPO=https://github.com/frappe/bench.git
|
||||
ARG GIT_BRANCH=v5.x
|
||||
ARG INSTALL_CHROMIUM=true
|
||||
|
||||
RUN apt-get update \
|
||||
&& DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y \
|
||||
|
|
@ -23,8 +24,6 @@ RUN apt-get update \
|
|||
libharfbuzz0b \
|
||||
libpangoft2-1.0-0 \
|
||||
libpangocairo-1.0-0 \
|
||||
#Chromium
|
||||
chromium-headless-shell \
|
||||
# to work inside the container
|
||||
locales \
|
||||
build-essential \
|
||||
|
|
@ -75,6 +74,11 @@ RUN apt-get update \
|
|||
file \
|
||||
# For MIME type detection
|
||||
media-types \
|
||||
# Chromium
|
||||
&& if [ "$INSTALL_CHROMIUM" != "false" ]; then \
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y \
|
||||
chromium-headless-shell; \
|
||||
fi \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen \
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ COPY resources/core/nginx/security_headers.conf /etc/nginx/snippets/security_hea
|
|||
|
||||
ARG WKHTMLTOPDF_VERSION=0.12.6.1-3
|
||||
ARG WKHTMLTOPDF_DISTRO=bookworm
|
||||
ARG INSTALL_CHROMIUM=true
|
||||
|
||||
ARG NODE_VERSION=24.13.0
|
||||
ENV NVM_DIR=/home/frappe/.nvm
|
||||
ENV PATH=${NVM_DIR}/versions/node/v${NODE_VERSION}/bin/:${PATH}
|
||||
|
|
@ -26,8 +28,6 @@ RUN useradd -ms /bin/bash frappe \
|
|||
libharfbuzz0b \
|
||||
libpangoft2-1.0-0 \
|
||||
libpangocairo-1.0-0 \
|
||||
#Chromium
|
||||
chromium-headless-shell \
|
||||
# For backups
|
||||
restic \
|
||||
gpg \
|
||||
|
|
@ -62,6 +62,11 @@ RUN useradd -ms /bin/bash frappe \
|
|||
&& curl -sLO https://github.com/wkhtmltopdf/packaging/releases/download/$WKHTMLTOPDF_VERSION/$downloaded_file \
|
||||
&& apt-get install -y ./$downloaded_file \
|
||||
&& rm $downloaded_file \
|
||||
# Chromium
|
||||
&& if [ "$INSTALL_CHROMIUM" != "false" ]; then \
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y \
|
||||
chromium-headless-shell; \
|
||||
fi \
|
||||
# Clean up
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& rm -fr /etc/nginx/sites-enabled/default \
|
||||
|
|
@ -158,20 +163,12 @@ VOLUME [ \
|
|||
USER root
|
||||
# This entrypoint script link build assets of the image to the mounted sites volume at container initialization
|
||||
COPY resources/core/main-entrypoint.sh /usr/local/bin/entrypoint.sh
|
||||
RUN chmod +x /usr/local/bin/entrypoint.sh
|
||||
RUN chmod 755 /usr/local/bin/entrypoint.sh
|
||||
|
||||
COPY resources/core/start.sh /usr/local/bin/start.sh
|
||||
RUN chmod 755 /usr/local/bin/start.sh
|
||||
|
||||
USER frappe
|
||||
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
|
||||
|
||||
CMD [ \
|
||||
"/home/frappe/frappe-bench/env/bin/gunicorn", \
|
||||
"--chdir=/home/frappe/frappe-bench/sites", \
|
||||
"--bind=0.0.0.0:8000", \
|
||||
"--threads=4", \
|
||||
"--workers=2", \
|
||||
"--worker-class=gthread", \
|
||||
"--worker-tmp-dir=/dev/shm", \
|
||||
"--timeout=120", \
|
||||
"--preload", \
|
||||
"frappe.app:application" \
|
||||
]
|
||||
CMD ["start.sh"]
|
||||
|
|
|
|||
|
|
@ -47,20 +47,12 @@ VOLUME [ \
|
|||
USER root
|
||||
# This entrypoint script link build assets of the image to the mounted sites volume at container initialization
|
||||
COPY resources/core/main-entrypoint.sh /usr/local/bin/entrypoint.sh
|
||||
RUN chmod +x /usr/local/bin/entrypoint.sh
|
||||
RUN chmod 755 /usr/local/bin/entrypoint.sh
|
||||
|
||||
COPY resources/core/start.sh /usr/local/bin/start.sh
|
||||
RUN chmod 755 /usr/local/bin/start.sh
|
||||
|
||||
USER frappe
|
||||
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
|
||||
|
||||
CMD [ \
|
||||
"/home/frappe/frappe-bench/env/bin/gunicorn", \
|
||||
"--chdir=/home/frappe/frappe-bench/sites", \
|
||||
"--bind=0.0.0.0:8000", \
|
||||
"--threads=4", \
|
||||
"--workers=2", \
|
||||
"--worker-class=gthread", \
|
||||
"--worker-tmp-dir=/dev/shm", \
|
||||
"--timeout=120", \
|
||||
"--preload", \
|
||||
"frappe.app:application" \
|
||||
]
|
||||
CMD ["start.sh"]
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ FROM python:${PYTHON_VERSION}-slim-${DEBIAN_BASE} AS base
|
|||
|
||||
ARG WKHTMLTOPDF_VERSION=0.12.6.1-3
|
||||
ARG WKHTMLTOPDF_DISTRO=bookworm
|
||||
ARG INSTALL_CHROMIUM=true
|
||||
|
||||
ARG NODE_VERSION=24.13.0
|
||||
ENV NVM_DIR=/home/frappe/.nvm
|
||||
ENV PATH=${NVM_DIR}/versions/node/v${NODE_VERSION}/bin/:${PATH}
|
||||
|
|
@ -22,8 +24,6 @@ RUN useradd -ms /bin/bash frappe \
|
|||
libharfbuzz0b \
|
||||
libpangoft2-1.0-0 \
|
||||
libpangocairo-1.0-0 \
|
||||
#Chromium
|
||||
chromium-headless-shell \
|
||||
# For backups
|
||||
restic \
|
||||
gpg \
|
||||
|
|
@ -58,6 +58,11 @@ RUN useradd -ms /bin/bash frappe \
|
|||
&& curl -sLO https://github.com/wkhtmltopdf/packaging/releases/download/$WKHTMLTOPDF_VERSION/$downloaded_file \
|
||||
&& apt-get install -y ./$downloaded_file \
|
||||
&& rm $downloaded_file \
|
||||
# Chromium
|
||||
&& if [ "$INSTALL_CHROMIUM" != "false" ]; then \
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y \
|
||||
chromium-headless-shell; \
|
||||
fi \
|
||||
# Clean up
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& rm -fr /etc/nginx/sites-enabled/default \
|
||||
|
|
@ -77,6 +82,7 @@ RUN useradd -ms /bin/bash frappe \
|
|||
COPY resources/core/nginx/nginx-template.conf /templates/nginx/frappe.conf.template
|
||||
COPY resources/core/nginx/nginx-entrypoint.sh /usr/local/bin/nginx-entrypoint.sh
|
||||
COPY resources/core/nginx/security_headers.conf /etc/nginx/snippets/security_headers.conf
|
||||
RUN chmod 755 /usr/local/bin/nginx-entrypoint.sh
|
||||
|
||||
FROM base AS build
|
||||
|
||||
|
|
@ -148,20 +154,12 @@ VOLUME [ \
|
|||
USER root
|
||||
# This entrypoint script link build assets of the image to the mounted sites volume at container initialization
|
||||
COPY resources/core/main-entrypoint.sh /usr/local/bin/entrypoint.sh
|
||||
RUN chmod +x /usr/local/bin/entrypoint.sh
|
||||
RUN chmod 755 /usr/local/bin/entrypoint.sh
|
||||
|
||||
COPY resources/core/start.sh /usr/local/bin/start.sh
|
||||
RUN chmod 755 /usr/local/bin/start.sh
|
||||
|
||||
USER frappe
|
||||
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
|
||||
|
||||
CMD [ \
|
||||
"/home/frappe/frappe-bench/env/bin/gunicorn", \
|
||||
"--chdir=/home/frappe/frappe-bench/sites", \
|
||||
"--bind=0.0.0.0:8000", \
|
||||
"--threads=4", \
|
||||
"--workers=2", \
|
||||
"--worker-class=gthread", \
|
||||
"--worker-tmp-dir=/dev/shm", \
|
||||
"--timeout=120", \
|
||||
"--preload", \
|
||||
"frappe.app:application" \
|
||||
]
|
||||
CMD ["start.sh"]
|
||||
|
|
|
|||
16
pwd.yml
16
pwd.yml
|
|
@ -1,6 +1,6 @@
|
|||
services:
|
||||
backend:
|
||||
image: frappe/erpnext:v16.16.0
|
||||
image: frappe/erpnext:v16.23.0
|
||||
networks:
|
||||
- frappe_network
|
||||
deploy:
|
||||
|
|
@ -16,7 +16,7 @@ services:
|
|||
MARIADB_ROOT_PASSWORD: admin
|
||||
|
||||
configurator:
|
||||
image: frappe/erpnext:v16.16.0
|
||||
image: frappe/erpnext:v16.23.0
|
||||
networks:
|
||||
- frappe_network
|
||||
deploy:
|
||||
|
|
@ -45,7 +45,7 @@ services:
|
|||
- logs:/home/frappe/frappe-bench/logs
|
||||
|
||||
create-site:
|
||||
image: frappe/erpnext:v16.16.0
|
||||
image: frappe/erpnext:v16.23.0
|
||||
networks:
|
||||
- frappe_network
|
||||
deploy:
|
||||
|
|
@ -101,7 +101,7 @@ services:
|
|||
- db-data:/var/lib/mysql
|
||||
|
||||
frontend:
|
||||
image: frappe/erpnext:v16.16.0
|
||||
image: frappe/erpnext:v16.23.0
|
||||
networks:
|
||||
- frappe_network
|
||||
depends_on:
|
||||
|
|
@ -127,7 +127,7 @@ services:
|
|||
- "8080:8080"
|
||||
|
||||
queue-long:
|
||||
image: frappe/erpnext:v16.16.0
|
||||
image: frappe/erpnext:v16.23.0
|
||||
networks:
|
||||
- frappe_network
|
||||
deploy:
|
||||
|
|
@ -146,7 +146,7 @@ services:
|
|||
FRAPPE_REDIS_QUEUE: redis://redis-queue:6379
|
||||
|
||||
queue-short:
|
||||
image: frappe/erpnext:v16.16.0
|
||||
image: frappe/erpnext:v16.23.0
|
||||
networks:
|
||||
- frappe_network
|
||||
deploy:
|
||||
|
|
@ -183,7 +183,7 @@ services:
|
|||
condition: on-failure
|
||||
|
||||
scheduler:
|
||||
image: frappe/erpnext:v16.16.0
|
||||
image: frappe/erpnext:v16.23.0
|
||||
networks:
|
||||
- frappe_network
|
||||
deploy:
|
||||
|
|
@ -197,7 +197,7 @@ services:
|
|||
- logs:/home/frappe/frappe-bench/logs
|
||||
|
||||
websocket:
|
||||
image: frappe/erpnext:v16.16.0
|
||||
image: frappe/erpnext:v16.23.0
|
||||
networks:
|
||||
- frappe_network
|
||||
deploy:
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
pytest==9.0.3
|
||||
pytest==9.1.0
|
||||
|
|
|
|||
20
resources/core/start.sh
Executable file
20
resources/core/start.sh
Executable file
|
|
@ -0,0 +1,20 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
#Gunicorn defaults
|
||||
GUNICORN_THREADS=${GUNICORN_THREADS:-4}
|
||||
GUNICORN_WORKERS=${GUNICORN_WORKERS:-2}
|
||||
GUNICORN_TIMEOUT=${GUNICORN_TIMEOUT:-120}
|
||||
|
||||
echo "Booting Gunicorn with $GUNICORN_WORKERS workers and $GUNICORN_THREADS threads..."
|
||||
|
||||
exec /home/frappe/frappe-bench/env/bin/gunicorn \
|
||||
--chdir=/home/frappe/frappe-bench/sites \
|
||||
--bind=0.0.0.0:8000 \
|
||||
--threads="$GUNICORN_THREADS" \
|
||||
--workers="$GUNICORN_WORKERS" \
|
||||
--worker-class=gthread \
|
||||
--worker-tmp-dir=/dev/shm \
|
||||
--timeout="$GUNICORN_TIMEOUT" \
|
||||
--preload \
|
||||
frappe.app:application
|
||||
Loading…
Reference in a new issue