PostgreSQL
Curated name postgres. Adds a PostgreSQL 18 service to the workbench in compose
mode, with seeded dev credentials and a readiness healthcheck.
What it’s for
Section titled “What it’s for”The default relational database for local development: a real Postgres your app and migrations run against, with dev credentials seeded for you so it works out of the box. Use it as the primary store for almost any web/app stack.
Add it
Section titled “Add it”At init, or to an existing workbench:
monoceros init acme --with-services=postgresmonoceros add-service acme postgresNeed a second database (say one for the app, one for analytics)? Add it again
under a different name with --as - each instance gets its own host, data dir,
and connection env:
monoceros add-service acme postgres --as=analyticsRemove it
Section titled “Remove it”monoceros remove-service acme postgresOr delete the service’s block from acme.yml by hand and re-run
monoceros apply acme - the yml is the source of truth. (Its data volume monoceros-acme-data-postgres is removed with the workbench on
monoceros remove, which backs it up first.)
The yml entry
Section titled “The yml entry”services: - name: postgres # host name in the container + data dir name image: postgres:18 port: 5432 # in-container port (feeds `monoceros tunnel`) env: POSTGRES_USER: ${POSTGRES_USER} # values live in acme.env POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: ${POSTGRES_DB} volumes: - data:/var/lib/postgresql # the service's own Docker volume restart: unless-stopped healthcheck: # workspace waits for service_healthy test: [CMD, pg_isready, -U, '${POSTGRES_USER}', -d, '${POSTGRES_DB}'] interval: 10s timeout: 5s retries: 5 connectionEnv: # → the workspace env vars below URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${host}:${port}/${POSTGRES_DB} HOST: ${host} PORT: ${port} USER: ${POSTGRES_USER} PASSWORD: ${POSTGRES_PASSWORD} DB: ${POSTGRES_DB}The credentials are ${VAR} references; the real values live in acme.env (dev
default monoceros for user, password, and database), so the yml stays
shareable without baking credentials in (see
Workbench configuration).
What your code sees
Section titled “What your code sees”Monoceros injects a connection env into the workspace container, prefixed with the service name, so the app/agent reaches the database without hardcoding anything:
| Variable | Value (defaults) |
|---|---|
POSTGRES_URL | postgresql://monoceros:monoceros@postgres:5432/monoceros |
POSTGRES_HOST | postgres |
POSTGRES_PORT | 5432 |
POSTGRES_USER | monoceros |
POSTGRES_PASSWORD | monoceros |
POSTGRES_DB | monoceros |
The prefix is the service name, uppercased. A second instance added with
--as=analytics gets ANALYTICS_URL, ANALYTICS_HOST, … - so two databases
never collide. Monoceros does not inject a bare DATABASE_URL; map
POSTGRES_URL to whatever your framework expects in the project’s own .env.