add portainer

This commit is contained in:
root
2026-05-22 12:22:14 -04:00
parent 3e856e093d
commit fc4d099d4f
4 changed files with 51 additions and 0 deletions
+28
View File
@@ -6,6 +6,7 @@ Three Docker environments are available:
- `Dockerfile.test` with `docker-compose.test.yml` - `Dockerfile.test` with `docker-compose.test.yml`
- `Dockerfile.production` with `docker-compose.production.yml` - `Dockerfile.production` with `docker-compose.production.yml`
- `docker-compose.pgmanage.yml` for a standalone pgManage container - `docker-compose.pgmanage.yml` for a standalone pgManage container
- `docker-compose.portainer.production.yml` for a standalone production Portainer deployment behind Traefik
### Development ### Development
@@ -118,6 +119,7 @@ Add an A record for every subdomain to your server's public IP before deploying
| `rentaldrivego.ma` | marketplace and public site | | `rentaldrivego.ma` | marketplace and public site |
| `api.rentaldrivego.ma` | API | | `api.rentaldrivego.ma` | API |
| `pgmanage.rentaldrivego.ma` | pgManage (DB admin) | | `pgmanage.rentaldrivego.ma` | pgManage (DB admin) |
| `portainer.rentaldrivego.ma` | Portainer |
#### 2. Install Docker and clone the repo #### 2. Install Docker and clone the repo
@@ -155,6 +157,7 @@ Open `.env.docker.production` and fill in every value. The minimum required secr
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 `/`. 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`. 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`.
Set `PORTAINER_DOMAIN=portainer.rentaldrivego.ma` in `.env.docker.production` to expose Portainer through Traefik.
#### 4a. Configure the registry for CI deploys #### 4a. Configure the registry for CI deploys
@@ -202,6 +205,7 @@ npm run docker:prod:start:dashboard
npm run docker:prod:start:admin npm run docker:prod:start:admin
npm run docker:prod:start:frontends npm run docker:prod:start:frontends
npm run docker:prod:start:pgmanage npm run docker:prod:start:pgmanage
npm run docker:prod:start:portainer
npm run docker:prod:start:all npm run docker:prod:start:all
``` ```
@@ -211,6 +215,20 @@ Docker will:
Traefik automatically picks up the containers and provisions TLS certificates. Services are live at their `https://` URLs within ~30 seconds. Traefik automatically picks up the containers and provisions TLS certificates. Services are live at their `https://` URLs within ~30 seconds.
#### 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
```
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. 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.
#### Updating after a code change #### Updating after a code change
@@ -345,6 +363,16 @@ pgManage is available at `https://pgmanage.rentaldrivego.ma`. To connect to the
- **Username:** `postgres` - **Username:** `postgres`
- **Password:** value of `POSTGRES_PASSWORD` from `.env.docker.production` - **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 ### Notes
- The production image builds the whole monorepo once, then each service overrides its runtime command. - The production image builds the whole monorepo once, then each service overrides its runtime command.
+1
View File
@@ -21,6 +21,7 @@
"docker:prod:start:admin": "bash scripts/docker-prod-up-admin.sh", "docker:prod:start:admin": "bash scripts/docker-prod-up-admin.sh",
"docker:prod:start:frontends": "bash scripts/docker-prod-up-frontends.sh", "docker:prod:start:frontends": "bash scripts/docker-prod-up-frontends.sh",
"docker:prod:start:pgmanage": "bash scripts/docker-prod-up-pgmanage.sh", "docker:prod:start:pgmanage": "bash scripts/docker-prod-up-pgmanage.sh",
"docker:prod:start:portainer": "bash scripts/docker-prod-up-portainer.sh",
"docker:prod:up": "docker compose -p rentaldrivego-prod --env-file .env.docker.production -f docker-compose.production.yml up --build -d", "docker:prod:up": "docker compose -p rentaldrivego-prod --env-file .env.docker.production -f docker-compose.production.yml up --build -d",
"docker:prod:down": "docker compose -p rentaldrivego-prod --env-file .env.docker.production -f docker-compose.production.yml down", "docker:prod:down": "docker compose -p rentaldrivego-prod --env-file .env.docker.production -f docker-compose.production.yml down",
"docker:prod:backup": "bash scripts/docker-prod-backup.sh", "docker:prod:backup": "bash scripts/docker-prod-backup.sh",
+12
View File
@@ -4,9 +4,11 @@ set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
PROD_COMPOSE_FILE="${ROOT_DIR}/docker-compose.production.yml" PROD_COMPOSE_FILE="${ROOT_DIR}/docker-compose.production.yml"
PORTAINER_COMPOSE_FILE="${ROOT_DIR}/docker-compose.portainer.production.yml"
TRAEFIK_COMPOSE_FILE="${ROOT_DIR}/traefik.yaml" TRAEFIK_COMPOSE_FILE="${ROOT_DIR}/traefik.yaml"
ENV_FILE="${ROOT_DIR}/.env.docker.production" ENV_FILE="${ROOT_DIR}/.env.docker.production"
PROJECT_NAME="${DOCKER_PROD_PROJECT_NAME:-rentaldrivego-prod}" PROJECT_NAME="${DOCKER_PROD_PROJECT_NAME:-rentaldrivego-prod}"
PORTAINER_PROJECT_NAME="${DOCKER_PORTAINER_PROJECT_NAME:-rentaldrivego-portainer-prod}"
TRAEFIK_NETWORK="${DOCKER_PROD_TRAEFIK_NETWORK:-traefik-proxy}" TRAEFIK_NETWORK="${DOCKER_PROD_TRAEFIK_NETWORK:-traefik-proxy}"
VOLUME_BACKUP_IMAGE="${DOCKER_VOLUME_BACKUP_IMAGE:-postgres:16-alpine}" VOLUME_BACKUP_IMAGE="${DOCKER_VOLUME_BACKUP_IMAGE:-postgres:16-alpine}"
@@ -29,6 +31,10 @@ prod_compose() {
docker compose -p "${PROJECT_NAME}" --env-file "${ENV_FILE}" -f "${PROD_COMPOSE_FILE}" "$@" docker compose -p "${PROJECT_NAME}" --env-file "${ENV_FILE}" -f "${PROD_COMPOSE_FILE}" "$@"
} }
portainer_compose() {
docker compose -p "${PORTAINER_PROJECT_NAME}" --env-file "${ENV_FILE}" -f "${PORTAINER_COMPOSE_FILE}" "$@"
}
traefik_compose() { traefik_compose() {
docker compose --env-file "${ENV_FILE}" -f "${TRAEFIK_COMPOSE_FILE}" "$@" docker compose --env-file "${ENV_FILE}" -f "${TRAEFIK_COMPOSE_FILE}" "$@"
} }
@@ -38,6 +44,12 @@ start_prod_services() {
prod_compose up --build -d "$@" prod_compose up --build -d "$@"
} }
start_portainer() {
ensure_env_file
ensure_traefik_network
portainer_compose up -d
}
start_traefik() { start_traefik() {
ensure_env_file ensure_env_file
ensure_traefik_network ensure_traefik_network
+10
View File
@@ -0,0 +1,10 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
source "${ROOT_DIR}/scripts/docker-prod-common.sh"
start_portainer
echo "Portainer is starting."