name: c-hr # Full stack — infra (services/*) + apps (apps/*). Used for prod-like # verification: `./scripts/dev.sh start`. For day-to-day dev, use # docker-compose.dev.yml (infra only) and run BE/FE natively via # `pnpm dev` for fast file watching + easy debugging. include: - ./services/postgres/docker-compose.yml - ./services/redis/docker-compose.yml - ./services/minio/docker-compose.yml services: backend: image: "${REGISTRY_IMAGE:-c-hr}/backend:${IMAGE_TAG:-latest}" build: context: ./apps/backend dockerfile: Dockerfile container_name: c-hr-backend restart: unless-stopped ports: - "127.0.0.1:${BACKEND_PORT:-8000}:8000" depends_on: postgres: condition: service_healthy redis: condition: service_healthy labels: - "traefik.enable=true" - "traefik.http.routers.c-hr-api.rule=Host(`${API_HOST:-hrm.cmcai.vn}`) && PathPrefix(`/api`)" - "traefik.http.routers.c-hr-api.priority=100" - "traefik.http.services.c-hr-api.loadbalancer.server.port=8000" environment: NODE_ENV: production PORT: 8000 API_PREFIX: ${API_PREFIX:-api/v1} API_BASE_URL: ${API_BASE_URL:-http://hrm.cmcai.vn} # Database — override @postgres container hostname DATABASE_URL: postgresql://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:-postgres}@postgres:5432/${POSTGRES_DB:-c_hr} # Redis — override @redis container hostname REDIS_HOST: redis REDIS_PORT: 6379 REDIS_PASSWORD: ${REDIS_PASSWORD:-} # JWT JWT_ACCESS_SECRET: ${JWT_ACCESS_SECRET:-change-me-access-secret} JWT_REFRESH_SECRET: ${JWT_REFRESH_SECRET:-change-me-refresh-secret} JWT_ACCESS_EXPIRATION: ${JWT_ACCESS_EXPIRATION:-15m} JWT_REFRESH_EXPIRATION: ${JWT_REFRESH_EXPIRATION:-7d} # CORS & Cookies CORS_ORIGIN: ${FRONTEND_URL:-http://hrm.cmcai.vn} COOKIE_DOMAIN: ${COOKIE_DOMAIN:-} COOKIE_SECURE: ${COOKIE_SECURE:-false} COOKIE_SAMESITE: ${COOKIE_SAMESITE:-lax} AUTH_ACCESS_COOKIE_NAME: ${AUTH_ACCESS_COOKIE_NAME:-access_token} AUTH_REFRESH_COOKIE_NAME: ${AUTH_REFRESH_COOKIE_NAME:-refresh_token} # Storage STORAGE_TYPE: ${STORAGE_TYPE:-s3} AWS_S3_ENDPOINT: ${AWS_S3_ENDPOINT:-http://minio:9000} AWS_S3_REGION: ${AWS_S3_REGION:-us-east-1} AWS_S3_BUCKET: ${AWS_S3_BUCKET:-} AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID:-} AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY:-} # Mail MAIL_HOST: ${MAIL_HOST:-localhost} MAIL_PORT: ${MAIL_PORT:-1025} MAIL_USER: ${MAIL_USER:-} MAIL_PASSWORD: ${MAIL_PASSWORD:-} MAIL_FROM: ${MAIL_FROM:-noreply@example.com} MAIL_SECURE: ${MAIL_SECURE:-false} # SSO (Microsoft Entra) FRONTEND_URL: ${FRONTEND_URL:-http://hrm.cmcai.vn} MS_SSO_TENANT_ID: ${MS_SSO_TENANT_ID:-common} MS_SSO_CLIENT_ID: ${MS_SSO_CLIENT_ID:-} MS_SSO_CLIENT_SECRET: ${MS_SSO_CLIENT_SECRET:-} # Active Directory / LDAP LDAP_URL: ${LDAP_URL:-} LDAP_BIND_DN: ${LDAP_BIND_DN:-} LDAP_BIND_PASSWORD: ${LDAP_BIND_PASSWORD:-} LDAP_BASE_DN: ${LDAP_BASE_DN:-} LDAP_DEFAULT_ORGANIZATION_ID: ${LDAP_DEFAULT_ORGANIZATION_ID:-} LDAP_USER_DOMAIN: ${LDAP_USER_DOMAIN:-} LDAP_USER_FILTER: ${LDAP_USER_FILTER:-} LDAP_START_TLS: ${LDAP_START_TLS:-false} LDAP_CA_FILE: ${LDAP_CA_FILE:-} LDAP_TLS_REJECT_UNAUTHORIZED: ${LDAP_TLS_REJECT_UNAUTHORIZED:-true} LDAP_TIMEOUT_MS: ${LDAP_TIMEOUT_MS:-5000} # Recruitment RECRUITMENT_CREDENTIALS_KEY: ${RECRUITMENT_CREDENTIALS_KEY:-change-me-to-a-long-random-string} TALENT_VN_BASE_URL: ${TALENT_VN_BASE_URL:-https://api.talent.rework.vn} TOPCV_BASE_URL: ${TOPCV_BASE_URL:-https://api.topcv.vn} networks: - c-hr - traefik-network frontend: image: "${REGISTRY_IMAGE:-c-hr}/frontend:${IMAGE_TAG:-latest}" build: context: ./apps/frontend dockerfile: Dockerfile container_name: c-hr-frontend restart: unless-stopped depends_on: backend: condition: service_started labels: - "traefik.enable=true" - "traefik.http.routers.c-hr-web.rule=Host(`${FRONTEND_HOST:-hrm.cmcai.vn}`)" - "traefik.http.routers.c-hr-web.priority=10" - "traefik.http.services.c-hr-web.loadbalancer.server.port=3000" environment: NODE_ENV: production PORT: 3000 # next-runtime-env reads these at request time — no rebuild needed. NEXT_PUBLIC_API_URL: ${API_BASE_URL:-http://hrm.cmcai.vn}/${API_PREFIX:-api/v1} NEXT_PUBLIC_SITE_URL: ${FRONTEND_URL:-http://hrm.cmcai.vn} networks: - c-hr - traefik-network networks: c-hr: name: c-hr driver: bridge traefik-network: external: true