mirror of
https://github.com/frappe/frappe_docker.git
synced 2026-06-18 06:05:09 +00:00
refactor(assets): externalize assets from sites volume using symlink
This commit is contained in:
parent
f8cfe4cb82
commit
0febe47d7b
8 changed files with 118 additions and 13 deletions
|
|
@ -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 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
|
||||
|
||||
|
|
|
|||
40
docs/06-migration/01-assets-volume-change.md
Normal file
40
docs/06-migration/01-assets-volume-change.md
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
---
|
||||
title: Assets Volume Change
|
||||
---
|
||||
|
||||
# Migration Guide: Assets Volume Change
|
||||
|
||||
## Background
|
||||
|
||||
The way `sites/assets` is handled has changed. Previously, assets were stored inside the a volume and persisted across container recreations. This could caused stale or mismatched assets after image updates. See [Assets Reference](../08-reference/07-how-assets-are-handeled.md) for details on the new approach.
|
||||
|
||||
## Who needs to migrate?
|
||||
|
||||
Anyone running an existing setup where the `sites` volume was created with **`frappe_docker` version `v3.1.0` or lower**.
|
||||
|
||||
**New setups are unaffected.**
|
||||
|
||||
## Migration Steps
|
||||
|
||||
1. **Pull an updated Image**
|
||||
|
||||
2. **Recreate all containers (`docker compose up --force-recreate`)**
|
||||
|
||||
3. **Enter the backend container**
|
||||
|
||||
```bash
|
||||
docker compose -p frappe exec -it backend bash
|
||||
```
|
||||
|
||||
4. **Run commands in container**
|
||||
```bash
|
||||
rm -rf /home/frappe/frappe-bench/sites/assets && \
|
||||
ln -s /home/frappe/frappe-bench/assets /home/frappe/frappe-bench/sites/assets && \
|
||||
exit
|
||||
```
|
||||
|
||||
## What this does
|
||||
|
||||
Replaces `sites/assets` directory with a symlink pointing to `/home/frappe/frappe-bench/assets`, which lives in the image layer. This ensures assets always match the running image version.
|
||||
|
||||
After this manual migration is made once no further steps are needed on further deployments.
|
||||
|
|
@ -114,14 +114,3 @@ 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.
|
||||
61
docs/08-reference/07-how-assets-are-handled.md
Normal file
61
docs/08-reference/07-how-assets-are-handled.md
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
---
|
||||
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 Docker build and replaced with a **symlink**. This means assets always come 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 && \
|
||||
ln -s /home/frappe/frappe-bench/assets /home/frappe/frappe-bench/sites/assets
|
||||
```
|
||||
|
||||
This runs **before** the `VOLUME` declaration, so the symlink is baked into
|
||||
the image layer.
|
||||
|
||||
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/assets` (symlink) | ✅ Yes (symlink itself) | Named volume (`sites`) |
|
||||
| `assets/` (symlink target) | ❌ No | Image layer |
|
||||
| `logs/` | ✅ Yes | Unnamed volume |
|
||||
|
||||
The symlink itself is persisted in the volume, but it always points to
|
||||
`assets/` which lives in the image layer and is discarded on container
|
||||
recreation.
|
||||
|
||||
## 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.
|
||||
|
|
@ -143,6 +143,11 @@ COPY --from=builder --chown=frappe:frappe /home/frappe/frappe-bench /home/frappe
|
|||
|
||||
WORKDIR /home/frappe/frappe-bench
|
||||
|
||||
# Move assets out of the sites volume, replace with symlink
|
||||
RUN cp -r /home/frappe/frappe-bench/sites/assets /home/frappe/frappe-bench/assets && \
|
||||
rm -rf /home/frappe/frappe-bench/sites/assets && \
|
||||
ln -s /home/frappe/frappe-bench/assets /home/frappe/frappe-bench/sites/assets
|
||||
|
||||
VOLUME [ \
|
||||
"/home/frappe/frappe-bench/sites", \
|
||||
"/home/frappe/frappe-bench/logs" \
|
||||
|
|
|
|||
|
|
@ -33,6 +33,11 @@ COPY --from=builder --chown=frappe:frappe /home/frappe/frappe-bench /home/frappe
|
|||
|
||||
WORKDIR /home/frappe/frappe-bench
|
||||
|
||||
# Move assets out of the sites volume, replace with symlink
|
||||
RUN cp -r /home/frappe/frappe-bench/sites/assets /home/frappe/frappe-bench/assets && \
|
||||
rm -rf /home/frappe/frappe-bench/sites/assets && \
|
||||
ln -s /home/frappe/frappe-bench/assets /home/frappe/frappe-bench/sites/assets
|
||||
|
||||
VOLUME [ \
|
||||
"/home/frappe/frappe-bench/sites", \
|
||||
"/home/frappe/frappe-bench/logs" \
|
||||
|
|
|
|||
|
|
@ -136,6 +136,11 @@ COPY --from=builder --chown=frappe:frappe /home/frappe/frappe-bench /home/frappe
|
|||
|
||||
WORKDIR /home/frappe/frappe-bench
|
||||
|
||||
# Move assets out of the sites volume, replace with symlink
|
||||
RUN cp -r /home/frappe/frappe-bench/sites/assets /home/frappe/frappe-bench/assets && \
|
||||
rm -rf /home/frappe/frappe-bench/sites/assets && \
|
||||
ln -s /home/frappe/frappe-bench/assets /home/frappe/frappe-bench/sites/assets
|
||||
|
||||
VOLUME [ \
|
||||
"/home/frappe/frappe-bench/sites", \
|
||||
"/home/frappe/frappe-bench/logs" \
|
||||
|
|
|
|||
Loading…
Reference in a new issue