Skip to content

PostgreSQL

Curated name postgres. Adds a PostgreSQL 18 service to the workbench in compose mode, with seeded dev credentials and a readiness healthcheck.

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.

At init, or to an existing workbench:

Terminal window
monoceros init acme --with-services=postgres
monoceros add-service acme postgres

Need 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:

Terminal window
monoceros add-service acme postgres --as=analytics
Terminal window
monoceros remove-service acme postgres

Or 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.)

acme.yml
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).

Monoceros injects a connection env into the workspace container, prefixed with the service name, so the app/agent reaches the database without hardcoding anything:

VariableValue (defaults)
POSTGRES_URLpostgresql://monoceros:monoceros@postgres:5432/monoceros
POSTGRES_HOSTpostgres
POSTGRES_PORT5432
POSTGRES_USERmonoceros
POSTGRES_PASSWORDmonoceros
POSTGRES_DBmonoceros

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.