From 683c8a49e2ccc84e795f29bc35795828679b0b8b Mon Sep 17 00:00:00 2001 From: benya Date: Sat, 7 Mar 2026 21:58:21 +0300 Subject: [PATCH] Parameterize docker-compose for server deployment Compose settings: - Reworked docker-compose.yml to use environment-variable driven configuration. - Added shared app env anchors for backend and worker to reduce duplication. - Made ports, credentials, security limits, SMTP, and storage options configurable. Production profile: - Added docker-compose.prod.yml override to close internal service ports. - Keeps external attack surface minimal for Linux server deployments. Docs and ops: - Added .env.docker.example with full variable set for server setup. - Updated README with quick-start and production launch commands. --- .env.docker.example | 57 ++++++++++++++++++ README.md | 10 +++- docker-compose.prod.yml | 15 +++++ docker-compose.yml | 125 ++++++++++++++++++---------------------- 4 files changed, 136 insertions(+), 71 deletions(-) create mode 100644 .env.docker.example create mode 100644 docker-compose.prod.yml diff --git a/.env.docker.example b/.env.docker.example new file mode 100644 index 0000000..7cfa9a0 --- /dev/null +++ b/.env.docker.example @@ -0,0 +1,57 @@ +# Core +APP_NAME=BenyaMessenger +ENVIRONMENT=production +DEBUG=false +API_V1_PREFIX=/api/v1 +AUTO_CREATE_TABLES=true +SECRET_KEY=replace-with-long-random-secret +JWT_ALGORITHM=HS256 +ACCESS_TOKEN_EXPIRE_MINUTES=30 +REFRESH_TOKEN_EXPIRE_DAYS=30 +EMAIL_VERIFICATION_TOKEN_EXPIRE_HOURS=24 +PASSWORD_RESET_TOKEN_EXPIRE_HOURS=1 + +# DB +POSTGRES_DB=messenger +POSTGRES_USER=postgres +POSTGRES_PASSWORD=postgres +POSTGRES_PORT=5432 + +# Redis +REDIS_PORT=6379 + +# MinIO +MINIO_ROOT_USER=minioadmin +MINIO_ROOT_PASSWORD=minioadmin +MINIO_API_PORT=9000 +MINIO_CONSOLE_PORT=9001 +S3_REGION=us-east-1 +S3_BUCKET_NAME=messenger-media +S3_PRESIGN_EXPIRE_SECONDS=900 +MAX_UPLOAD_SIZE_BYTES=104857600 + +# Public URLs +FRONTEND_BASE_URL=http://localhost +WEB_PORT=80 +BACKEND_PORT=8000 + +# Mail +SMTP_HOST=mailpit +SMTP_PORT=1025 +SMTP_USERNAME= +SMTP_PASSWORD= +SMTP_USE_TLS=false +SMTP_FROM_EMAIL=no-reply@benyamessenger.local +MAILPIT_SMTP_PORT=1025 +MAILPIT_UI_PORT=8025 + +# Security Limits +LOGIN_RATE_LIMIT_PER_MINUTE=10 +REGISTER_RATE_LIMIT_PER_MINUTE=5 +RESET_RATE_LIMIT_PER_MINUTE=5 +REFRESH_RATE_LIMIT_PER_MINUTE=30 +MESSAGE_RATE_LIMIT_PER_MINUTE=30 +DUPLICATE_MESSAGE_COOLDOWN_SECONDS=10 + +# Dev/Test utility +CELERY_TASK_ALWAYS_EAGER=false diff --git a/README.md b/README.md index c11e9aa..c3786d7 100644 --- a/README.md +++ b/README.md @@ -35,9 +35,17 @@ celery -A app.celery_app:celery_app worker --loglevel=info Run full stack (web + api + worker + postgres + redis + minio + mailpit): -1. docker compose up --build +1. cp .env.docker.example .env +2. edit `.env` (`SECRET_KEY`, passwords, domain) +3. docker compose up -d --build 2. Open: - Web: http://localhost - API docs: http://localhost:8000/docs - Mailpit UI: http://localhost:8025 - MinIO console: http://localhost:9001 + +### Production Mode + +Use production override to close internal ports (postgres/redis/minio/mailpit/backend): + +docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml new file mode 100644 index 0000000..46720ad --- /dev/null +++ b/docker-compose.prod.yml @@ -0,0 +1,15 @@ +services: + postgres: + ports: [] + + redis: + ports: [] + + minio: + ports: [] + + mailpit: + ports: [] + + backend: + ports: [] diff --git a/docker-compose.yml b/docker-compose.yml index 8b34598..4f8559d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,17 +1,53 @@ +x-app-env: &app-env + APP_NAME: ${APP_NAME:-BenyaMessenger} + ENVIRONMENT: ${ENVIRONMENT:-production} + DEBUG: ${DEBUG:-false} + API_V1_PREFIX: ${API_V1_PREFIX:-/api/v1} + AUTO_CREATE_TABLES: ${AUTO_CREATE_TABLES:-true} + SECRET_KEY: ${SECRET_KEY:-change-me-please-with-a-long-random-secret} + JWT_ALGORITHM: ${JWT_ALGORITHM:-HS256} + ACCESS_TOKEN_EXPIRE_MINUTES: ${ACCESS_TOKEN_EXPIRE_MINUTES:-30} + REFRESH_TOKEN_EXPIRE_DAYS: ${REFRESH_TOKEN_EXPIRE_DAYS:-30} + EMAIL_VERIFICATION_TOKEN_EXPIRE_HOURS: ${EMAIL_VERIFICATION_TOKEN_EXPIRE_HOURS:-24} + PASSWORD_RESET_TOKEN_EXPIRE_HOURS: ${PASSWORD_RESET_TOKEN_EXPIRE_HOURS:-1} + POSTGRES_DSN: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:-postgres}@postgres:5432/${POSTGRES_DB:-messenger} + REDIS_URL: redis://redis:6379/0 + S3_ENDPOINT_URL: http://minio:9000 + S3_ACCESS_KEY: ${MINIO_ROOT_USER:-minioadmin} + S3_SECRET_KEY: ${MINIO_ROOT_PASSWORD:-minioadmin} + S3_REGION: ${S3_REGION:-us-east-1} + S3_BUCKET_NAME: ${S3_BUCKET_NAME:-messenger-media} + S3_PRESIGN_EXPIRE_SECONDS: ${S3_PRESIGN_EXPIRE_SECONDS:-900} + MAX_UPLOAD_SIZE_BYTES: ${MAX_UPLOAD_SIZE_BYTES:-104857600} + FRONTEND_BASE_URL: ${FRONTEND_BASE_URL:-http://localhost} + SMTP_HOST: ${SMTP_HOST:-mailpit} + SMTP_PORT: ${SMTP_PORT:-1025} + SMTP_USERNAME: ${SMTP_USERNAME:-} + SMTP_PASSWORD: ${SMTP_PASSWORD:-} + SMTP_USE_TLS: ${SMTP_USE_TLS:-false} + SMTP_FROM_EMAIL: ${SMTP_FROM_EMAIL:-no-reply@benyamessenger.local} + LOGIN_RATE_LIMIT_PER_MINUTE: ${LOGIN_RATE_LIMIT_PER_MINUTE:-10} + REGISTER_RATE_LIMIT_PER_MINUTE: ${REGISTER_RATE_LIMIT_PER_MINUTE:-5} + RESET_RATE_LIMIT_PER_MINUTE: ${RESET_RATE_LIMIT_PER_MINUTE:-5} + REFRESH_RATE_LIMIT_PER_MINUTE: ${REFRESH_RATE_LIMIT_PER_MINUTE:-30} + MESSAGE_RATE_LIMIT_PER_MINUTE: ${MESSAGE_RATE_LIMIT_PER_MINUTE:-30} + DUPLICATE_MESSAGE_COOLDOWN_SECONDS: ${DUPLICATE_MESSAGE_COOLDOWN_SECONDS:-10} + CELERY_TASK_ALWAYS_EAGER: ${CELERY_TASK_ALWAYS_EAGER:-false} + services: postgres: image: postgres:16-alpine container_name: messenger-postgres environment: - POSTGRES_DB: messenger - POSTGRES_USER: postgres - POSTGRES_PASSWORD: postgres + POSTGRES_DB: ${POSTGRES_DB:-messenger} + POSTGRES_USER: ${POSTGRES_USER:-postgres} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres} ports: - - "5432:5432" + - "${POSTGRES_PORT:-5432}:5432" volumes: - pg_data:/var/lib/postgresql/data healthcheck: - test: ["CMD-SHELL", "pg_isready -U postgres -d messenger"] + test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-postgres} -d ${POSTGRES_DB:-messenger}"] interval: 5s timeout: 5s retries: 20 @@ -20,7 +56,7 @@ services: image: redis:7-alpine container_name: messenger-redis ports: - - "6379:6379" + - "${REDIS_PORT:-6379}:6379" volumes: - redis_data:/data healthcheck: @@ -34,11 +70,11 @@ services: container_name: messenger-minio command: server /data --console-address ":9001" environment: - MINIO_ROOT_USER: minioadmin - MINIO_ROOT_PASSWORD: minioadmin + MINIO_ROOT_USER: ${MINIO_ROOT_USER:-minioadmin} + MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:-minioadmin} ports: - - "9000:9000" - - "9001:9001" + - "${MINIO_API_PORT:-9000}:9000" + - "${MINIO_CONSOLE_PORT:-9001}:9001" volumes: - minio_data:/data @@ -48,8 +84,8 @@ services: - minio entrypoint: > /bin/sh -c " - mc alias set local http://minio:9000 minioadmin minioadmin && - mc mb --ignore-existing local/messenger-media + mc alias set local http://minio:9000 ${MINIO_ROOT_USER:-minioadmin} ${MINIO_ROOT_PASSWORD:-minioadmin} && + mc mb --ignore-existing local/${S3_BUCKET_NAME:-messenger-media} " restart: "no" @@ -66,35 +102,9 @@ services: minio-init: condition: service_completed_successfully environment: - APP_NAME: BenyaMessenger - ENVIRONMENT: production - DEBUG: "false" - API_V1_PREFIX: /api/v1 - AUTO_CREATE_TABLES: "true" - SECRET_KEY: "change-me-please-with-a-long-random-secret" - JWT_ALGORITHM: HS256 - ACCESS_TOKEN_EXPIRE_MINUTES: "30" - REFRESH_TOKEN_EXPIRE_DAYS: "30" - EMAIL_VERIFICATION_TOKEN_EXPIRE_HOURS: "24" - PASSWORD_RESET_TOKEN_EXPIRE_HOURS: "1" - POSTGRES_DSN: postgresql+asyncpg://postgres:postgres@postgres:5432/messenger - REDIS_URL: redis://redis:6379/0 - S3_ENDPOINT_URL: http://minio:9000 - S3_ACCESS_KEY: minioadmin - S3_SECRET_KEY: minioadmin - S3_REGION: us-east-1 - S3_BUCKET_NAME: messenger-media - S3_PRESIGN_EXPIRE_SECONDS: "900" - MAX_UPLOAD_SIZE_BYTES: "104857600" - FRONTEND_BASE_URL: http://localhost - SMTP_HOST: mailpit - SMTP_PORT: "1025" - SMTP_USERNAME: "" - SMTP_PASSWORD: "" - SMTP_USE_TLS: "false" - SMTP_FROM_EMAIL: no-reply@benyamessenger.local + <<: *app-env ports: - - "8000:8000" + - "${BACKEND_PORT:-8000}:8000" worker: build: @@ -108,40 +118,15 @@ services: backend: condition: service_started environment: - APP_NAME: BenyaMessenger - ENVIRONMENT: production - DEBUG: "false" - API_V1_PREFIX: /api/v1 - AUTO_CREATE_TABLES: "false" - SECRET_KEY: "change-me-please-with-a-long-random-secret" - JWT_ALGORITHM: HS256 - ACCESS_TOKEN_EXPIRE_MINUTES: "30" - REFRESH_TOKEN_EXPIRE_DAYS: "30" - EMAIL_VERIFICATION_TOKEN_EXPIRE_HOURS: "24" - PASSWORD_RESET_TOKEN_EXPIRE_HOURS: "1" - POSTGRES_DSN: postgresql+asyncpg://postgres:postgres@postgres:5432/messenger - REDIS_URL: redis://redis:6379/0 - S3_ENDPOINT_URL: http://minio:9000 - S3_ACCESS_KEY: minioadmin - S3_SECRET_KEY: minioadmin - S3_REGION: us-east-1 - S3_BUCKET_NAME: messenger-media - S3_PRESIGN_EXPIRE_SECONDS: "900" - MAX_UPLOAD_SIZE_BYTES: "104857600" - FRONTEND_BASE_URL: http://localhost - SMTP_HOST: mailpit - SMTP_PORT: "1025" - SMTP_USERNAME: "" - SMTP_PASSWORD: "" - SMTP_USE_TLS: "false" - SMTP_FROM_EMAIL: no-reply@benyamessenger.local + <<: *app-env + AUTO_CREATE_TABLES: false mailpit: image: axllent/mailpit:latest container_name: messenger-mailpit ports: - - "1025:1025" - - "8025:8025" + - "${MAILPIT_SMTP_PORT:-1025}:1025" + - "${MAILPIT_UI_PORT:-8025}:8025" web: build: @@ -151,7 +136,7 @@ services: depends_on: - backend ports: - - "80:80" + - "${WEB_PORT:-80}:80" volumes: pg_data: