Skip to content

Commit 4ff3363

Browse files
JohnMcLearclaude
andauthored
docs(docker): document settings.json writable-layer + env-var-vs-file semantics (#7819) (#7827)
Two related operator-facing docs gaps, both surfaced by #7819: 1. settings.json on disk is a *template*; env-var substitution happens at load time in memory only. Operators repeatedly mistake the templated file for a stale config because the docs never spell out that the on-disk file is intentionally unchanged by env vars. 2. The default docker-compose.yml puts settings.json in the container's writable layer with no host mount, which means admin /settings edits are silently lost on `docker compose down && up`, `pull`, or watchtower — but preserved across plain `restart`. Operators don't reliably know which compose verbs recreate the container. Adds two prose sections to doc/docker.md (explaining both gotchas, with a recreate-vs-restart table) and a commented-out `./settings.json:…` bind mount in both docker-compose.yml and the README compose example. Bind mount is opt-in so existing setups behave identically. No runtime change. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 689dd9d commit 4ff3363

2 files changed

Lines changed: 46 additions & 0 deletions

File tree

doc/docker.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,37 @@ Edit `<BASEDIR>/settings.json.docker` at your will. When rebuilding the image, t
2929

3030
**Each configuration parameter can also be set via an environment variable**, using the syntax `"${ENV_VAR}"` or `"${ENV_VAR:default_value}"`. For details, refer to `settings.json.template`.
3131

32+
### How `settings.json` and environment variables interact
33+
34+
This trips people up often enough that it's worth calling out explicitly (see [#7819](https://github.com/ether/etherpad/issues/7819)):
35+
36+
* `settings.json` inside the container is a **template** containing `${VAR:default}` placeholders.
37+
* Environment variable substitution happens at **load time, in memory only** — env vars never overwrite `settings.json` on disk.
38+
* `docker exec <container> cat /opt/etherpad-lite/settings.json` will therefore always show the *templated* file (e.g. `"port": "${PORT:9001}"`), regardless of what `PORT` is set to in your environment. The resolved value is what Etherpad uses at runtime; the file is unchanged.
39+
* The admin /settings page also reads this file directly, so the raw view shows placeholders too. The page now surfaces a banner and an "Effective" tab that displays the in-memory resolved values when placeholders are present.
40+
41+
### Persisting admin /settings edits across container recreates
42+
43+
`settings.json` lives in the container's writable layer by default. That means:
44+
45+
| Operation | Effect on `settings.json` |
46+
|------------------------------------------|------------------------------------------|
47+
| `docker restart` | Preserved (writable layer is reused) |
48+
| `docker compose restart` | Preserved |
49+
| `docker compose down && docker compose up` | **Reset** to the image template |
50+
| `docker compose pull && docker compose up` | **Reset** to the new image template |
51+
| Watchtower / image auto-update | **Reset** to the new image template |
52+
| `docker rm` + `docker run` | **Reset** to the image template |
53+
54+
If you intend to edit `settings.json` through the admin UI (rather than relying solely on env vars), mount the file from the host so edits survive container recreate:
55+
56+
```yaml
57+
volumes:
58+
- ./settings.json:/opt/etherpad-lite/settings.json
59+
```
60+
61+
(Bootstrap by copying `settings.json.docker` to `./settings.json` on the host before the first `up`.) The default compose example below ships this line commented out — uncomment it if you need persistent on-disk edits.
62+
3263
### Rebuilding including some plugins
3364
If you want to install some plugins in your container, it is sufficient to list them in the ETHERPAD_PLUGINS build variable.
3465
The variable value has to be a space separated, double quoted list of plugin names (see examples).
@@ -282,6 +313,13 @@ services:
282313
volumes:
283314
- plugins:/opt/etherpad-lite/src/plugin_packages
284315
- etherpad-var:/opt/etherpad-lite/var
316+
# OPTIONAL: persist admin /settings edits across container recreates.
317+
# Without this mount, settings.json lives in the image's writable
318+
# layer — `docker compose restart` preserves it, but `docker compose
319+
# down && up`, `pull`, or watchtower reverts it to the image
320+
# template. Uncomment if you intend to edit settings.json through
321+
# the /admin UI. See https://github.com/ether/etherpad/issues/7819.
322+
# - ./settings.json:/opt/etherpad-lite/settings.json
285323
depends_on:
286324
- postgres
287325
environment:

docker-compose.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@ services:
77
volumes:
88
- plugins:/opt/etherpad-lite/src/plugin_packages
99
- etherpad-var:/opt/etherpad-lite/var
10+
# OPTIONAL: persist admin /settings edits across container recreates.
11+
# Without this mount, settings.json lives in the image's writable
12+
# layer — `docker compose restart` preserves it, but `docker compose
13+
# down && up`, `pull`, or watchtower reverts it to the image
14+
# template. Uncomment if you intend to edit settings.json through
15+
# the /admin UI instead of (or in addition to) env vars. See
16+
# https://github.com/ether/etherpad/issues/7819.
17+
# - ./settings.json:/opt/etherpad-lite/settings.json
1018
depends_on:
1119
- postgres
1220
environment:

0 commit comments

Comments
 (0)