fix(build): add optional CACHE_BUST for custom image rebuilds

This commit is contained in:
jslocomotor 2026-04-25 17:06:20 +02:00
parent 84e0608209
commit a260d9a431
3 changed files with 55 additions and 28 deletions

View file

@ -56,9 +56,9 @@ Choose the appropriate build command based on your container runtime and desired
```bash ```bash
docker build \ docker build \
--no-cache \
--build-arg=FRAPPE_PATH=https://github.com/frappe/frappe \ --build-arg=FRAPPE_PATH=https://github.com/frappe/frappe \
--build-arg=FRAPPE_BRANCH=version-16 \ --build-arg=FRAPPE_BRANCH=version-16 \
--build-arg=APPS_JSON_HASH="$(sha256sum apps.json | awk '{print $1}')" \
--secret=id=apps_json,src=apps.json \ --secret=id=apps_json,src=apps.json \
--tag=custom:16 \ --tag=custom:16 \
--file=images/layered/Containerfile . --file=images/layered/Containerfile .
@ -68,9 +68,9 @@ docker build \
```bash ```bash
podman build \ podman build \
--no-cache \
--build-arg=FRAPPE_PATH=https://github.com/frappe/frappe \ --build-arg=FRAPPE_PATH=https://github.com/frappe/frappe \
--build-arg=FRAPPE_BRANCH=version-16 \ --build-arg=FRAPPE_BRANCH=version-16 \
--build-arg=APPS_JSON_HASH="$(sha256sum apps.json | awk '{print $1}')" \
--secret=id=apps_json,src=apps.json \ --secret=id=apps_json,src=apps.json \
--tag=custom:16 \ --tag=custom:16 \
--file=images/layered/Containerfile . --file=images/layered/Containerfile .
@ -78,38 +78,64 @@ podman build \
## CI/CD pipelines ## CI/CD pipelines
Example: When using automated builds, `CACHE_BUST` can be used to control cache invalidation of the frappe layer in order to rebuild it.
Possible techniques:
- No override: normal Docker layer caching is used
- Timestamp: force a rebuild on every pipeline run
- Pipeline run ID: rebuild once per CI run
- Commit SHA: rebuild once per commit
- apps.json hash: rebuild only when the custom app definition changes
Examples:
Commit SHA from GitHub
```yaml ```yaml
- name: Build Docker image - name: Build Docker image
shell: sh shell: sh
run: | run: |
docker build \ docker build \
--build-arg=FRAPPE_PATH=https://github.com/frappe/frappe \ --build-arg=FRAPPE_PATH=https://github.com/frappe/frappe \
--build-arg=FRAPPE_BRANCH=version-16 \ --build-arg=FRAPPE_BRANCH=version-16 \
--build-arg=APPS_JSON_HASH="$(sha256sum apps.json | awk '{print $1}')" \ --build-arg=CACHE_BUST="$GITHUB_SHA" \
--secret=id=apps_json,src=apps.json \ --secret=id=apps_json,src=apps.json \
--tag=custom:16 \ --tag=custom:16 \
--file=images/layered/Containerfile . --file=images/layered/Containerfile .
```
apps.json hash
```yaml
- name: Build Docker image
shell: sh
run: |
docker build \
--build-arg=FRAPPE_PATH=https://github.com/frappe/frappe \
--build-arg=FRAPPE_BRANCH=version-16 \
--build-arg=CACHE_BUST="$(sha256sum apps.json | awk '{print $1}')" \
--secret=id=apps_json,src=apps.json \
--tag=custom:16 \
--file=images/layered/Containerfile .
``` ```
## Build args, secrets and flags ## Build args, secrets and flags
| Variable | Purpose | | Variable | Purpose |
| -------------------- | ------------------------------------------------------------------------------------------------ | | -------------------- | ----------------------------------------------------------------------------------------------- |
| **Frappe Framework** | | | **Frappe Framework** | |
| FRAPPE_PATH | Repository URL for Frappe framework source code. Defaults to <https://github.com/frappe/frappe> | | 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-16 | | FRAPPE_BRANCH | Branch to use for Frappe framework. Defaults to version-16 |
| **Custom Apps** | | | **Custom Apps** | |
| APPS_JSON_HASH | Hash of `apps.json`, used to invalidate the cached layer when `apps_json` is passed as a secret. | | CACHE_BUST | Can be used to invalidate the cached layer when `apps_json` is passed as a secret. |
| (secret) apps_json | Passed via `--secret=id=apps_json,src=apps.json`. Never use `--build-arg` for this file. | | (secret) apps_json | Passed via `--secret=id=apps_json,src=apps.json`. Never use `--build-arg` for this file. |
| **Dependencies** | | | **Dependencies** | |
| PYTHON_VERSION | Python version for the base image | | PYTHON_VERSION | Python version for the base image |
| NODE_VERSION | Node.js version | | NODE_VERSION | Node.js version |
| WKHTMLTOPDF_VERSION | wkhtmltopdf version | | WKHTMLTOPDF_VERSION | wkhtmltopdf version |
| **bench only** | | | **bench only** | |
| DEBIAN_BASE | Debian base version for the bench image, defaults to `bookworm` | | DEBIAN_BASE | Debian base version for the bench image, defaults to `bookworm` |
| WKHTMLTOPDF_DISTRO | use the specified distro for debian package. Default is `bookworm` | | WKHTMLTOPDF_DISTRO | use the specified distro for debian package. Default is `bookworm` |
# Deploy the stack # Deploy the stack

View file

@ -118,9 +118,10 @@ USER frappe
ARG FRAPPE_BRANCH=version-16 ARG FRAPPE_BRANCH=version-16
ARG FRAPPE_PATH=https://github.com/frappe/frappe ARG FRAPPE_PATH=https://github.com/frappe/frappe
ARG APPS_JSON_HASH="" ARG CACHE_BUST=""
RUN --mount=type=secret,id=apps_json,target=/opt/frappe/apps.json,uid=1000,gid=1000 \ RUN --mount=type=secret,id=apps_json,target=/opt/frappe/apps.json,uid=1000,gid=1000 \
: "${APPS_JSON_HASH}" && \ : "${CACHE_BUST}" && \
export APP_INSTALL_ARGS="" && \ export APP_INSTALL_ARGS="" && \
if [ -f /opt/frappe/apps.json ] && [ -s /opt/frappe/apps.json ]; then \ if [ -f /opt/frappe/apps.json ] && [ -s /opt/frappe/apps.json ]; then \
export APP_INSTALL_ARGS="--apps_path=/opt/frappe/apps.json"; \ export APP_INSTALL_ARGS="--apps_path=/opt/frappe/apps.json"; \

View file

@ -5,12 +5,12 @@ FROM ${FRAPPE_IMAGE_PREFIX}/build:${FRAPPE_BRANCH} AS builder
ARG FRAPPE_BRANCH=version-16 ARG FRAPPE_BRANCH=version-16
ARG FRAPPE_PATH=https://github.com/frappe/frappe ARG FRAPPE_PATH=https://github.com/frappe/frappe
ARG APPS_JSON_HASH="" ARG CACHE_BUST=""
USER frappe USER frappe
RUN --mount=type=secret,id=apps_json,target=/opt/frappe/apps.json,uid=1000,gid=1000 \ RUN --mount=type=secret,id=apps_json,target=/opt/frappe/apps.json,uid=1000,gid=1000 \
: "${APPS_JSON_HASH}" && \ : "${CACHE_BUST}" && \
export APP_INSTALL_ARGS="" && \ export APP_INSTALL_ARGS="" && \
if [ -f /opt/frappe/apps.json ] && [ -s /opt/frappe/apps.json ]; then \ if [ -f /opt/frappe/apps.json ] && [ -s /opt/frappe/apps.json ]; then \
export APP_INSTALL_ARGS="--apps_path=/opt/frappe/apps.json"; \ export APP_INSTALL_ARGS="--apps_path=/opt/frappe/apps.json"; \