Containers and volumes
The containers and Docker volumes that make up a Workforce Intelligence deployment, and what each one holds.
The stack is defined in docker-compose.prod.yml under the project name wi-prod. The file
ships inside the wi-server image, and install.sh extracts it from the image it pulls, so it
always matches that version.
Containers#
| Service | Image | What it does |
|---|---|---|
postgres |
pgvector/pgvector:pg17 |
The database. Health-checked with pg_isready. Its port is not published. |
app |
ghcr.io/<owner>/wi-server:<tag> |
The application server on internal port 8300. On start it applies database migrations, then serves. It never loads sample data. It mounts the Docker socket so it can run the per-company Coworker workbench containers and the in-app updater. |
dokku |
dokku/dokku:0.35.16 |
The Dokku host for deployed Apps. Its container name is wi-prod-dokku. It publishes WI_DOKKU_SSH_PORT (default 22) for Builders' git push. |
web |
ghcr.io/<owner>/wi-web:<tag> |
Caddy, serving the web app and forwarding /api/*, /auth/*, /healthz, and /apps/serve/*. It publishes ports 80 and 443 and starts after app is healthy and dokku has started. |
<owner> defaults to radialventures and <tag> to latest. See
Configuration reference.
The app container mounts three things:
- the
wi-prod-app-datavolume at/data; - the host's Docker socket;
- the host's Docker config directory (
/root/.dockerby default) read-only, for registry credentials.
Docker housekeeping trims what updates leave behind: old pre-update-* image tags, finished
update containers, unused workbench images and older backups. It never removes volumes or the
postgres and dokku services. See Docker housekeeping.
Coworker workbench containers and deployed Apps' containers are created on the same Docker daemon at runtime. They are not services in the compose file.
Container logs#
Every container in the stack writes its output to Docker's json-file log driver, capped at
10 MB per file and 3 files (about 30 MB per container). The compose file sets this once for
all four services. The in-app updater keeps the cap on the app and web containers it
recreates, and the Coworker workbench containers and the update's temporary helper container
get the same cap. The files sit under /var/lib/docker/containers/ on the host. Read a
service's log with sudo docker compose -p wi-prod logs <service>.
A box installed before the cap existed adopts it in two steps. Re-running install.sh
recreates postgres and dokku with the cap (the database restarts briefly). The next
in-app update gives app and web the cap. An in-app update alone leaves postgres and
dokku uncapped. Logs already written are not truncated.
Volumes#
| Volume | Holds | Back it up |
|---|---|---|
wi-prod-data |
Postgres data. | Yes. |
wi-prod-app-data |
Application files at /data: the identity signing key, Coworker workbench home directories (including any small data files a Coworker keeps for itself, such as a SQLite database under its data/ folder), and the pre-update database backups in /data/backups (the 2 newest are kept; older ones are removed by Docker housekeeping). |
Yes. |
wi-prod-dokku-data |
Dokku's data: deployed Apps' repositories and configuration. | Yes. |
wi-prod-caddy-data |
Caddy's certificates and certificate-authority account. | Keep it. Never delete it. See Domains and HTTPS. |
Together with .env, these volumes are everything that matters on the box. See
Backups and recovery on AWS and
Master key custody.
What the in-app updater replaces#
An in-app update replaces the app and web containers. It does not touch postgres or
dokku, and it does not change the compose file. See
What an update changes and
How an update runs.