You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docker/README.md
+71-19Lines changed: 71 additions & 19 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -29,6 +29,12 @@ All images take the same build-arg contract: `PYTHON_VERSION` (from
29
29
`pants.toml`) and `PKGVER` (normalized `VERSION`), and install the release
30
30
wheels staged in `dist/` with the build context at the repository root.
31
31
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
+
32
38
## Infra images (not published)
33
39
34
40
| Dockerfile | Role |
@@ -37,6 +43,29 @@ wheels staged in `dist/` with the build context at the repository root.
37
43
|`linuxkit-nsenter.dockerfile`| Namespace helper for LinuxKit-based Docker Desktop hosts |
38
44
|`socket-relay.dockerfile`| Relays the Docker socket for restricted mount scenarios |
39
45
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 |
| 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 |
|`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
+
40
69
## Container privileges
41
70
42
71
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.
51
80
|`pid: host`| — | ✅ | Host PID namespace visibility: the agent inspects and signals kernel processes by host PID |
52
81
|`cgroup: host` (host cgroup namespace) | — | ✅ |**Required, not optional** — see below |
53
82
| 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) |
54
84
| Path parity mounts | — | ✅ | See below |
55
85
56
86
### The agent cgroup-namespace trap
@@ -69,50 +99,72 @@ set explicitly.
69
99
70
100
### Agent path parity
71
101
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:
76
107
77
-
| Path (host = container) | Used for |
78
-
|---|---|
79
-
|`/var/lib/backend.ai`| Scratch roots of kernel containers |
|`[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.
83
122
84
123
## Reference compose file
85
124
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:
91
129
92
130
```yaml
93
131
services:
94
132
manager:
95
-
image: lablup/backend.ai-manager:26.9.0
133
+
image: lablup/backend.ai-manager:26.4.4
96
134
network_mode: host
97
135
privileged: true
98
136
volumes:
99
137
- /var/run/docker.sock:/var/run/docker.sock
138
+
- /etc/machine-id:/etc/machine-id
100
139
- ./manager.toml:/etc/backend.ai/manager.toml:ro
101
-
- /tmp/backend.ai/ipc:/tmp/backend.ai/ipc
140
+
- ./fixtures:/app/fixtures:ro
102
141
restart: unless-stopped
103
142
104
143
agent:
105
-
image: lablup/backend.ai-agent:26.9.0
144
+
image: lablup/backend.ai-agent:26.4.4
106
145
network_mode: host
107
146
privileged: true
108
147
pid: host
109
148
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]
110
156
volumes:
111
157
- /var/run/docker.sock:/var/run/docker.sock
158
+
- /etc/machine-id:/etc/machine-id
112
159
- ./agent.toml:/etc/backend.ai/agent.toml:ro
113
160
# path-parity mounts: host path == container path
114
161
- /var/lib/backend.ai:/var/lib/backend.ai
115
-
- /tmp/backend.ai/ipc:/tmp/backend.ai/ipc
162
+
- /tmp/backend.ai:/tmp/backend.ai
116
163
- /tmp/backend-ai-krunner:/tmp/backend-ai-krunner
117
164
restart: unless-stopped
118
165
```
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
0 commit comments