Files
imen_pishghaman/docker-compose.yml
T
S. EsmaeiliandClaude Sonnet 5.5 3dc5f4ae91 fix(compose): give internal services unique network aliases
On a shared Docker network (Dokploy) plain service names like web or api
also resolve to other stacks' containers, so the gateway balanced requests
across foreign containers and returned 502. Services reached by name now
carry an imen-* alias, used by the gateway upstreams and the service URLs.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 08:28:04 +03:30

162 lines
4.7 KiB
YAML

# Production stack. The images only copy pre-built output (`pnpm build`, committed), nothing is
# installed or compiled on the server. Copy .env.example to .env, fill in the secrets, then:
# docker compose up -d --build
# docker compose exec api node dist/seed/seed.js # first run only: initial content + admin user
#
# gateway (nginx) ─┬─ site domain → web (Nuxt SSR) /api → api /media → minio
# └─ admin domain → admin (static) /api → api /media → minio
# services that other containers reach by name get an imen-* alias: on a shared network (Dokploy) plain
# names like web or api would also resolve to other stacks' containers
#
# fixed project name, so this stack never shares containers or volumes with docker-compose.dev.yml
name: imen
services:
postgres:
image: docker.arvancloud.ir/postgres:18-alpine
restart: unless-stopped
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
volumes:
- pgdata:/var/lib/postgresql
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 10s
timeout: 5s
retries: 10
minio:
image: docker.arvancloud.ir/minio/minio:latest
networks:
default:
aliases: [imen-minio]
restart: unless-stopped
command: server /data
environment:
MINIO_ROOT_USER: ${S3_ACCESS_KEY}
MINIO_ROOT_PASSWORD: ${S3_SECRET_KEY}
volumes:
- miniodata:/data
# runs pending database migrations, then exits; api starts after it succeeds
migrate:
image: imen-migrate
build:
context: .
dockerfile: docker/api.Dockerfile
target: migrate
restart: "no"
depends_on:
postgres:
condition: service_healthy
environment:
DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}
api:
image: imen-api
networks:
default:
aliases: [imen-api]
build:
context: .
dockerfile: docker/api.Dockerfile
target: runtime
restart: unless-stopped
depends_on:
migrate:
condition: service_completed_successfully
minio:
condition: service_started
environment:
NODE_ENV: production
DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}
JWT_SECRET: ${JWT_SECRET}
COOKIE_SECURE: ${COOKIE_SECURE:-true}
TRUST_PROXY: ${TRUST_PROXY:-2}
S3_ENDPOINT: http://imen-minio:9000
S3_BUCKET: ${S3_BUCKET:-imen-media}
S3_ACCESS_KEY: ${S3_ACCESS_KEY}
S3_SECRET_KEY: ${S3_SECRET_KEY}
S3_FORCE_PATH_STYLE: "true"
S3_ENSURE_BUCKET: "true"
MEDIA_PUBLIC_URL: /media
WEB_REVALIDATE_URL: http://imen-web:3000/_internal/revalidate
REVALIDATE_SECRET: ${REVALIDATE_SECRET}
ADMIN_PHONE: ${ADMIN_PHONE}
ADMIN_PASSWORD: ${ADMIN_PASSWORD}
ADMIN_NAME: ${ADMIN_NAME:-مدیر سایت}
web:
image: imen-web
networks:
default:
aliases: [imen-web]
build:
context: .
dockerfile: docker/web.Dockerfile
restart: unless-stopped
depends_on:
- api
environment:
NUXT_API_INTERNAL_URL: http://imen-api:4000/api
NUXT_REVALIDATE_SECRET: ${REVALIDATE_SECRET}
NUXT_PUBLIC_SITE_URL: https://${SITE_DOMAIN}
admin:
image: imen-admin
networks:
default:
aliases: [imen-admin]
build:
context: .
dockerfile: docker/admin.Dockerfile
restart: unless-stopped
gateway:
image: docker.arvancloud.ir/nginx:alpine
restart: unless-stopped
depends_on:
- web
- api
- admin
- minio
environment:
SITE_DOMAIN: ${SITE_DOMAIN}
ADMIN_DOMAIN: ${ADMIN_DOMAIN}
S3_BUCKET: ${S3_BUCKET:-imen-media}
volumes:
# rendered to /etc/nginx/conf.d/default.conf (replaces the stock server block)
- ./docker/nginx/gateway.conf.template:/etc/nginx/templates/default.conf.template:ro
ports:
- "${HTTP_PORT:-8080}:80"
# daily database dump into ./backups (kept 14 days)
backup:
image: docker.arvancloud.ir/postgres:18-alpine
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
environment:
PGHOST: postgres
PGUSER: ${POSTGRES_USER}
PGPASSWORD: ${POSTGRES_PASSWORD}
PGDATABASE: ${POSTGRES_DB}
volumes:
- ./backups:/backups
entrypoint:
- /bin/sh
- -c
- |
while true; do
pg_dump -Fc -f /backups/imen-$$(date +%F).dump && find /backups -name '*.dump' -mtime +14 -delete
sleep 86400
done
volumes:
pgdata:
miniodata: