fix registry link
This commit is contained in:
@@ -5,6 +5,7 @@ PUBLIC_SITE_DOMAIN=example.com
|
||||
PGMANAGE_DOMAIN=pgmanage.example.com
|
||||
PORTAINER_DOMAIN=portainer.example.com
|
||||
REGISTRY_DOMAIN=registry.rentaldrivego.ma
|
||||
REGISTRY_UPSTREAM_URL=http://10.0.0.10:5000
|
||||
|
||||
# ── Optional prebuilt image source ────────────────────────────────────────────
|
||||
# Used for pull-based deployments. CI injects APP_IMAGE and APP_VERSION
|
||||
@@ -15,6 +16,7 @@ REGISTRY_HOST=registry.rentaldrivego.ma
|
||||
REGISTRY_USER=rentaldrivego_registry
|
||||
REGISTRY_PASSWORD=PMPS5k0D7rUeJOk0NkhI5bRtoGjkUqjK
|
||||
REGISTRY_IMAGE=registry.rentaldrivego.ma/rentaldrivego/car_management_system
|
||||
REGISTRY_HTTP_SECRET=PMPS5k0D7rUeJOk0NkhI5bRtoGjkUqjK
|
||||
|
||||
# ── Database ──────────────────────────────────────────────────────────────────
|
||||
# Full connection URL (used when DATABASE_URL_FROM_POSTGRES=false)
|
||||
|
||||
@@ -5,6 +5,7 @@ PUBLIC_SITE_DOMAIN=example.com
|
||||
PGMANAGE_DOMAIN=pgmanage.example.com
|
||||
PORTAINER_DOMAIN=portainer.example.com
|
||||
REGISTRY_DOMAIN=registry.example.com
|
||||
REGISTRY_UPSTREAM_URL=http://10.0.0.10:5000
|
||||
|
||||
# Database
|
||||
DATABASE_URL_FROM_POSTGRES=true
|
||||
|
||||
+3
-3
@@ -147,10 +147,10 @@ deploy_to_vps:
|
||||
echo "-- Syncing deployment assets --"
|
||||
ssh $VPS_USER@$VPS_IP "
|
||||
set -e
|
||||
mkdir -p '$DEPLOY_ROOT/scripts' '$DEPLOY_ROOT/docker/pgmanage' '$DEPLOY_ROOT/docker/registry/auth'
|
||||
mkdir -p '$DEPLOY_ROOT/scripts' '$DEPLOY_ROOT/docker/pgmanage' '$DEPLOY_ROOT/docker/registry/auth' '$DEPLOY_ROOT/dynamic'
|
||||
"
|
||||
scp docker-compose.production.yml docker-compose.portainer.production.yml docker-compose.registry.production.yml traefik.yaml $VPS_USER@$VPS_IP:$DEPLOY_ROOT/
|
||||
scp scripts/docker-prod-common.sh scripts/docker-prod-deploy.sh scripts/docker-prod-up-registry.sh $VPS_USER@$VPS_IP:$DEPLOY_ROOT/scripts/
|
||||
scp docker-compose.production.yml docker-compose.portainer.production.yml docker-compose.registry.production.yml docker-compose.registry.local.yml traefik.yaml $VPS_USER@$VPS_IP:$DEPLOY_ROOT/
|
||||
scp scripts/docker-prod-common.sh scripts/docker-prod-deploy.sh scripts/docker-prod-up-registry.sh scripts/docker-registry-local-up.sh $VPS_USER@$VPS_IP:$DEPLOY_ROOT/scripts/
|
||||
scp docker/pgmanage/override.py $VPS_USER@$VPS_IP:$DEPLOY_ROOT/docker/pgmanage/
|
||||
|
||||
echo "-- Running deploy script on VPS --"
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
name: rentaldrivego-registry-local
|
||||
|
||||
services:
|
||||
registry:
|
||||
image: registry:2
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- 5000:5000
|
||||
environment:
|
||||
REGISTRY_HTTP_ADDR: 0.0.0.0:5000
|
||||
REGISTRY_HTTP_RELATIVEURLS: "true"
|
||||
REGISTRY_HTTP_SECRET: ${REGISTRY_HTTP_SECRET:-change-me}
|
||||
REGISTRY_AUTH: htpasswd
|
||||
REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm
|
||||
REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd
|
||||
REGISTRY_STORAGE_DELETE_ENABLED: "true"
|
||||
volumes:
|
||||
- registry_local_data:/var/lib/registry
|
||||
- ./docker/registry/auth:/auth:ro
|
||||
|
||||
volumes:
|
||||
registry_local_data:
|
||||
+34
-6
@@ -8,6 +8,7 @@ Three Docker environments are available:
|
||||
- `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
|
||||
|
||||
@@ -165,7 +166,8 @@ Production now derives `DATABASE_URL` inside the app container from `POSTGRES_HO
|
||||
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.
|
||||
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 local Docker registry through Traefik.
|
||||
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`:
|
||||
|
||||
@@ -265,21 +267,47 @@ Equivalent raw Docker Compose command:
|
||||
docker compose -p rentaldrivego-portainer-prod --env-file .env.docker.production -f docker-compose.portainer.production.yml up -d
|
||||
```
|
||||
|
||||
#### 6b. Deploy the local registry
|
||||
#### 6b. Deploy the registry on a separate local server
|
||||
|
||||
The registry is deployed separately from the main app stack and reuses the shared `traefik-proxy` network managed by Traefik.
|
||||
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:prod:start:registry
|
||||
npm run docker:registry:local:start
|
||||
```
|
||||
|
||||
Equivalent raw Docker Compose command:
|
||||
|
||||
```bash
|
||||
docker compose -p rentaldrivego-registry-prod --env-file .env.docker.production -f docker-compose.registry.production.yml up -d
|
||||
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`. After the registry is up, verify it with:
|
||||
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
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
"docker:prod:start:pgmanage": "bash scripts/docker-prod-up-pgmanage.sh",
|
||||
"docker:prod:start:portainer": "bash scripts/docker-prod-up-portainer.sh",
|
||||
"docker:prod:start:registry": "bash scripts/docker-prod-up-registry.sh",
|
||||
"docker:registry:local:start": "bash scripts/docker-registry-local-up.sh",
|
||||
"docker:prod:deploy": "bash scripts/docker-prod-deploy.sh",
|
||||
"docker:prod:up": "bash scripts/docker-prod-up-all.sh",
|
||||
"docker:prod:down": "docker compose -p rentaldrivego-prod --env-file .env.docker.production -f docker-compose.production.yml down",
|
||||
|
||||
@@ -8,6 +8,8 @@ PORTAINER_COMPOSE_FILE="${ROOT_DIR}/docker-compose.portainer.production.yml"
|
||||
REGISTRY_COMPOSE_FILE="${ROOT_DIR}/docker-compose.registry.production.yml"
|
||||
TRAEFIK_COMPOSE_FILE="${ROOT_DIR}/traefik.yaml"
|
||||
ENV_FILE="${ROOT_DIR}/.env.docker.production"
|
||||
DYNAMIC_DIR="${ROOT_DIR}/dynamic"
|
||||
REGISTRY_DYNAMIC_FILE="${DYNAMIC_DIR}/registry-upstream.yml"
|
||||
PROJECT_NAME="${DOCKER_PROD_PROJECT_NAME:-rentaldrivego-prod}"
|
||||
PORTAINER_PROJECT_NAME="${DOCKER_PORTAINER_PROJECT_NAME:-rentaldrivego-portainer-prod}"
|
||||
REGISTRY_PROJECT_NAME="${DOCKER_REGISTRY_PROJECT_NAME:-rentaldrivego-registry-prod}"
|
||||
@@ -39,6 +41,10 @@ ensure_api_uploads_volume() {
|
||||
fi
|
||||
}
|
||||
|
||||
ensure_dynamic_dir() {
|
||||
mkdir -p "${DYNAMIC_DIR}"
|
||||
}
|
||||
|
||||
prod_compose() {
|
||||
docker compose -p "${PROJECT_NAME}" --env-file "${ENV_FILE}" -f "${PROD_COMPOSE_FILE}" "$@"
|
||||
}
|
||||
@@ -149,6 +155,38 @@ start_portainer() {
|
||||
portainer_compose up -d
|
||||
}
|
||||
|
||||
render_registry_proxy_config() {
|
||||
ensure_dynamic_dir
|
||||
|
||||
if [[ -z "${REGISTRY_DOMAIN:-}" && -z "${REGISTRY_UPSTREAM_URL:-}" ]]; then
|
||||
rm -f "${REGISTRY_DYNAMIC_FILE}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ -z "${REGISTRY_DOMAIN:-}" || -z "${REGISTRY_UPSTREAM_URL:-}" ]]; then
|
||||
echo "REGISTRY_DOMAIN and REGISTRY_UPSTREAM_URL must either both be set or both be unset." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cat > "${REGISTRY_DYNAMIC_FILE}" <<EOF
|
||||
http:
|
||||
routers:
|
||||
registry:
|
||||
rule: Host(\`${REGISTRY_DOMAIN}\`)
|
||||
entryPoints:
|
||||
- websecure
|
||||
tls:
|
||||
certResolver: letsencrypt
|
||||
service: registry-upstream
|
||||
|
||||
services:
|
||||
registry-upstream:
|
||||
loadBalancer:
|
||||
servers:
|
||||
- url: "${REGISTRY_UPSTREAM_URL}"
|
||||
EOF
|
||||
}
|
||||
|
||||
ensure_registry_auth_file() {
|
||||
mkdir -p "${REGISTRY_AUTH_DIR}"
|
||||
|
||||
@@ -176,6 +214,7 @@ start_registry() {
|
||||
start_traefik() {
|
||||
ensure_env_file
|
||||
ensure_traefik_network
|
||||
render_registry_proxy_config
|
||||
traefik_compose up -d
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
ENV_FILE="${ROOT_DIR}/.env.docker.production"
|
||||
COMPOSE_FILE="${ROOT_DIR}/docker-compose.registry.local.yml"
|
||||
AUTH_DIR="${ROOT_DIR}/docker/registry/auth"
|
||||
AUTH_FILE="${AUTH_DIR}/htpasswd"
|
||||
|
||||
if [[ ! -f "${ENV_FILE}" ]]; then
|
||||
echo "Missing ${ENV_FILE}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
set -a
|
||||
source "${ENV_FILE}"
|
||||
set +a
|
||||
|
||||
mkdir -p "${AUTH_DIR}"
|
||||
|
||||
if [[ -n "${REGISTRY_USER:-}" && -n "${REGISTRY_PASSWORD:-}" ]]; then
|
||||
docker run --rm --entrypoint htpasswd httpd:2-alpine -Bbn "${REGISTRY_USER}" "${REGISTRY_PASSWORD}" > "${AUTH_FILE}"
|
||||
chmod 600 "${AUTH_FILE}"
|
||||
elif [[ ! -f "${AUTH_FILE}" ]]; then
|
||||
echo "Set REGISTRY_USER and REGISTRY_PASSWORD in ${ENV_FILE} or create ${AUTH_FILE} manually." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
docker compose -p rentaldrivego-registry-local --env-file "${ENV_FILE}" -f "${COMPOSE_FILE}" up -d
|
||||
|
||||
echo "Local registry is starting on port 5000."
|
||||
Reference in New Issue
Block a user