Local PostgreSQL with Docker Compose
The Billing Rails Compose file starts an isolated PostgreSQL 17 service for local development and tests. It does not share the root repository’s boo-mcp-test-db container.
Defaults:
-
loopback address
127.0.0.1; -
host port
55440, avoiding the existing root test port55439; -
PostgreSQL user
billing; -
local-only password
billing-local-only; -
databases
billing_rails_developmentandbilling_rails_test; -
persistent Compose volume
billing-rails-local_postgres_data.
The password is a development default, not a production credential. Choose any password override before the volume is initialized for the first time. The host port may be changed on any start. For example:
BILLING_POSTGRES_PORT=55441 BILLING_POSTGRES_PASSWORD='another-local-password' \ docker compose -f docker-compose.yml up -d --wait postgres
PostgreSQL stores the role password in the named volume. Merely changing BILLING_POSTGRES_PASSWORD on a later start does not rotate that password and makes the healthcheck use credentials that PostgreSQL does not recognize. To rotate it without deleting data:
-
Run
docker compose -f docker-compose.yml exec postgres psql -U billing -d postgres. -
At the
psqlprompt, run\password billing, enter the new value twice, then run\q. -
Start Compose with the same new
BILLING_POSTGRES_PASSWORD. Compose may replace the service container, but it keepsbilling-rails-local_postgres_data.
Do not put the new password in SQL, shell history, source files, or documentation.
Start and initialize
From billing_rails:
docker compose -f docker-compose.yml up -d --wait postgres
On first initialization, the container creates both databases and loads the checked-in db/structure.sql into each. Initialization scripts run automatically only when the named volume is new. It also records the Rails environment (development or test) and the structure fingerprint so Rails’ protected-environment and schema checks remain active. The script is safe to invoke manually because it leaves a nonempty public schema unchanged and does not claim that an existing schema matches the current structure file.
If an older billing-rails-local_postgres_data volume lacks billing_rails_test, or contains an empty development or test database, recover it without deleting the volume:
docker compose -f docker-compose.yml exec -T postgres \ /docker-entrypoint-initdb.d/10-create-test-database.sh
This creates the missing test database, loads db/structure.sql only into an empty public schema, and restores the known Rails environment marker. It does not migrate or overwrite a populated database. For later schema changes, use the repository’s migration workflow and PostgreSQL schema guide.
Check service state and readiness without changing it:
docker compose -f docker-compose.yml ps docker compose -f docker-compose.yml exec postgres \ pg_isready -U billing -d billing_rails_development
Run the application and tests
bin/test-local defaults to this persistent service: loopback port 55440, user billing, password billing-local-only. The application server still needs the explicit environment below. If you chose a different local password, export it for tests too. A legacy test instance can be selected with explicit BILLING_DB_PORT, BILLING_DB_USER and BILLING_DB_PASSWORD overrides; it must have the current schema before running tests.
export BILLING_DB_HOST=127.0.0.1 export BILLING_DB_PORT=55440 export BILLING_DB_USER=billing export BILLING_DB_PASSWORD=billing-local-only bin/rails server sh bin/test-local test/services/billing/pricing_test.rb
Use the host port and password supplied to Compose when overriding either default.
Stop without deleting data
docker compose -f docker-compose.yml stop
docker compose -f docker-compose.yml down removes the service container and network while keeping the named volume. Deleting billing-rails-local_postgres_data permanently deletes both local Billing Rails databases and is intentionally outside this routine setup workflow.