From b81835661c27918ce71cf86b3dd0caadb632d25c Mon Sep 17 00:00:00 2001 From: Mathis HERRIOT <197931332+0x485254@users.noreply.github.com> Date: Wed, 14 Jan 2026 16:38:07 +0100 Subject: [PATCH] feat(docker): add production-ready docker-compose configuration with health checks Introduce a new `docker-compose.prod.yml` file tailored for production setups. Add health checks for PostgreSQL, Redis, and ClamAV services. Update existing `docker-compose.yml` with health checks, environment refinements, service dependencies, and production-specific optimizations. --- docker-compose.prod.yml | 143 ++++++++++++++++++++++++++++++++++++++++ docker-compose.yml | 59 ++++++++++++----- 2 files changed, 184 insertions(+), 18 deletions(-) create mode 100644 docker-compose.prod.yml diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml new file mode 100644 index 0000000..c638d60 --- /dev/null +++ b/docker-compose.prod.yml @@ -0,0 +1,143 @@ +services: + db: + image: postgres:17-alpine + container_name: memegoat-db + restart: always + environment: + POSTGRES_USER: ${POSTGRES_USER:-app} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-app} + POSTGRES_DB: ${POSTGRES_DB:-app} + networks: + - nw_memegoat + volumes: + - postgres_data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"] + interval: 10s + timeout: 5s + retries: 5 + + redis: + image: redis:7-alpine + container_name: memegoat-redis + restart: always + networks: + - nw_memegoat + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 10s + timeout: 5s + retries: 5 + + s3: + image: minio/minio:RELEASE.2025-04-08T15-41-24Z + container_name: memegoat-s3 + restart: always + networks: + - nw_memegoat + #ports: + # - "9000:9000" + # - "9001:9001" + environment: + MINIO_ROOT_USER: ${S3_ACCESS_KEY:-minioadmin} + MINIO_ROOT_PASSWORD: ${S3_SECRET_KEY:-minioadmin} + command: server /data --console-address ":9001" + volumes: + - minio_data:/data + + #mail: + # image: axllent/mailpit + # container_name: memegoat-mail + # restart: always + # ports: + # - "1025:1025" # smtp + # - "8025:8025" # web ui + + backend: + build: + context: . + dockerfile: backend/Dockerfile + target: runtime + container_name: memegoat-backend + networks: + - nw_memegoat + - nw_caddy + command: > + node dist/src/main + depends_on: + db: + condition: service_healthy + redis: + condition: service_healthy + s3: + condition: service_started + clamav: + condition: service_started + ports: + - "3000:3000" + environment: + NODE_ENV: production + POSTGRES_HOST: memegoat-db + POSTGRES_PORT: 5432 + POSTGRES_DB: ${POSTGRES_DB:-app} + POSTGRES_USER: ${POSTGRES_USER:-app} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-app} + REDIS_HOST: memegoat-redis + REDIS_PORT: 6379 + S3_ENDPOINT: memegoat-s3 + S3_PORT: 9000 + S3_ACCESS_KEY: ${S3_ACCESS_KEY:-minioadmin} + S3_SECRET_KEY: ${S3_SECRET_KEY:-minioadmin} + S3_BUCKET_NAME: ${S3_BUCKET_NAME:-memegoat} + MAIL_HOST: ${MAIL_HOST:-smtp.mail.ovh.net} + MAIL_PORT: 465 + MAIL_USER: ${MAIL_USER} + MAIL_PASS: ${MAIL_PASS} + MAIL_FROM: ${MAIL_FROM:-noreply@memegoat.fr} + DOMAIN_NAME: ${DOMAIN_NAME:-localhost} + JWT_SECRET: ${JWT_SECRET:-super-secret-jwt-key-change-me-in-prod} + ENCRYPTION_KEY: ${ENCRYPTION_KEY:-01234567890123456789012345678901} + PGP_ENCRYPTION_KEY: ${PGP_ENCRYPTION_KEY:-super-secret-pgp-key} + SESSION_PASSWORD: ${SESSION_PASSWORD:-super-secret-session-password-32-chars} + CORS_DOMAIN_NAME: ${CORS_DOMAIN_NAME:-*} + ENABLE_CORS: ${ENABLE_CORS:-true} + CLAMAV_HOST: memegoat-clamav + CLAMAV_PORT: 3310 + MAX_IMAGE_SIZE_KB: 512 + MAX_GIF_SIZE_KB: 1024 + + clamav: + image: clamav/clamav:latest + container_name: memegoat-clamav + restart: always + networks: + - nw_memegoat + healthcheck: + test: ["CMD", "clamdscan", "--version"] + interval: 20s + timeout: 10s + retries: 5 + + frontend: + build: + context: . + dockerfile: frontend/Dockerfile + target: runner + container_name: memegoat-frontend + networks: + - nw_caddy + restart: always + environment: + NODE_ENV: production + NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL:-http://localhost:3000} + depends_on: + - backend + +volumes: + postgres_data: + minio_data: +networks: + nw_memegoat: + internal: true + nw_caddy: + external: true diff --git a/docker-compose.yml b/docker-compose.yml index 3a06fbd..2e83901 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,6 +11,11 @@ services: - "5432:5432" volumes: - postgres_data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"] + interval: 10s + timeout: 5s + retries: 5 redis: image: redis:7-alpine @@ -18,6 +23,11 @@ services: restart: always ports: - "6379:6379" + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 10s + timeout: 5s + retries: 5 s3: image: minio/minio:RELEASE.2025-04-08T15-41-24Z @@ -45,17 +55,23 @@ services: build: context: . dockerfile: backend/Dockerfile - target: base + target: runtime container_name: memegoat-backend - command: pnpm run --filter @memegoat/backend start:dev - volumes: - - .:/usr/src/app - - /usr/src/app/node_modules - - /usr/src/app/backend/node_modules + command: > + node dist/src/main + depends_on: + db: + condition: service_healthy + redis: + condition: service_healthy + s3: + condition: service_started + clamav: + condition: service_started ports: - "3000:3000" environment: - NODE_ENV: development + NODE_ENV: production POSTGRES_HOST: db POSTGRES_PORT: 5432 POSTGRES_DB: ${POSTGRES_DB:-app} @@ -78,26 +94,33 @@ services: ENCRYPTION_KEY: ${ENCRYPTION_KEY:-01234567890123456789012345678901} PGP_ENCRYPTION_KEY: ${PGP_ENCRYPTION_KEY:-super-secret-pgp-key} SESSION_PASSWORD: ${SESSION_PASSWORD:-super-secret-session-password-32-chars} - depends_on: - - db - - redis - - s3 + CORS_DOMAIN_NAME: ${CORS_DOMAIN_NAME:-*} + ENABLE_CORS: ${ENABLE_CORS:-true} + CLAMAV_HOST: clamav + CLAMAV_PORT: 3310 + + clamav: + image: clamav/clamav:1.4 + container_name: memegoat-clamav + restart: always + healthcheck: + test: ["CMD", "clamdscan", "--version"] + interval: 20s + timeout: 10s + retries: 5 frontend: build: context: . dockerfile: frontend/Dockerfile - target: base + target: runner container_name: memegoat-frontend - command: pnpm run --filter @memegoat/frontend dev - volumes: - - .:/usr/src/app - - /usr/src/app/node_modules - - /usr/src/app/frontend/node_modules + restart: always ports: - "3001:3000" environment: - NEXT_PUBLIC_API_URL: http://localhost:3000 + NODE_ENV: production + NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL:-http://localhost:3000} depends_on: - backend