add portainer
This commit is contained in:
@@ -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.
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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."
|
||||||
Reference in New Issue
Block a user