-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathdocker-compose.yml
More file actions
119 lines (110 loc) · 5.59 KB
/
Copy pathdocker-compose.yml
File metadata and controls
119 lines (110 loc) · 5.59 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
# vis — containerised gateway
# Everything vis needs is inside the image (JDK, clojure, maven, python, node,
# chrome, ffmpeg, and the Parakeet ASR model). The
# host contributes nothing but a port, a state volume and a workspace.
#
# Site tooling is NOT in here. This file builds and runs the BASE image; a
# deployment that needs its own CLIs extends it in its own repository (see the
# Dockerfile header) and points `VIS_IMAGE`/`VIS_TAG` at that derived tag.
#
# The gateway itself is the native binary this source builds: `docker compose
# build` runs native-image (roughly twenty minutes and a ~12 GiB live set), and
# what the container serves is exactly the artifact a release publishes.
#
# docker compose build
# docker compose up -d
# docker compose exec vis-gateway cat /home/vis/.vis/gateway-token
#
# Publish address: `VIS_BIND_HOST` defaults to loopback. If you front the
# gateway with a reverse proxy / ingress that terminates TLS, bind the PRIVATE
# interface that proxy dials (e.g. VIS_BIND_HOST=10.0.0.5) so the container can
# replace a systemd-run gateway with no change on the proxy side. Binding
# 0.0.0.0 additionally exposes the gateway on every public NIC, bypassing that
# proxy (and its TLS) entirely.
services:
vis-gateway:
build:
context: .
dockerfile: Dockerfile
args:
# Build-time toggles only; version pins live in the Dockerfile's ARGs.
WITH_CHROME: ${WITH_CHROME:-true}
# No version arg: `vis-agent --version` reads a resource stamped from
# the repo-root VIS_VERSION, which is the only version source there is.
image: ${VIS_IMAGE:-vis-gateway}:${VIS_TAG:-local}
container_name: vis-gateway
restart: unless-stopped
# tini is the image's ENTRYPOINT and reaps what the agent spawns, so
# compose's own init is redundant here.
ports:
- "${VIS_BIND_HOST:-127.0.0.1}:${VIS_BIND_PORT:-7890}:7890"
volumes:
# State: the LMDB store, config, and the auto-generated bearer token.
# Named volume, not a bind mount — uid 10001 inside the container owns it,
# and a host bind would land root-owned and unwritable on first boot.
- vis-state:/home/vis/.vis
# The workspace the agent actually edits. Nothing else on the host is
# reachable: no docker socket, no /etc, no other user's home.
- ${VIS_WORKSPACE:-./work}:/work
# The GitHub identity, split from the state volume on purpose: `docker
# volume rm vis-state` throws away session history, and doing so must not
# also throw away a registered SSH key (which would have to be deleted on
# github.com and re-added) or a credential a derived image's CLI stored.
# .ssh — id_ed25519_github + known_hosts + the github.com Host block
# .config — git's config, which the image points here with
# GIT_CONFIG_GLOBAL rather than leaving it in ~/.gitconfig,
# beside whatever a derived image keeps there.
# Both paths exist in the image owned by uid 10001, which is what makes
# docker seed these volumes writable — see the Dockerfile's useradd.
- vis-ssh:/home/vis/.ssh
- vis-config:/home/vis/.config
# The model cache lives in the image, so a `docker volume rm` of the
# state volume costs nothing but the session history.
environment:
# VIS_HOME/VIS_PARAKEET_MODEL_DIR are already set in the image; repeated
# here only when you want to override them.
TZ: ${TZ:-Europe/Warsaw}
# /healthz is unauthenticated by design (everything under /v1 is 401), so
# it is the only probe that works without minting a token.
healthcheck:
test: ["CMD", "curl", "-fsS", "-o", "/dev/null", "http://127.0.0.1:7890/healthz"]
interval: 30s
timeout: 5s
start_period: 60s
retries: 3
# The agent runs untrusted, model-authored commands. It is already an
# unprivileged user in a namespace; deny the escalation paths outright.
security_opt:
- no-new-privileges:true
# NOT `cap_drop: ALL`. Chromium's own sandbox needs to create user
# namespaces; stripped of every capability it dies on the first launch and
# the only cure is running the browser with --no-sandbox, which is strictly
# worse. no-new-privileges above already blocks the setuid escalation path.
# Chrome needs a bigger /dev/shm than docker's 64 MB default, or it can
# terminate on the first heavy page.
shm_size: ${VIS_SHM_SIZE:-1gb}
logging:
driver: json-file
options:
max-size: "50m"
max-file: "5"
volumes:
vis-state:
# Explicit `name:` on the two credential volumes, and only on them.
# Compose otherwise prefixes a volume with the project name, so the same
# secret material would live under `vis_vis-ssh` here and `foo_vis-ssh`
# in a checkout cloned to another directory. These two can be provisioned
# out of band — possibly before the image is ever built — so their identity
# must not depend on what the working copy happens to be called.
# vis-state is deliberately left prefixed: it is per-checkout state, and
# renaming it would orphan the gateway token and sessions of anyone who
# already has a `vis_vis-state` volume.
# If these volumes were populated before this file first ran, compose warns
# "already exists but was not created by Docker Compose". That warning is
# expected and harmless: compose adopts the volume as-is. Do NOT silence it
# with `external: true` — that would make a fresh checkout fail outright
# instead of creating the two empty volumes an unprovisioned run needs.
vis-ssh:
name: vis-ssh
vis-config:
name: vis-config