Skip to content

Commit d35acab

Browse files
committed
doc(BA-7272): update docker/README.md from the verified live deployment
1 parent 5943cfc commit d35acab

1 file changed

Lines changed: 71 additions & 19 deletions

File tree

docker/README.md

Lines changed: 71 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ All images take the same build-arg contract: `PYTHON_VERSION` (from
2929
`pants.toml`) and `PKGVER` (normalized `VERSION`), and install the release
3030
wheels staged in `dist/` with the build context at the repository root.
3131

32+
**Run every `lablup/backend.ai-*` image in one deployment at the SAME version.**
33+
The components exchange serialized messages over the shared Redis/Valkey event
34+
bus, and the message schema evolves between minor releases; a mixed-version
35+
fleet fails at runtime with deserialization errors (e.g. a pre-26.8 subscriber
36+
crashes on the `triggered_user` metadata field added in 26.8).
37+
3238
## Infra images (not published)
3339

3440
| Dockerfile | Role |
@@ -37,6 +43,29 @@ wheels staged in `dist/` with the build context at the repository root.
3743
| `linuxkit-nsenter.dockerfile` | Namespace helper for LinuxKit-based Docker Desktop hosts |
3844
| `socket-relay.dockerfile` | Relays the Docker socket for restricted mount scenarios |
3945

46+
## Deployment layout
47+
48+
A compose deployment needs, per service, a config file bind-mounted at the
49+
path the image's default command reads:
50+
51+
| Service | Config mount target | Notes |
52+
|---|---|---|
53+
| manager | `/etc/backend.ai/manager.toml` | also mount `fixtures/` at `/app/fixtures:ro` (initial DB fixtures) |
54+
| agent | `/etc/backend.ai/agent.toml` | see the privilege and path-parity sections below |
55+
| webserver | `/etc/backend.ai/webserver.conf` | note the `.conf` target name, not `.toml` |
56+
| storage-proxy | `/etc/backend.ai/storage-proxy.toml` | runs unprivileged — set `user:` to the vfroot owner UID:GID; mount TLS material at `/app/ssl:ro` if enabled |
57+
| appproxy-coordinator | `/etc/backend.ai/proxy-coordinator.toml` | |
58+
| appproxy-worker | `/etc/backend.ai/proxy-worker.toml` | one container per worker: each needs its OWN toml with a unique `authority`, protocol (`http`/`tcp`), `api_bind_addr` port, and non-overlapping `bind_port_range` — and the compose port mappings must match |
59+
60+
Shared prerequisites:
61+
62+
| Item | Used by | Why |
63+
|---|---|---|
64+
| halfstack services (PostgreSQL, Valkey/Redis, etcd) | all | the reference definitions live in `docker-compose.halfstack-main.yml` |
65+
| `supergraph.graphql` + a GraphQL gateway (e.g. `ghcr.io/graphql-hive/gateway`) | GraphQL federation | the supergraph schema is generated per release (`scripts/generate-graphql-schema.sh`); the gateway composes manager subgraphs |
66+
| `/etc/machine-id` bind mount | manager, agent | stable node identity |
67+
| `wheelhouse/` mount at `/app/wheelhouse` (optional) | manager, agent | staging directory for extra plugin wheels (e.g. accelerator plugins) installed into the container on top of the base image |
68+
4069
## Container privileges
4170

4271
Most services run fine with compose defaults (bridge network, config file
@@ -51,6 +80,7 @@ consciously — together they amount to root-equivalent control of the host.
5180
| `pid: host` ||| Host PID namespace visibility: the agent inspects and signals kernel processes by host PID |
5281
| `cgroup: host` (host cgroup namespace) ||| **Required, not optional** — see below |
5382
| Host `/sys` visibility ||| Container resource metrics are read from the host cgroupfs/sysfs (follows automatically from the host cgroup namespace) |
83+
| GPU device reservation || ✅ (GPU nodes) | compose-native form: `deploy.resources.reservations.devices` with `driver: nvidia, count: all, capabilities: [gpu]` (requires the NVIDIA container toolkit on the host) |
5484
| Path parity mounts ||| See below |
5585

5686
### The agent cgroup-namespace trap
@@ -69,50 +99,72 @@ set explicitly.
6999

70100
### Agent path parity
71101

72-
Docker resolves kernel bind-mount *sources* in the **host** filesystem, so any
73-
path the containerized agent hands to the host daemon must exist at the same
74-
absolute path on both sides. Bind-mount each of these host paths to the
75-
identical path inside the agent container:
102+
Docker resolves bind-mount *sources* in the **host** filesystem, so any
103+
absolute path the containerized agent hands to the host daemon must exist at
104+
the same absolute path on both sides. The paths are set by `agent.toml`
105+
**every one of them must be an absolute path**, bind-mounted host↔container at
106+
the identical location:
76107

77-
| Path (host = container) | Used for |
78-
|---|---|
79-
| `/var/lib/backend.ai` | Scratch roots of kernel containers |
80-
| `/tmp/backend.ai/ipc` | Agent↔kernel IPC sockets |
81-
| `/tmp/backend-ai-krunner` | Kernel-runner files: the image entrypoint copies them here so the host daemon can mount them into kernels |
82-
| vfolder mount roots (deployment-specific) | Data folder bind-mount sources |
108+
| Config knob (`agent.toml`) | Reference value | Used for |
109+
|---|---|---|
110+
| `[container] scratch-root` | `/var/lib/backend.ai/scratches` | Scratch roots of kernel containers |
111+
| `[agent] ipc-base-path` | `/tmp/backend.ai/ipc` | Agent↔kernel IPC sockets |
112+
| `[agent] var-base-path` | `/var/lib/backend.ai` | Plugin state bind-mounted into kernels (e.g. accelerator hook caches) |
113+
| — (fixed path) | `/tmp/backend-ai-krunner` | Kernel-runner files: the image entrypoint copies them here so the host daemon can mount them into kernels; **without this mount kernel creation fails** with `bind source path does not exist` (the entrypoint logs a warning at startup) |
114+
115+
With the reference values, three parity mounts cover everything:
116+
`/var/lib/backend.ai`, `/tmp/backend.ai`, and `/tmp/backend-ai-krunner`.
117+
118+
Vfolder roots (e.g. `/vfroot/local/volume1`) follow the same rule on the
119+
**storage-proxy**: mount each volume at the identical absolute path on host and
120+
in the storage-proxy container, so the kernel bind-mount sources it reports
121+
resolve on the host. The agent container itself does not need the vfroot mount.
83122

84123
## Reference compose file
85124

86-
`docker-compose.monorepo.yml` at the repository root composes the manager,
87-
webserver, and app proxy images and is the maintained example; it assumes the
88-
halfstack dependencies (PostgreSQL, Valkey, etcd) from
89-
`docker-compose.halfstack-main.yml` are running. The fragment below shows the
90-
full privilege set for the two elevated services:
125+
`docker-compose.monorepo.yml` at the repository root composes the service
126+
images and assumes the halfstack dependencies from
127+
`docker-compose.halfstack-main.yml`. The fragment below shows the full working
128+
shape of the two elevated services, verified against a live deployment:
91129

92130
```yaml
93131
services:
94132
manager:
95-
image: lablup/backend.ai-manager:26.9.0
133+
image: lablup/backend.ai-manager:26.4.4
96134
network_mode: host
97135
privileged: true
98136
volumes:
99137
- /var/run/docker.sock:/var/run/docker.sock
138+
- /etc/machine-id:/etc/machine-id
100139
- ./manager.toml:/etc/backend.ai/manager.toml:ro
101-
- /tmp/backend.ai/ipc:/tmp/backend.ai/ipc
140+
- ./fixtures:/app/fixtures:ro
102141
restart: unless-stopped
103142

104143
agent:
105-
image: lablup/backend.ai-agent:26.9.0
144+
image: lablup/backend.ai-agent:26.4.4
106145
network_mode: host
107146
privileged: true
108147
pid: host
109148
cgroup: host # REQUIRED on cgroup v2 hosts; Docker defaults to private
149+
deploy: # GPU nodes only
150+
resources:
151+
reservations:
152+
devices:
153+
- driver: nvidia
154+
count: all
155+
capabilities: [gpu]
110156
volumes:
111157
- /var/run/docker.sock:/var/run/docker.sock
158+
- /etc/machine-id:/etc/machine-id
112159
- ./agent.toml:/etc/backend.ai/agent.toml:ro
113160
# path-parity mounts: host path == container path
114161
- /var/lib/backend.ai:/var/lib/backend.ai
115-
- /tmp/backend.ai/ipc:/tmp/backend.ai/ipc
162+
- /tmp/backend.ai:/tmp/backend.ai
116163
- /tmp/backend-ai-krunner:/tmp/backend-ai-krunner
117164
restart: unless-stopped
118165
```
166+
167+
The agent entrypoint builds its krunner symlink farm **at container start**, so
168+
after adding or changing the parity mounts, recreate the container
169+
(`docker compose up -d --force-recreate agent`) — a restart of the old
170+
container is not enough.

0 commit comments

Comments
 (0)