Files
carmanagement/DOCKER.md
T
2026-05-17 15:36:17 -04:00

7.9 KiB

Docker Environments

Three Docker environments are available:

  • Dockerfile.dev with docker-compose.dev.yml
  • Dockerfile.test with docker-compose.test.yml
  • Dockerfile.production with docker-compose.production.yml
  • docker-compose.pgmanage.yml for a standalone pgManage container

Development

Use the full dev stack for local work with hot reload and bundled Postgres and Redis:

docker compose -f docker-compose.dev.yml --profile full up --build

Services:

  • marketplace: http://localhost:3000
  • dashboard: http://localhost:3001
  • admin: http://localhost:3002
  • public-site: http://localhost:3003
  • api: http://localhost:4000
  • pgAdmin: http://localhost:5050

Each dev app now runs in its own container and can be started independently with a profile tag:

docker compose -f docker-compose.dev.yml --profile api up --build
docker compose -f docker-compose.dev.yml --profile marketplace up --build
docker compose -f docker-compose.dev.yml --profile dashboard up --build
docker compose -f docker-compose.dev.yml --profile admin up --build
docker compose -f docker-compose.dev.yml --profile public-site up --build
docker compose -f docker-compose.dev.yml --profile tools up --build

Notes:

  • api starts postgres, redis, and migrate automatically through dependencies.
  • frontend profiles also start api and its dependencies automatically.
  • tools starts only pgadmin plus its required postgres dependency.

On startup, Docker now waits for Postgres to become healthy, runs a one-shot migrate service, and only then starts the selected app container. For development, that bootstrap runs db:generate every time, but db:deploy and db:seed only the first time for a persisted dev database, so your local data survives rebuilds and normal restarts.

Default dev platform administrator:

  • email: admin@rentaldrivego.com
  • password: changeme123

If you intentionally want a fresh dev bootstrap:

docker compose -f docker-compose.dev.yml down -v

If you want to keep the database and only apply new schema changes manually:

docker compose -f docker-compose.dev.yml run --rm migrate sh -c "npm run db:deploy"

pgAdmin dev login:

  • email: admin@rentaldrivego.local
  • email: admin@rentaldrivego.dev
  • password: admin

pgAdmin opens with the dev Postgres server pre-registered as RentalDriveGo Dev DB.

pgAdmin Postgres connection:

  • host: postgres
  • port: 5432
  • database: rentaldrivego
  • username: postgres
  • password: password

Standalone pgManage

If you want a standalone Postgres management UI without starting the full development stack:

docker compose -f docker-compose.pgmanage.yml up -d

It publishes http://localhost:8000 with a standard Docker port mapping and persists its data in the named Docker volume pgmanage_data. From inside the container, connect to the local Postgres service through host.docker.internal:5432.

Test

Use the test stack to run repeatable containerized verification:

docker compose -f docker-compose.test.yml up --build --abort-on-container-exit

The test container runs:

  • npm run db:deploy
  • npm run db:generate
  • npm run type-check
  • npm run build

Production

The production stack runs behind Traefik (reverse proxy + automatic HTTPS via Let's Encrypt). All services communicate over a private Docker network (internal). Traefik reaches public-facing services via a separate traefik-proxy network.

1. Point DNS to your server

Add an A record for every subdomain to your server's public IP before deploying so Let's Encrypt can issue certificates:

Subdomain Service
rentaldrivego.ma marketplace and public site
api.rentaldrivego.ma API
pgmanage.rentaldrivego.ma pgManage (DB admin)

2. Install Docker and clone the repo

# Install Docker (if not already installed)
curl -fsSL https://get.docker.com | sh

git clone <repo-url> rentaldrivego
cd rentaldrivego

3. Create the shared Traefik network

Only needs to be done once per server. If it already exists this is a no-op.

docker network create traefik-proxy

4. Configure environment variables

cp .env.docker.production.example .env.docker.production

Open .env.docker.production and fill in every value. The minimum required secrets are:

Variable What to set
POSTGRES_PASSWORD Strong random password
JWT_SECRET Long random string (e.g. openssl rand -hex 64)
ACME_EMAIL Your email for Let's Encrypt notifications
RESEND_API_KEY Resend API key (or configure SMTP vars instead)

Production now derives DATABASE_URL inside the app container from POSTGRES_HOST, POSTGRES_PORT, POSTGRES_DB, POSTGRES_USER, and POSTGRES_PASSWORD when DATABASE_URL_FROM_POSTGRES=true. That avoids Prisma auth failures when the database password contains reserved URL characters such as @, :, or /.

The example file uses rentaldrivego.ma for the marketplace and public site. The dashboard and admin panel are routed under that same host at /dashboard and /admin.

5. Start Traefik

Traefik must be running before the app stack so it can wire up routes at startup.

docker compose -f traefik.yaml up -d

6. Build and start the app stack

npm run docker:prod:up

Docker will:

  1. Build the monorepo image
  2. Start all app services (api, marketplace, dashboard, admin, pgmanage)

Traefik automatically picks up the containers and provisions TLS certificates. Services are live at their https:// URLs within ~30 seconds.

Updating after a code change

Pull the latest code and rebuild only the changed service:

git pull
docker compose -p rentaldrivego-prod --env-file .env.docker.production -f docker-compose.production.yml up --build -d --no-deps <service>
# e.g. to redeploy only the API:
docker compose -p rentaldrivego-prod --env-file .env.docker.production -f docker-compose.production.yml up --build -d --no-deps api

To rebuild everything:

npm run docker:prod:up

Apply database migrations without downtime

docker compose -p rentaldrivego-prod --env-file .env.docker.production -f docker-compose.production.yml run --rm api npm run db:deploy

View logs

# All services
npm run docker:prod:logs

# Single service
npm run docker:prod:logs:api

Stop the stack

# Stop containers but keep volumes (data is preserved)
npm run docker:prod:down

# Stop and delete all data (destructive — irreversible)
docker compose -p rentaldrivego-prod --env-file .env.docker.production -f docker-compose.production.yml down -v

pgManage (DB admin UI)

pgManage is available at https://pgmanage.rentaldrivego.ma. To connect to the production database, add a connection inside pgManage with:

  • Host: localhost
  • Port: 5432
  • Database: rentaldrivego
  • Username: postgres
  • Password: value of POSTGRES_PASSWORD from .env.docker.production

Notes

  • The production image builds the whole monorepo once, then each service overrides its runtime command.
  • The dev compose file bind-mounts the repo and keeps node_modules in a named volume.
  • API_INTERNAL_URL is used for server-side container-to-container calls, while NEXT_PUBLIC_API_URL is used by the browser.
  • The Dockerfiles activate the repo's pinned npm@10.5.0 with corepack before install so container builds do not depend on the npm version bundled with the base image.
  • The dev compose stack stores Postgres data in postgres_dev_data and the bootstrap marker in postgres_bootstrap_state, so up --build does not reseed an existing local database.
  • If you need database schema updates inside Docker, run:
docker compose -f docker-compose.dev.yml run --rm migrate

If a cached base image still fails during npm ci, refresh it and rebuild without cache:

docker pull node:20-bookworm
docker compose -f docker-compose.dev.yml build --no-cache dashboard