Update tech_docs/docker_compose_guide.md
This commit is contained in:
@@ -32,7 +32,7 @@ serendipity/
|
|||||||
|
|
||||||
### 2. The Royal Charter (`kingdom.yml`)
|
### 2. The Royal Charter (`kingdom.yml`)
|
||||||
|
|
||||||
```yaml
|
|
||||||
kingdom:
|
kingdom:
|
||||||
# determinism knobs
|
# determinism knobs
|
||||||
seed: 42
|
seed: 42
|
||||||
@@ -53,7 +53,7 @@ kingdom:
|
|||||||
to: stdout
|
to: stdout
|
||||||
- format: yaml
|
- format: yaml
|
||||||
to: out/kingdom_rendered.yaml
|
to: out/kingdom_rendered.yaml
|
||||||
```
|
|
||||||
|
|
||||||
Nothing outside this file ever changes the deterministic output except the **seed**.
|
Nothing outside this file ever changes the deterministic output except the **seed**.
|
||||||
|
|
||||||
@@ -63,12 +63,12 @@ Nothing outside this file ever changes the deterministic output except the **see
|
|||||||
|
|
||||||
Every object **MUST** be valid YAML and **MAY** include Jinja2 expressions inside **quoted** scalars only.
|
Every object **MUST** be valid YAML and **MAY** include Jinja2 expressions inside **quoted** scalars only.
|
||||||
|
|
||||||
```yaml
|
|
||||||
# objects/unicorn.yaml
|
# objects/unicorn.yaml
|
||||||
id: unicorn
|
id: unicorn
|
||||||
color: "{{ rng.choice(['silver','iridescent']) }}"
|
color: "{{ rng.choice(['silver','iridescent']) }}"
|
||||||
blessing: "{{ magic.uuid4() }}"
|
blessing: "{{ magic.uuid4() }}"
|
||||||
```
|
|
||||||
|
|
||||||
Important:
|
Important:
|
||||||
- Expressions are **strings** → safe for YAML parsers.
|
- Expressions are **strings** → safe for YAML parsers.
|
||||||
@@ -78,7 +78,7 @@ Important:
|
|||||||
|
|
||||||
### 4. The Single Rulebook (`rules/resolve.j2`)
|
### 4. The Single Rulebook (`rules/resolve.j2`)
|
||||||
|
|
||||||
```jinja2
|
|
||||||
{#- 1. Bootstrap deterministic engines -#}
|
{#- 1. Bootstrap deterministic engines -#}
|
||||||
{% set rng = load_rng(kingdom.rng) %}
|
{% set rng = load_rng(kingdom.rng) %}
|
||||||
{% set magic = load_magic(kingdom.magic) %}
|
{% set magic = load_magic(kingdom.magic) %}
|
||||||
@@ -93,7 +93,7 @@ Important:
|
|||||||
|
|
||||||
{#- 3. Emit final deterministic YAML -#}
|
{#- 3. Emit final deterministic YAML -#}
|
||||||
{{ court | to_yaml }}
|
{{ court | to_yaml }}
|
||||||
```
|
|
||||||
|
|
||||||
Helper filters (`load_rng`, `load_magic`, `glob`, `read_file`, `render_str`) are registered once at startup; **they never change** and are **not serialisable**, so they cannot leak into objects.
|
Helper filters (`load_rng`, `load_magic`, `glob`, `read_file`, `render_str`) are registered once at startup; **they never change** and are **not serialisable**, so they cannot leak into objects.
|
||||||
|
|
||||||
@@ -101,7 +101,7 @@ Helper filters (`load_rng`, `load_magic`, `glob`, `read_file`, `render_str`) are
|
|||||||
|
|
||||||
### 5. Bootstrap Script (one-time, never edited)
|
### 5. Bootstrap Script (one-time, never edited)
|
||||||
|
|
||||||
```python
|
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# bootstrap.py (kept outside kingdom/)
|
# bootstrap.py (kept outside kingdom/)
|
||||||
import os, yaml, jinja2, glob, hashlib, random
|
import os, yaml, jinja2, glob, hashlib, random
|
||||||
@@ -128,7 +128,7 @@ env.globals.update({
|
|||||||
|
|
||||||
template = env.get_template('resolve.j2')
|
template = env.get_template('resolve.j2')
|
||||||
print(env.from_string(template.render(kingdom=meta['kingdom'])).render())
|
print(env.from_string(template.render(kingdom=meta['kingdom'])).render())
|
||||||
```
|
|
||||||
|
|
||||||
Run once → deterministic stream of bytes.
|
Run once → deterministic stream of bytes.
|
||||||
Commit the stream if you need reproducibility without Python.
|
Commit the stream if you need reproducibility without Python.
|
||||||
@@ -169,11 +169,11 @@ Commit the stream if you need reproducibility without Python.
|
|||||||
|
|
||||||
### 9. Single-Command Invocation (CI / Makefile)
|
### 9. Single-Command Invocation (CI / Makefile)
|
||||||
|
|
||||||
```makefile
|
|
||||||
render:
|
render:
|
||||||
@python bootstrap.py > kingdom_rendered.yaml
|
@python bootstrap.py > kingdom_rendered.yaml
|
||||||
@echo "SHA256: $$(sha256sum kingdom_rendered.yaml)"
|
@echo "SHA256: $$(sha256sum kingdom_rendered.yaml)"
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -187,7 +187,7 @@ render:
|
|||||||
Here is a **drop-in Jinja2 template skeleton** that turns the entire service stanza into variables you can override at render-time (`docker compose -f <(jinja2 compose.yml.j2 env.yml)` or `docker compose config`).
|
Here is a **drop-in Jinja2 template skeleton** that turns the entire service stanza into variables you can override at render-time (`docker compose -f <(jinja2 compose.yml.j2 env.yml)` or `docker compose config`).
|
||||||
You only need to set the variables you care about; everything else falls back to safe blanks or defaults.
|
You only need to set the variables you care about; everything else falls back to safe blanks or defaults.
|
||||||
|
|
||||||
```jinja2
|
|
||||||
# compose.yml.j2
|
# compose.yml.j2
|
||||||
services:
|
services:
|
||||||
{{ service_name | default("app") }}:
|
{{ service_name | default("app") }}:
|
||||||
@@ -316,11 +316,11 @@ services:
|
|||||||
{{ k }}: {{ v }}
|
{{ k }}: {{ v }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
```
|
|
||||||
|
|
||||||
Usage example with a tiny `env.yml`:
|
Usage example with a tiny `env.yml`:
|
||||||
|
|
||||||
```yaml
|
|
||||||
# env.yml
|
# env.yml
|
||||||
service_name: api
|
service_name: api
|
||||||
image: mycorp/api:1.4.2
|
image: mycorp/api:1.4.2
|
||||||
@@ -334,13 +334,13 @@ volumes:
|
|||||||
depends_on:
|
depends_on:
|
||||||
- db
|
- db
|
||||||
restart: always
|
restart: always
|
||||||
```
|
|
||||||
|
|
||||||
Render and validate:
|
Render and validate:
|
||||||
|
|
||||||
```bash
|
|
||||||
jinja2 compose.yml.j2 env.yml | docker compose -f - config # dry-run
|
jinja2 compose.yml.j2 env.yml | docker compose -f - config # dry-run
|
||||||
```
|
|
||||||
|
|
||||||
All other knobs (secrets, configs, devices, ulimits, etc.) can be added the same way—only when you need them.
|
All other knobs (secrets, configs, devices, ulimits, etc.) can be added the same way—only when you need them.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user