Parameterize docker-compose for server deployment
All checks were successful
CI / test (push) Successful in 20s

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.
This commit is contained in:
2026-03-07 21:58:21 +03:00
parent 2501466c7a
commit 683c8a49e2
4 changed files with 136 additions and 71 deletions

57
.env.docker.example Normal file
View File

@@ -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

View File

@@ -35,9 +35,17 @@ celery -A app.celery_app:celery_app worker --loglevel=info
Run full stack (web + api + worker + postgres + redis + minio + mailpit): 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: 2. Open:
- Web: http://localhost - Web: http://localhost
- API docs: http://localhost:8000/docs - API docs: http://localhost:8000/docs
- Mailpit UI: http://localhost:8025 - Mailpit UI: http://localhost:8025
- MinIO console: http://localhost:9001 - 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

15
docker-compose.prod.yml Normal file
View File

@@ -0,0 +1,15 @@
services:
postgres:
ports: []
redis:
ports: []
minio:
ports: []
mailpit:
ports: []
backend:
ports: []

View File

@@ -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: services:
postgres: postgres:
image: postgres:16-alpine image: postgres:16-alpine
container_name: messenger-postgres container_name: messenger-postgres
environment: environment:
POSTGRES_DB: messenger POSTGRES_DB: ${POSTGRES_DB:-messenger}
POSTGRES_USER: postgres POSTGRES_USER: ${POSTGRES_USER:-postgres}
POSTGRES_PASSWORD: postgres POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres}
ports: ports:
- "5432:5432" - "${POSTGRES_PORT:-5432}:5432"
volumes: volumes:
- pg_data:/var/lib/postgresql/data - pg_data:/var/lib/postgresql/data
healthcheck: 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 interval: 5s
timeout: 5s timeout: 5s
retries: 20 retries: 20
@@ -20,7 +56,7 @@ services:
image: redis:7-alpine image: redis:7-alpine
container_name: messenger-redis container_name: messenger-redis
ports: ports:
- "6379:6379" - "${REDIS_PORT:-6379}:6379"
volumes: volumes:
- redis_data:/data - redis_data:/data
healthcheck: healthcheck:
@@ -34,11 +70,11 @@ services:
container_name: messenger-minio container_name: messenger-minio
command: server /data --console-address ":9001" command: server /data --console-address ":9001"
environment: environment:
MINIO_ROOT_USER: minioadmin MINIO_ROOT_USER: ${MINIO_ROOT_USER:-minioadmin}
MINIO_ROOT_PASSWORD: minioadmin MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:-minioadmin}
ports: ports:
- "9000:9000" - "${MINIO_API_PORT:-9000}:9000"
- "9001:9001" - "${MINIO_CONSOLE_PORT:-9001}:9001"
volumes: volumes:
- minio_data:/data - minio_data:/data
@@ -48,8 +84,8 @@ services:
- minio - minio
entrypoint: > entrypoint: >
/bin/sh -c " /bin/sh -c "
mc alias set local http://minio:9000 minioadmin minioadmin && mc alias set local http://minio:9000 ${MINIO_ROOT_USER:-minioadmin} ${MINIO_ROOT_PASSWORD:-minioadmin} &&
mc mb --ignore-existing local/messenger-media mc mb --ignore-existing local/${S3_BUCKET_NAME:-messenger-media}
" "
restart: "no" restart: "no"
@@ -66,35 +102,9 @@ services:
minio-init: minio-init:
condition: service_completed_successfully condition: service_completed_successfully
environment: environment:
APP_NAME: BenyaMessenger <<: *app-env
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
ports: ports:
- "8000:8000" - "${BACKEND_PORT:-8000}:8000"
worker: worker:
build: build:
@@ -108,40 +118,15 @@ services:
backend: backend:
condition: service_started condition: service_started
environment: environment:
APP_NAME: BenyaMessenger <<: *app-env
ENVIRONMENT: production AUTO_CREATE_TABLES: false
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
mailpit: mailpit:
image: axllent/mailpit:latest image: axllent/mailpit:latest
container_name: messenger-mailpit container_name: messenger-mailpit
ports: ports:
- "1025:1025" - "${MAILPIT_SMTP_PORT:-1025}:1025"
- "8025:8025" - "${MAILPIT_UI_PORT:-8025}:8025"
web: web:
build: build:
@@ -151,7 +136,7 @@ services:
depends_on: depends_on:
- backend - backend
ports: ports:
- "80:80" - "${WEB_PORT:-80}:80"
volumes: volumes:
pg_data: pg_data: