Nginx resolves upstream hostnames at boot time; if estore isn't registered in Docker DNS yet it crashes in a restart loop. Using service_healthy lets nginx wait until the Next.js app passes its healthcheck before nginx attempts to start. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
120 lines
4.4 KiB
YAML
120 lines
4.4 KiB
YAML
services:
|
|
|
|
# ── Nginx reverse proxy ───────────────────────────────────────────────────────
|
|
nginx:
|
|
image: nginx:alpine
|
|
container_name: bpb-nginx
|
|
ports:
|
|
- "80:80"
|
|
volumes:
|
|
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
|
|
depends_on:
|
|
main-site:
|
|
condition: service_started
|
|
estore:
|
|
condition: service_healthy
|
|
restart: always
|
|
|
|
# ── Main website ─────────────────────────────────────────────────────────────
|
|
main-site:
|
|
build: ./main-site
|
|
container_name: bpb-main
|
|
expose:
|
|
- "3050"
|
|
environment:
|
|
NODE_ENV: production
|
|
ADMIN_PASSWORD: ${MAIN_ADMIN_PASSWORD}
|
|
volumes:
|
|
- ./main-site/update.json:/usr/src/app/update.json
|
|
restart: always
|
|
depends_on:
|
|
- gallery-backend
|
|
|
|
# ── Photo gallery backend ─────────────────────────────────────────────────────
|
|
gallery-backend:
|
|
build: ./main-site/photo-gallery-app/backend
|
|
container_name: bpb-gallery
|
|
ports:
|
|
- "5002:5000"
|
|
environment:
|
|
MONGO_URI: mongodb://mongodb:27017/photogallery
|
|
WATERMARK_URL: http://watermarker:8000/watermark
|
|
ADMIN_PASSWORD: ${MAIN_ADMIN_PASSWORD}
|
|
volumes:
|
|
- ./main-site/photo-gallery-app/backend/uploads:/usr/src/app/uploads
|
|
depends_on:
|
|
- mongodb
|
|
- watermarker
|
|
restart: always
|
|
|
|
# ── Watermarker ───────────────────────────────────────────────────────────────
|
|
watermarker:
|
|
build: ./main-site/photo-gallery-app/watermarker
|
|
container_name: bpb-watermarker
|
|
restart: always
|
|
|
|
# ── MongoDB ───────────────────────────────────────────────────────────────────
|
|
mongodb:
|
|
image: mongo:latest
|
|
container_name: bpb-mongodb
|
|
volumes:
|
|
- ./mongodb_data:/data/db
|
|
restart: always
|
|
|
|
# ── eStore (Next.js / Square) ─────────────────────────────────────────────────
|
|
# NEXT_PUBLIC_* vars are baked into the JS bundle at build time.
|
|
# They are resolved from the root .env file (same dir as this compose file).
|
|
estore:
|
|
build:
|
|
context: ./estore
|
|
args:
|
|
NEXT_PUBLIC_SQUARE_APP_ID: ${NEXT_PUBLIC_SQUARE_APP_ID}
|
|
NEXT_PUBLIC_SQUARE_LOCATION_ID: ${NEXT_PUBLIC_SQUARE_LOCATION_ID}
|
|
NEXT_PUBLIC_SQUARE_ENVIRONMENT: ${NEXT_PUBLIC_SQUARE_ENVIRONMENT}
|
|
NEXT_PUBLIC_SITE_URL: ${NEXT_PUBLIC_SITE_URL}
|
|
container_name: bpb-estore
|
|
expose:
|
|
- "3000"
|
|
env_file: ./estore/.env
|
|
environment:
|
|
OSRM_URL: ${OSRM_URL} # injected from root .env; overrides estore/.env
|
|
volumes:
|
|
- ./estore/data:/app/data
|
|
restart: unless-stopped
|
|
depends_on:
|
|
- osrm
|
|
healthcheck:
|
|
test: ["CMD", "node", "-e", "fetch('http://localhost:3000/shop/api/catalog').then(r=>{if(!r.ok)process.exit(1)}).catch(()=>process.exit(1))"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
|
|
# ── OSRM download (runs once, exits) ─────────────────────────────────────────
|
|
# Downloads the PBF map file into the shared volume if not already present.
|
|
osrm-download:
|
|
build:
|
|
context: ./osrm
|
|
dockerfile: Dockerfile.download
|
|
container_name: bpb-osrm-download
|
|
volumes:
|
|
- ./osrm/data:/data
|
|
environment:
|
|
OSRM_REGION: connecticut-latest
|
|
restart: "no"
|
|
|
|
# ── OSRM (routing engine) ─────────────────────────────────────────────────────
|
|
osrm:
|
|
build: ./osrm
|
|
container_name: bpb-osrm
|
|
expose:
|
|
- "5000"
|
|
volumes:
|
|
- ./osrm/data:/data
|
|
environment:
|
|
OSRM_REGION: connecticut-latest
|
|
OSRM_PROFILE: /opt/car.lua
|
|
depends_on:
|
|
osrm-download:
|
|
condition: service_completed_successfully
|
|
restart: unless-stopped
|