8aab968e09
Build & Deploy / Build & Push Docker Image (push) Successful in 1m2s
Test / Type Check (all packages) (push) Failing after 28s
Test / API Unit Tests (push) Has been skipped
Test / Homepage Unit Tests (push) Has been skipped
Test / Storefront Unit Tests (push) Has been skipped
Test / Admin Unit Tests (push) Has been skipped
Test / Dashboard Unit Tests (push) Has been skipped
Test / API Integration Tests (push) Has been skipped
Build & Deploy / Deploy to VPS (push) Successful in 3s
Comprehensive rename of all marketplace references to storefront: - API module: apps/api/src/modules/marketplace/ → storefront/ - Components: MarketplaceHeader → StorefrontHeader, MarketplaceShell → StorefrontShell, MarketplaceFooter → StorefrontFooter - Types: marketplace-homepage.ts → storefront-homepage.ts - Test files: employee-marketplace-* → employee-storefront-* - All source code identifiers, imports, route paths, and strings - Documentation (docs/), CI config (.gitlab-ci.yml), scripts - Dashboard, admin, storefront workspace references - Prisma field names preserved (isListedOnMarketplace, marketplaceRating, marketplaceFunnelEvent) as they map to database schema Validation: - API type-check: 0 errors - Storefront type-check: 0 errors - Dashboard type-check: 0 errors - Full monorepo type-check: only pre-existing admin TS18046
514 lines
20 KiB
Markdown
514 lines
20 KiB
Markdown
## 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
|
|
- `docker-compose.portainer.production.yml` for a standalone production Portainer deployment behind Traefik
|
|
- `docker-compose.registry.production.yml` for a standalone production Docker registry behind Traefik
|
|
- `docker-compose.registry.local.yml` for a Docker registry running on a separate local server with port `5000` exposed directly
|
|
|
|
### Development
|
|
|
|
Use the full dev stack for local work with hot reload and bundled Postgres and Redis:
|
|
|
|
```bash
|
|
docker compose -f docker-compose.dev.yml --profile full up --build
|
|
```
|
|
|
|
Services:
|
|
|
|
- storefront: `http://localhost:3000`
|
|
- dashboard: `http://localhost:3000/dashboard`
|
|
- admin: `http://localhost:3000/admin`
|
|
- 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:
|
|
|
|
```bash
|
|
docker compose -f docker-compose.dev.yml --profile api up --build
|
|
docker compose -f docker-compose.dev.yml --profile storefront 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
|
|
docker compose -f docker-compose.dev.yml --profile api --profile storefront --profile dashboard --profile admin 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.
|
|
|
|
Uploaded assets handled by the API, including vehicle photos and company branding images, are stored in the named Docker volume `api_uploads_dev` at `/var/lib/rentaldrivego/storage` inside the container. They stay available across normal container rebuilds and restarts.
|
|
|
|
Default dev platform administrator:
|
|
|
|
- email: `admin@rentaldrivego.com`
|
|
- password: `changeme123`
|
|
|
|
If you intentionally want a fresh dev bootstrap:
|
|
|
|
```bash
|
|
docker compose -f docker-compose.dev.yml down -v
|
|
```
|
|
|
|
If you want to keep the database and only apply new schema changes manually:
|
|
|
|
```bash
|
|
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:
|
|
|
|
```bash
|
|
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`.
|
|
For local HTTP access, pgManage defaults `PGMANAGE_SECURE_COOKIES=False`. If you expose it behind HTTPS instead, set `PGMANAGE_SECURE_COOKIES=True`.
|
|
If you are using the enterprise image, set `PGMANAGE_LICENSE_KEY` to remove the startup license error.
|
|
|
|
### Test
|
|
|
|
Use the test stack to run repeatable containerized verification:
|
|
|
|
```bash
|
|
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`
|
|
- `npm run test:api:integration`
|
|
|
|
### 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` | storefront and public site |
|
|
| `api.rentaldrivego.ma` | API |
|
|
| `pgmanage.rentaldrivego.ma` | pgManage (DB admin) |
|
|
| `portainer.rentaldrivego.ma` | Portainer |
|
|
| `registry.rentaldrivego.ma` | Docker registry |
|
|
|
|
#### 2. Install Docker and clone the repo
|
|
|
|
```bash
|
|
# 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.
|
|
|
|
```bash
|
|
docker network create traefik-proxy
|
|
```
|
|
|
|
#### 4. Configure environment variables
|
|
|
|
```bash
|
|
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) |
|
|
| `PGMANAGE_DOMAIN` | Hostname for pgManage, e.g. `pgmanage.rentaldrivego.ma` |
|
|
|
|
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 storefront and public site. The dashboard and admin panel are routed under that same host at `/dashboard` and `/admin`.
|
|
Set `PORTAINER_DOMAIN=portainer.rentaldrivego.ma` in `.env.docker.production` to expose Portainer through Traefik.
|
|
Set `PGMANAGE_DOMAIN=pgmanage.rentaldrivego.ma` to expose pgManage through Traefik, and set `PGMANAGE_LICENSE_KEY` if you are running the enterprise image.
|
|
Set `REGISTRY_DOMAIN=registry.rentaldrivego.ma` to expose the Docker registry through Traefik.
|
|
Set `REGISTRY_UPSTREAM_URL=http://<local-registry-server-ip>:5000` on the VPS when the registry itself runs on a different server and Traefik should reverse-proxy to it.
|
|
|
|
If you want to use a self-hosted registry on the same VPS, also set these values in `.env.docker.production`:
|
|
|
|
```text
|
|
REGISTRY_HOST=registry.rentaldrivego.ma
|
|
REGISTRY_USER=<registry-user>
|
|
REGISTRY_PASSWORD=<strong-registry-password>
|
|
REGISTRY_IMAGE=registry.rentaldrivego.ma/rentaldrivego/car_management_system
|
|
```
|
|
|
|
The registry bootstrap script uses `REGISTRY_USER` and `REGISTRY_PASSWORD` to generate the htpasswd file mounted into the registry container, so the same credentials can be used by GitLab CI for `docker login`.
|
|
|
|
#### 4a. Configure the registry for CI deploys
|
|
|
|
If you want GitLab CI to build once and deploy by pulling a prebuilt image on the VPS, configure one of these two modes in GitLab `Settings > CI/CD > Variables`:
|
|
|
|
- Built-in GitLab Container Registry:
|
|
Enable the project registry and use GitLab's default `CI_REGISTRY`, `CI_REGISTRY_USER`, `CI_REGISTRY_PASSWORD`, and `CI_REGISTRY_IMAGE` variables.
|
|
- Explicit registry variables:
|
|
Set `REGISTRY_HOST`, `REGISTRY_USER`, `REGISTRY_PASSWORD`, and `REGISTRY_IMAGE` yourself. This works for GitLab Registry, Docker Hub, GHCR, or another OCI registry.
|
|
|
|
If `REGISTRY_*` variables are set, the CI pipeline now uses them as a complete override and requires all four values. If they are unset, the pipeline falls back to GitLab's `CI_REGISTRY_*` variables.
|
|
|
|
For production image builds, also define these GitLab CI/CD variables with their real public URLs:
|
|
|
|
```text
|
|
NEXT_PUBLIC_API_URL=https://api.rentaldrivego.ma/api/v1
|
|
NEXT_PUBLIC_MARKETPLACE_URL=https://rentaldrivego.ma
|
|
NEXT_PUBLIC_DASHBOARD_URL=https://rentaldrivego.ma/dashboard
|
|
NEXT_PUBLIC_ADMIN_URL=https://rentaldrivego.ma/admin
|
|
```
|
|
|
|
The Docker build now fails if any of those values are missing or still point at `example.com`, because Next.js inlines them into the production frontend bundles at build time.
|
|
|
|
Example explicit values for a local registry exposed through Traefik:
|
|
|
|
```text
|
|
REGISTRY_HOST=registry.rentaldrivego.ma
|
|
REGISTRY_IMAGE=registry.rentaldrivego.ma/rentaldrivego/car_management_system
|
|
REGISTRY_USER=<registry-user>
|
|
REGISTRY_PASSWORD=<registry-password>
|
|
```
|
|
|
|
For the deploy job, add these GitLab CI variables as well:
|
|
|
|
```text
|
|
VPS_IP=<server-ip-or-hostname>
|
|
VPS_USER=<ssh-user>
|
|
SSH_PRIVATE_KEY=<deployment-private-key>
|
|
```
|
|
|
|
`SSH_PRIVATE_KEY` must be an unencrypted private key that OpenSSH can read in a non-interactive job. The pipeline accepts any of these formats:
|
|
|
|
- GitLab `File` variable containing the private key
|
|
- Standard multiline key pasted directly into the variable value
|
|
- Single-line key with literal `\n` newline escapes
|
|
- Base64-encoded private key stored as a single line
|
|
|
|
If your key is passphrase-protected, generate a dedicated deploy key without a passphrase for CI instead of reusing an interactive workstation key.
|
|
|
|
The production compose file reads `APP_IMAGE` and `APP_VERSION` for pull-based deploys. The GitLab deploy job injects those values automatically and now syncs the deployment assets to the VPS before running the server-side deploy script. Production no longer depends on `git pull` during release.
|
|
|
|
The CI pipeline publishes and deploys from the GitLab default branch (`$CI_DEFAULT_BRANCH`). If you change your release branch, update the repository default branch in GitLab instead of hard-coding branch names in `.gitlab-ci.yml`.
|
|
|
|
If you use `docker:dind` on a self-hosted GitLab runner, the runner's Docker executor must be started with `privileged = true`. Without that, `docker:dind` often logs AppArmor or `/sys/kernel/security` mount errors and can become unreliable even when the job container still starts.
|
|
|
|
#### 5. Bootstrap the server once
|
|
|
|
Traefik must be running before the app stack so it can wire up routes at startup. This bootstrap path is for the first server setup or for deliberate source-based rebuilds. Normal production releases should go through GitLab CI.
|
|
|
|
```bash
|
|
bash scripts/docker-prod-up-traefik.sh
|
|
```
|
|
|
|
If you intentionally want to build from source on the server:
|
|
|
|
```bash
|
|
npm run docker:prod:up
|
|
```
|
|
|
|
Or use the helper scripts if you want to start one production container at a time:
|
|
|
|
```bash
|
|
npm run docker:prod:start:traefik
|
|
npm run docker:prod:start:postgres
|
|
npm run docker:prod:start:redis
|
|
npm run docker:prod:start:api
|
|
npm run docker:prod:start:storefront
|
|
npm run docker:prod:start:dashboard
|
|
npm run docker:prod:start:admin
|
|
npm run docker:prod:start:frontends
|
|
npm run docker:prod:start:pgmanage
|
|
npm run docker:prod:start:portainer
|
|
npm run docker:prod:start:registry
|
|
npm run docker:prod:start:all
|
|
npm run docker:prod:start:api && npm run docker:prod:start:frontends
|
|
```
|
|
|
|
Docker will:
|
|
1. Build the monorepo image on the server
|
|
2. Start all app services (`api`, `storefront`, `dashboard`, `admin`, `pgmanage`)
|
|
|
|
Traefik automatically picks up the containers and provisions TLS certificates. Services are live at their `https://` URLs within ~30 seconds.
|
|
|
|
#### 6. Standard release flow
|
|
|
|
Normal production releases should use GitLab CI:
|
|
|
|
1. CI builds and pushes a single versioned image.
|
|
2. CI copies the current deployment assets (`docker-compose.production.yml`, Traefik config, deploy scripts, pgManage override) to the VPS.
|
|
3. CI runs `bash scripts/docker-prod-deploy.sh` on the VPS with `APP_IMAGE` and `APP_VERSION` pinned to the commit being released.
|
|
4. The deploy script pulls the release image, starts Postgres and Redis, runs `npm run db:deploy` as a one-shot migration job, then starts the API and frontends and waits for their health checks.
|
|
|
|
This avoids the old drift where the VPS checkout changed independently through `git pull`, or where API startup silently mixed migrations with application boot.
|
|
|
|
#### 6a. Deploy Portainer
|
|
|
|
Portainer is deployed separately from the main app stack and reuses the shared `traefik-proxy` network managed by Traefik.
|
|
|
|
```bash
|
|
npm run docker:prod:start:portainer
|
|
```
|
|
|
|
Equivalent raw Docker Compose command:
|
|
|
|
```bash
|
|
docker compose -p rentaldrivego-portainer-prod --env-file .env.docker.production -f docker-compose.portainer.production.yml up -d
|
|
```
|
|
|
|
#### 6b. Deploy the registry on a separate local server
|
|
|
|
For the split setup:
|
|
|
|
1. Run the registry on your local server with port `5000` exposed directly.
|
|
2. Set `REGISTRY_UPSTREAM_URL` on the VPS to `http://<local-registry-server-ip>:5000`.
|
|
3. Restart Traefik on the VPS so it renders the dynamic registry upstream file and serves TLS for `REGISTRY_DOMAIN`.
|
|
|
|
On the local registry server:
|
|
|
|
```bash
|
|
npm run docker:registry:local:start
|
|
```
|
|
|
|
Equivalent raw Docker Compose command:
|
|
|
|
```bash
|
|
docker compose -p rentaldrivego-registry-local --env-file .env.docker.production -f docker-compose.registry.local.yml up -d
|
|
```
|
|
|
|
On first start, the script generates `docker/registry/auth/htpasswd` from `REGISTRY_USER` and `REGISTRY_PASSWORD` in `.env.docker.production`.
|
|
|
|
From the VPS, verify the upstream directly before involving Traefik:
|
|
|
|
```bash
|
|
curl -I http://<local-registry-server-ip>:5000/v2/
|
|
```
|
|
|
|
Expected response:
|
|
|
|
```text
|
|
HTTP/1.1 401 Unauthorized
|
|
```
|
|
|
|
Then on the VPS restart Traefik:
|
|
|
|
```bash
|
|
bash scripts/docker-prod-up-traefik.sh
|
|
```
|
|
|
|
After that, verify the public route and login flow:
|
|
|
|
```bash
|
|
docker login registry.rentaldrivego.ma
|
|
docker pull registry:2
|
|
docker tag registry:2 registry.rentaldrivego.ma/smoke-test:latest
|
|
docker push registry.rentaldrivego.ma/smoke-test:latest
|
|
```
|
|
|
|
Uploaded assets handled by the API, including vehicle photos and company branding images, are persisted in the named Docker volume `api_uploads`, mounted inside the API container at `/var/lib/rentaldrivego/storage`. Rebuilding or redeploying the API no longer clears those files as long as that volume is kept.
|
|
|
|
The production helper scripts and the GitLab deploy job now explicitly create the Docker volume `${DOCKER_PROD_PROJECT_NAME:-rentaldrivego-prod}_api_uploads` before starting or redeploying the API stack, so a fresh server bootstrap does not accidentally start the API without its upload storage volume.
|
|
|
|
#### Updating after a code change
|
|
|
|
Push to the GitLab default branch and let the pipeline deploy the pinned image. That is the supported production release path.
|
|
|
|
If CI is unavailable and you need to redeploy the image already published to the registry from the server:
|
|
|
|
```bash
|
|
APP_IMAGE=registry.example.com/rentaldrivego/car_management_system \
|
|
APP_VERSION=<gitlab-commit-sha> \
|
|
REGISTRY_HOST=registry.example.com \
|
|
REGISTRY_USER=<registry-user> \
|
|
REGISTRY_PASSWORD=<registry-password> \
|
|
bash scripts/docker-prod-deploy.sh
|
|
```
|
|
|
|
Only use `npm run docker:prod:up` when you intentionally want a source build on the server.
|
|
|
|
#### Apply database migrations without downtime
|
|
|
|
```bash
|
|
docker compose -p rentaldrivego-prod --env-file .env.docker.production -f docker-compose.production.yml run --rm migrate
|
|
```
|
|
|
|
#### Create the first production admin
|
|
|
|
The repo includes a seed that creates the first `SUPER_ADMIN` if that email does not already exist.
|
|
|
|
```bash
|
|
docker compose -p rentaldrivego-prod --env-file .env.docker.production -f docker-compose.production.yml run --rm \
|
|
-e ADMIN_SEED_EMAIL=rentaldrivego@gmail.com \
|
|
-e ADMIN_SEED_PASSWORD='Qwerty00!@#$%' \
|
|
-e ADMIN_SEED_FIRST_NAME=Super \
|
|
-e ADMIN_SEED_LAST_NAME=Admin \
|
|
api npm run db:seed:admin
|
|
```
|
|
|
|
Then sign in at `https://rentaldrivego.ma/admin/login` and create any additional admin users from the admin panel.
|
|
|
|
#### View logs
|
|
|
|
```bash
|
|
# All services
|
|
npm run docker:prod:logs
|
|
|
|
# Single service
|
|
npm run docker:prod:logs:api
|
|
```
|
|
|
|
#### Backup production data
|
|
|
|
Create a timestamped backup directory under `./backups`:
|
|
|
|
```bash
|
|
npm run docker:prod:backup
|
|
```
|
|
|
|
Or choose a different parent directory:
|
|
|
|
```bash
|
|
bash scripts/docker-prod-backup.sh /srv/rentaldrivego-backups
|
|
```
|
|
|
|
Each backup contains:
|
|
|
|
- `postgres.dump` — logical PostgreSQL backup in custom format
|
|
- `api-uploads.tar.gz` — uploaded files from `/var/lib/rentaldrivego/storage`
|
|
- `traefik-letsencrypt.tar.gz` — Traefik ACME certificate state, when available
|
|
- `volumes/*.tar.gz` — raw Docker volume archives for the default production volumes
|
|
- `manifest.txt` — basic metadata
|
|
|
|
By default, the backup also archives these named production volumes when they exist:
|
|
|
|
- `${DOCKER_PROD_PROJECT_NAME:-rentaldrivego-prod}_api_uploads`
|
|
- `${DOCKER_PROD_PROJECT_NAME:-rentaldrivego-prod}_pgmanage_prod_data`
|
|
- `${DOCKER_PROD_PROJECT_NAME:-rentaldrivego-prod}_postgres_prod_data`
|
|
- `${DOCKER_PROD_PROJECT_NAME:-rentaldrivego-prod}_redis_prod_data`
|
|
|
|
To include extra named volumes from the same server, pass them as additional arguments:
|
|
|
|
```bash
|
|
bash scripts/docker-prod-backup.sh /srv/rentaldrivego-backups \
|
|
gitlab-l3gq_gitlab-config \
|
|
gitlab-l3gq_gitlab-data \
|
|
gitlab-l3gq_gitlab-logs \
|
|
pgmanage_data \
|
|
traefik-gcjk_portainer_data \
|
|
traefik-gcjk_traefik-letsencrypt
|
|
```
|
|
|
|
You can also provide extra volume names through `DOCKER_EXTRA_BACKUP_VOLUMES`.
|
|
|
|
#### Restore production data
|
|
|
|
Restore is destructive: it overwrites the production database, uploaded files, and, when present in the backup, Traefik ACME state.
|
|
|
|
```bash
|
|
bash scripts/docker-prod-restore.sh ./backups/rentaldrivego-prod-YYYYMMDDTHHMMSSZ --yes
|
|
```
|
|
|
|
The restore script:
|
|
|
|
1. Stops public app services
|
|
2. Restores the PostgreSQL dump
|
|
3. Replaces uploaded files
|
|
4. Restores Traefik ACME state if the archive exists
|
|
5. Restores raw volume archives from `volumes/` except the ones already covered by the database and upload restore steps
|
|
6. Starts Traefik and the production stack again
|
|
|
|
If the backup contains raw archives for volumes used by other stacks such as GitLab or Portainer, stop those containers before running restore. The script will refuse to overwrite a volume that is currently attached to a running container.
|
|
|
|
Before running restore on a live server, take a fresh backup first.
|
|
|
|
#### Stop the stack
|
|
|
|
```bash
|
|
# 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`
|
|
|
|
#### Portainer
|
|
|
|
Portainer is available at `https://portainer.rentaldrivego.ma`.
|
|
|
|
Use this command to deploy or update it:
|
|
|
|
```bash
|
|
npm run docker:prod:start:portainer
|
|
```
|
|
|
|
### 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:
|
|
|
|
```bash
|
|
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:
|
|
|
|
```bash
|
|
docker pull node:20-bookworm
|
|
docker compose -f docker-compose.dev.yml build --no-cache dashboard
|
|
```
|