Containers and volumes

The containers and Docker volumes that make up a Workforce Intelligence deployment, and what each one holds.

For: Administrators operating a deployment · Last updated

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-data volume at /data;
  • the host's Docker socket;
  • the host's Docker config directory (/root/.docker by 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.