-
-
Notifications
You must be signed in to change notification settings - Fork 727
Expand file tree
/
Copy pathdocker-compose.yml.tmpl
More file actions
231 lines (226 loc) · 9.26 KB
/
Copy pathdocker-compose.yml.tmpl
File metadata and controls
231 lines (226 loc) · 9.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
# vim: ft=yaml.docker-compose
services:
anthias-server:
image: ghcr.io/screenly/anthias-server:${DOCKER_TAG}-${DEVICE_TYPE}
build:
context: .
dockerfile: docker/Dockerfile.server
ports:
- 80:8080
environment:
- MAC_ADDRESS=${MAC_ADDRESS}
- HOST_USER=${USER}
- HOME=/data
- LISTEN=0.0.0.0
- CELERY_BROKER_URL=redis://redis:6379/0
- CELERY_RESULT_BACKEND=redis://redis:6379/0
# HTTP proxy support (GH #3239). upgrade_containers.sh sources
# /etc/anthias/proxy.env before envsubst, so these substitute to
# the configured proxy (or empty strings when none is set, which
# every client treats as "no proxy"). NO_PROXY already includes the
# anthias-server/redis service names so internal traffic bypasses
# the proxy.
- HTTP_PROXY=${HTTP_PROXY}
- HTTPS_PROXY=${HTTPS_PROXY}
- NO_PROXY=${NO_PROXY}
- http_proxy=${http_proxy}
- https_proxy=${https_proxy}
- no_proxy=${no_proxy}
# Chunk size for large browser uploads, for an operator behind a
# proxy that caps request bodies. Empty when unset, which the
# server reads as "use the default". The durable place to set it
# is `upload_chunk_size_mb` in ~/.anthias/anthias.conf, which
# wins over this and survives an upgrade; balena devices use a
# dashboard variable, which the supervisor injects into every
# service. This entry only carries a value exported into the
# environment of the run that renders the template.
- ANTHIAS_UPLOAD_CHUNK_SIZE_MB=${ANTHIAS_UPLOAD_CHUNK_SIZE_MB}
# Gate startup on redis actually answering PING (see the
# healthcheck on the redis service below) — plain service_started
# only orders container creation, so uvicorn's first Channels /
# Celery touch could still race a redis that hadn't finished
# loading its RDB. NOTE: docker-compose only; the balena
# supervisor doesn't support depends_on conditions, so fleet
# devices rely on each consumer's own reconnect logic instead.
depends_on:
redis:
condition: service_healthy
# No `devices:` here, deliberately. This service needs no hardware
# access at all: HDMI-CEC is driven by the anthias-viewer container
# (privileged, so it already sees every /dev/cec*) and reached over
# the Redis command bus — see src/anthias_server/lib/cec_client.py.
# /dev/vchiq used to be listed for libcec's display-power probe,
# which is gone.
restart: always
volumes:
- resin-data:/data
- /home/${USER}/.anthias:/data/.anthias
- /home/${USER}/anthias_assets:/data/anthias_assets
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
labels:
io.balena.features.supervisor-api: '1'
logging:
driver: journald
options:
tag: anthias-server
anthias-viewer:
image: ghcr.io/screenly/anthias-viewer:${DOCKER_TAG}-${DEVICE_TYPE}
build:
context: .
dockerfile: docker/Dockerfile.viewer
mem_limit: ${VIEWER_MEMORY_LIMIT_KB}k
# redis: the viewer subscribes to the anthias.viewer pub/sub
# channel and publishes the display resolution; wait for a PING
# so neither hits "connection refused" at boot. (compose-only —
# see the note on anthias-server's depends_on.)
depends_on:
anthias-server:
condition: service_started
redis:
condition: service_healthy
environment:
- HOME=/data
- PORT=8080
- NOREFRESH=1
- LISTEN=anthias-server
# Forward the host's system locale into the viewer container so
# AnthiasWebview can send a matching Accept-Language header
# (issue 480 — multi-language URL assets used to render in
# English regardless of the Pi's locale). upgrade_containers.sh
# sources /etc/default/locale before running envsubst, so these
# substitute to whatever `update-locale` wrote. When the host has
# no locale configured these substitute to empty strings; the
# viewer's start_viewer.sh treats an empty value as "unset" so
# downstream consumers see the container image's defaults rather
# than an empty LANG.
- LANG=${LANG}
- LANGUAGE=${LANGUAGE}
- LC_ALL=${LC_ALL}
# HTTP proxy support (GH #3239) — also picked up by QtWebEngine
# (Chromium reads http_proxy/https_proxy on Linux) for web assets.
- HTTP_PROXY=${HTTP_PROXY}
- HTTPS_PROXY=${HTTPS_PROXY}
- NO_PROXY=${NO_PROXY}
- http_proxy=${http_proxy}
- https_proxy=${https_proxy}
- no_proxy=${no_proxy}
privileged: true
restart: always
# cage (the wlroots kiosk compositor used on Pi 5 / x86 /
# arm64 viewers) doesn't always release the DRM master on
# SIGTERM — its event loop blocks on a libinput shutdown
# path that hangs on certain kernels, and the kernel's GPU
# driver leaves dangling references that prevent the next
# container start from acquiring DRM master. ``stop_grace_period``
# caps how long ``docker compose down/restart`` waits before
# SIGKILLing the container; 3s is short enough that an
# upgrade rolls in a reasonable time even if cage hangs.
# ``stop_signal: SIGKILL`` skips the SIGTERM-then-wait dance
# entirely on intentional stops — same effect as a kernel
# OOM killer landing on the viewer, which the next ``up``
# cleans up from automatically.
stop_grace_period: 3s
stop_signal: SIGKILL
shm_size: ${SHM_SIZE_KB}kb
volumes:
- resin-data:/data
- /home/${USER}/.asoundrc:/data/.asoundrc
- /home/${USER}/.anthias:/data/.anthias
- /home/${USER}/anthias_assets:/data/anthias_assets
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
labels:
io.balena.features.supervisor-api: '1'
logging:
driver: journald
options:
tag: anthias-viewer
anthias-celery:
# Runs on the same image as anthias-server with a CMD override.
# Shipping one image instead of two is the point — server and celery
# share their entire root filesystem (base apt + venv + app source),
# and a separate celery image was duplicating ~825 MB extracted of
# identical content per device. See refactor: drop celery image.
image: ghcr.io/screenly/anthias-server:${DOCKER_TAG}-${DEVICE_TYPE}
# ``mem_limit`` keeps a runaway celery task (e.g. a HEIC →
# WebP convert on a decompression-bomb fixture) from eating
# the box's RAM and starving the viewer. 60% of host (computed
# in bin/upgrade_containers.sh) leaves comfortable headroom on
# every supported SBC.
mem_limit: ${CELERY_MEMORY_LIMIT_KB}k
# ``nice -n 19 ionice -c 3`` keeps any subprocess celery
# spawns (ffprobe, Pillow's libheif binding) at idle priority
# so the on-device viewer always wins CPU + IO contention. No
# current task is CPU-bound enough that this matters in
# practice, but the wrappers are cheap insurance against a
# pathological input.
command: >
nice -n 19 ionice -c 3
celery -A anthias_server.celery_tasks.celery worker -B -n worker@anthias
--loglevel=info --scheduler celery.beat.Scheduler
# redis is both the broker and the beat heartbeat; gate on a PING
# so the worker doesn't burn its first connection retries during
# compose startup. (compose-only — see anthias-server's note.)
depends_on:
anthias-server:
condition: service_started
redis:
condition: service_healthy
environment:
- HOME=/data
- CELERY_BROKER_URL=redis://redis:6379/0
- CELERY_RESULT_BACKEND=redis://redis:6379/0
# HTTP proxy support (GH #3239) — the celery worker downloads URL
# assets (requests, honours these) and shells out to yt-dlp (inherits
# the container env).
- HTTP_PROXY=${HTTP_PROXY}
- HTTPS_PROXY=${HTTPS_PROXY}
- NO_PROXY=${NO_PROXY}
- http_proxy=${http_proxy}
- https_proxy=${https_proxy}
- no_proxy=${no_proxy}
# See the note on anthias-server: no hardware access needed. Celery
# runs the periodic display-power query and the schedule, but it
# asks anthias-viewer to do the CEC work rather than opening the
# devices itself.
restart: always
volumes:
- resin-data:/data
- /home/${USER}/.anthias:/data/.anthias
- /home/${USER}/anthias_assets:/data/anthias_assets
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
labels:
io.balena.features.supervisor-api: '1'
logging:
driver: journald
options:
tag: anthias-celery
redis:
image: ghcr.io/screenly/anthias-redis:${DOCKER_TAG}-${DEVICE_TYPE}
build:
context: .
dockerfile: docker/Dockerfile.redis
ports:
- 127.0.0.1:6379:6379
# Lets the depends_on conditions above hold service startup until
# redis actually answers, covering the RDB-load window after a
# restart on a slow SD card. start_period keeps the early probes
# from counting against the retry budget.
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 12
start_period: 10s
restart: always
volumes:
- redis-data:/var/lib/redis
logging:
driver: journald
options:
tag: anthias-redis
volumes:
resin-data:
redis-data: