Merge branch 'main' into feat/easy-docker

This commit is contained in:
RocketQuack 2026-04-20 23:30:17 +02:00
commit 74f41a3948
19 changed files with 123 additions and 91 deletions

View file

@ -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.0.0
uses: docker/bake-action@v7.1.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.0.0
uses: docker/bake-action@v7.1.0
with:
targets: bench
push: true

View file

@ -66,7 +66,7 @@ jobs:
echo "NODE_VERSION=${{ inputs.node_version }}" >> "$GITHUB_ENV"
- name: Build
uses: docker/bake-action@v7.0.0
uses: docker/bake-action@v7.1.0
with:
source: .
push: true
@ -95,7 +95,7 @@ jobs:
- name: Push
if: ${{ inputs.push }}
uses: docker/bake-action@v7.0.0
uses: docker/bake-action@v7.1.0
with:
push: true
set: "*.platform=linux/amd64,linux/arm64"

View file

@ -32,17 +32,23 @@ jobs:
- name: Checkout
uses: actions/checkout@v6
- name: Install pnpm
uses: pnpm/action-setup@v5
with:
version: 10
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node-version }}
cache: "pnpm"
cache-dependency-path: ./docs
- name: Enable Corepack
run: corepack enable
- name: Activate pnpm
run: corepack prepare pnpm@10.28.2 --activate
- name: Show tool versions
run: |
node --version
corepack --version
pnpm --version
which pnpm
- name: Install dependencies
run: pnpm i --frozen-lockfile
@ -51,7 +57,7 @@ jobs:
run: pnpm docs:build
- name: Upload artifact
uses: actions/upload-pages-artifact@v4
uses: actions/upload-pages-artifact@v5
with:
path: docs/.vitepress/dist

25
MAINTAINERS.md Normal file
View file

@ -0,0 +1,25 @@
# Maintainers
This project is actively maintained by the following people.
Maintainers are responsible for:
- Reviewing and merging pull requests
- Managing releases
- Triaging and responding to issues
- Ensuring the overall health and direction of the project
## Current Maintainers
- [@revant](https://github.com/revant)
- [@DanielRadlAMR](https://github.com/DanielRadlAMR)
- [@Rocket-Quack](https://github.com/Rocket-Quack)
## Emeritus Maintainers
_(none)_
## Becoming a Maintainer
Contributors who consistently help review pull requests, participate in issue triage,
and contribute to releases may be invited to become maintainers.

View file

@ -5,7 +5,6 @@ services:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
- --skip-character-set-client-handshake
- --skip-innodb-read-only-compressed # Temporary fix for MariaDB 10.6
environment:
MYSQL_ROOT_PASSWORD: 123
MARIADB_AUTO_UPGRADE: 1

View file

@ -1,3 +1,20 @@
{
"python.defaultInterpreterPath": "${workspaceFolder}/frappe-bench/env/bin/python"
"python.defaultInterpreterPath": "${workspaceFolder}/frappe-bench/env/bin/python",
"files.watcherExclude": {
// --- Node modules ---
"**/node_modules/**": true,
// --- Frappe bench core dirs ---
"**/env/**": true,
"**/config/**": true,
// --- Build artifacts ---
"**/__pycache__/**": true,
"**/*.pyc": true
},
"files.exclude": {
"**/__pycache__": true,
"**/*.pyc": true,
"**/.git": false
}
}

View file

@ -100,7 +100,7 @@ services:
bench new-site --mariadb-user-host-login-scope=% --admin-password=admin --db-root-password=admin --install-app erpnext --set-default frontend;
db:
image: mariadb:10.6
image: mariadb:11.8
platform: linux/amd64
healthcheck:
test: mysqladmin ping -h localhost --password=admin
@ -113,7 +113,6 @@ services:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
- --skip-character-set-client-handshake
- --skip-innodb-read-only-compressed # Temporary fix for MariaDB 10.6
environment:
MYSQL_ROOT_PASSWORD: admin
volumes:

View file

@ -7,11 +7,13 @@ This guide walks you through building Frappe images from the repository resource
# Prerequisites
- git
- docker or podman
- docker (Engine **v23.0+**) 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.
> **Why Docker Engine v23+?** The build uses [BuildKit secrets](https://docs.docker.com/build/building/secrets/) (`--secret`) to keep `apps.json` tokens out of image layers. BuildKit is the default builder starting with Docker Engine 23.0 — older releases will fail or silently fall back to the legacy builder, which does not support secret mounts.
# Clone this repo
```bash
@ -42,23 +44,19 @@ To include custom apps in your image, create an `apps.json` file in the reposito
]
```
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.
> **Security note:** The `apps.json` file is passed as a [BuildKit secret](https://docs.docker.com/build/building/secrets/) so that private repository tokens are **never** stored in image layer metadata. Do not use `--build-arg` for `apps.json` — build arguments are permanently visible via `docker image history`. This requires **Docker Engine v23.0+** (where BuildKit is the default builder).
`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 \
--secret=id=apps_json,src=apps.json \
--tag=custom:15 \
--file=images/layered/Containerfile .
```
@ -69,27 +67,27 @@ docker build \
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 \
--secret=id=apps_json,src=apps.json \
--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` |
| 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** | |
| (secret) apps_json | Passed via `--secret=id=apps_json,src=apps.json`. Never use `--build-arg` for this file. |
| **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

View file

@ -15,7 +15,7 @@ We will setup the following:
## Requirements
- A server that can run Docker (recommended: 2 vCPU, 4 GB RAM, 50 GB SSD).
- 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](https://docs.docker.com/build/building/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.com`
@ -84,25 +84,17 @@ cat > ~/gitops/apps.json <<'EOF'
EOF
```
Generate the BASE64 value and build:
Build the image, passing `apps.json` as a [BuildKit secret](https://docs.docker.com/build/building/secrets/) so that private repo tokens are never stored in image layers. This requires **Docker Engine v23.0+**, where BuildKit is the default builder:
```shell
export APPS_JSON_BASE64=$(base64 -w 0 ~/gitops/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 \
--secret=id=apps_json,src=$HOME/gitops/apps.json \
--tag=my-erpnext-prod-image:16.0.0 \
--file=images/layered/Containerfile .
```
If `base64 -w 0` is not available on your system, use:
```shell
export APPS_JSON_BASE64=$(base64 ~/gitops/apps.json | tr -d '\n')
```
### Configure environment
Create an environment file for the bench:

View file

@ -114,3 +114,14 @@ create-site:
# ... removed for brevity
```
## Upgrading from images with a nested sites/assets volume
Previous images declared `VOLUME /home/frappe/frappe-bench/sites/assets` separately. This created an implicit nested mountpoint inside the `sites` volume, which could cause Docker to attach different anonymous volumes per container in multi-container setups.
That declaration has been removed. `sites` is now the single shared mount, consistent with the compose setup and docs.
**After pulling the updated image:**
- Recreate all containers (`docker compose up --force-recreate`). Without this, Docker may keep the old anonymous `sites/assets` volume
attached from before the change.
- No `bench build` is needed — this only fixes mount consistency, not the asset workflow.

View file

@ -10,6 +10,7 @@
},
"pnpm": {
"overrides": {
"vite": "7.3.2",
"minimatch": "10.2.5",
"picomatch": "4.0.4"
}

View file

@ -5,6 +5,7 @@ settings:
excludeLinksFromLockfile: false
overrides:
vite: 7.3.2
minimatch: 10.2.5
picomatch: 4.0.4
@ -412,7 +413,7 @@ packages:
resolution: {integrity: sha512-bL3AxKuQySfk1iGcBsQnoRVexTPJq0Z/ixFVM8OhVJAP6ZXXXLtM7NFKWhLl30Kg7uTBqIaPXbh+nuQCuBDedg==}
engines: {node: ^20.19.0 || >=22.12.0}
peerDependencies:
vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0
vite: 7.3.2
vue: ^3.2.25
'@vue/compiler-core@3.5.30':
@ -846,8 +847,8 @@ packages:
vfile@6.0.3:
resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==}
vite@7.3.1:
resolution: {integrity: sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==}
vite@7.3.2:
resolution: {integrity: sha512-Bby3NOsna2jsjfLVOHKes8sGwgl4TT0E6vvpYgnAYDIF/tie7MRaFthmKuHx1NSXjiTueXH3do80FMQgvEktRg==}
engines: {node: ^20.19.0 || >=22.12.0}
hasBin: true
peerDependencies:
@ -1185,10 +1186,10 @@ snapshots:
'@ungap/structured-clone@1.3.0': {}
'@vitejs/plugin-vue@6.0.5(vite@7.3.1)(vue@3.5.30)':
'@vitejs/plugin-vue@6.0.5(vite@7.3.2)(vue@3.5.30)':
dependencies:
'@rolldown/pluginutils': 1.0.0-rc.2
vite: 7.3.1
vite: 7.3.2
vue: 3.5.30
'@vue/compiler-core@3.5.30':
@ -1665,7 +1666,7 @@ snapshots:
'@types/unist': 3.0.3
vfile-message: 4.0.3
vite@7.3.1:
vite@7.3.2:
dependencies:
esbuild: 0.27.4
fdir: 6.5.0(picomatch@4.0.4)
@ -1692,7 +1693,7 @@ snapshots:
'@shikijs/transformers': 3.23.0
'@shikijs/types': 3.23.0
'@types/markdown-it': 14.1.2
'@vitejs/plugin-vue': 6.0.5(vite@7.3.1)(vue@3.5.30)
'@vitejs/plugin-vue': 6.0.5(vite@7.3.2)(vue@3.5.30)
'@vue/devtools-api': 8.1.0
'@vue/shared': 3.5.30
'@vueuse/core': 14.2.1(vue@3.5.30)
@ -1701,7 +1702,7 @@ snapshots:
mark.js: 8.11.1
minisearch: 7.2.0
shiki: 3.23.0
vite: 7.3.1
vite: 7.3.2
vue: 3.5.30
optionalDependencies:
postcss: 8.5.8

View file

@ -1,6 +1,6 @@
# Reference: https://github.com/frappe/frappe_docker/blob/main/docs/02-setup/04-env-variables.md
ERPNEXT_VERSION=v16.13.2
ERPNEXT_VERSION=v16.14.0
DB_PASSWORD=123

View file

@ -113,18 +113,13 @@ RUN apt-get update \
libbz2-dev \
&& rm -rf /var/lib/apt/lists/*
# apps.json includes
ARG APPS_JSON_BASE64
RUN if [ -n "${APPS_JSON_BASE64}" ]; then \
mkdir /opt/frappe && echo "${APPS_JSON_BASE64}" | base64 -d > /opt/frappe/apps.json; \
fi
USER frappe
ARG FRAPPE_BRANCH=version-16
ARG FRAPPE_PATH=https://github.com/frappe/frappe
RUN export APP_INSTALL_ARGS="" && \
if [ -n "${APPS_JSON_BASE64}" ]; then \
RUN --mount=type=secret,id=apps_json,target=/opt/frappe/apps.json,uid=1000,gid=1000 \
export APP_INSTALL_ARGS="" && \
if [ -f /opt/frappe/apps.json ] && [ -s /opt/frappe/apps.json ]; then \
export APP_INSTALL_ARGS="--apps_path=/opt/frappe/apps.json"; \
fi && \
bench init ${APP_INSTALL_ARGS}\
@ -149,7 +144,6 @@ WORKDIR /home/frappe/frappe-bench
VOLUME [ \
"/home/frappe/frappe-bench/sites", \
"/home/frappe/frappe-bench/sites/assets", \
"/home/frappe/frappe-bench/logs" \
]

View file

@ -4,18 +4,12 @@ FROM frappe/build:${FRAPPE_BRANCH} AS builder
ARG FRAPPE_BRANCH=version-16
ARG FRAPPE_PATH=https://github.com/frappe/frappe
ARG APPS_JSON_BASE64
USER root
RUN if [ -n "${APPS_JSON_BASE64}" ]; then \
mkdir /opt/frappe && echo "${APPS_JSON_BASE64}" | base64 -d > /opt/frappe/apps.json; \
fi
USER frappe
RUN export APP_INSTALL_ARGS="" && \
if [ -n "${APPS_JSON_BASE64}" ]; then \
RUN --mount=type=secret,id=apps_json,target=/opt/frappe/apps.json,uid=1000,gid=1000 \
export APP_INSTALL_ARGS="" && \
if [ -f /opt/frappe/apps.json ] && [ -s /opt/frappe/apps.json ]; then \
export APP_INSTALL_ARGS="--apps_path=/opt/frappe/apps.json"; \
fi && \
bench init ${APP_INSTALL_ARGS}\
@ -40,7 +34,6 @@ WORKDIR /home/frappe/frappe-bench
VOLUME [ \
"/home/frappe/frappe-bench/sites", \
"/home/frappe/frappe-bench/sites/assets", \
"/home/frappe/frappe-bench/logs" \
]

View file

@ -137,7 +137,6 @@ WORKDIR /home/frappe/frappe-bench
VOLUME [ \
"/home/frappe/frappe-bench/sites", \
"/home/frappe/frappe-bench/sites/assets", \
"/home/frappe/frappe-bench/logs" \
]

View file

@ -13,7 +13,6 @@ services:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
- --skip-character-set-client-handshake
- --skip-innodb-read-only-compressed
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD:-changeit}
MARIADB_AUTO_UPGRADE: 1

View file

@ -20,7 +20,6 @@ services:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
- --skip-character-set-client-handshake
- --skip-innodb-read-only-compressed # Temporary fix for MariaDB 10.6
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD:-123}
MARIADB_AUTO_UPGRADE: 1

19
pwd.yml
View file

@ -1,6 +1,6 @@
services:
backend:
image: frappe/erpnext:v16.13.2
image: frappe/erpnext:v16.14.0
networks:
- frappe_network
deploy:
@ -16,7 +16,7 @@ services:
MARIADB_ROOT_PASSWORD: admin
configurator:
image: frappe/erpnext:v16.13.2
image: frappe/erpnext:v16.14.0
networks:
- frappe_network
deploy:
@ -45,7 +45,7 @@ services:
- logs:/home/frappe/frappe-bench/logs
create-site:
image: frappe/erpnext:v16.13.2
image: frappe/erpnext:v16.14.0
networks:
- frappe_network
deploy:
@ -78,7 +78,7 @@ services:
bench new-site --mariadb-user-host-login-scope='%' --admin-password=admin --db-root-username=root --db-root-password=admin --install-app erpnext --set-default frontend;
db:
image: mariadb:10.6
image: mariadb:11.8
networks:
- frappe_network
healthcheck:
@ -92,7 +92,6 @@ services:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
- --skip-character-set-client-handshake
- --skip-innodb-read-only-compressed # Temporary fix for MariaDB 10.6
environment:
MYSQL_ROOT_PASSWORD: admin
MARIADB_ROOT_PASSWORD: admin
@ -100,7 +99,7 @@ services:
- db-data:/var/lib/mysql
frontend:
image: frappe/erpnext:v16.13.2
image: frappe/erpnext:v16.14.0
networks:
- frappe_network
depends_on:
@ -126,7 +125,7 @@ services:
- "8080:8080"
queue-long:
image: frappe/erpnext:v16.13.2
image: frappe/erpnext:v16.14.0
networks:
- frappe_network
deploy:
@ -145,7 +144,7 @@ services:
FRAPPE_REDIS_QUEUE: redis://redis-queue:6379
queue-short:
image: frappe/erpnext:v16.13.2
image: frappe/erpnext:v16.14.0
networks:
- frappe_network
deploy:
@ -182,7 +181,7 @@ services:
condition: on-failure
scheduler:
image: frappe/erpnext:v16.13.2
image: frappe/erpnext:v16.14.0
networks:
- frappe_network
deploy:
@ -196,7 +195,7 @@ services:
- logs:/home/frappe/frappe-bench/logs
websocket:
image: frappe/erpnext:v16.13.2
image: frappe/erpnext:v16.14.0
networks:
- frappe_network
deploy: