fix: DockerSecretsResolver - don't normalize absolute paths like /var/www/html/...
Some checks failed
Deploy Application / deploy (push) Has been cancelled
Some checks failed
Deploy Application / deploy (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
# PostgreSQL Production Connection Override
|
||||
#
|
||||
# This file provides network configuration for connecting to the PostgreSQL Production Stack.
|
||||
# Used by Production Stack.
|
||||
#
|
||||
# Usage:
|
||||
# Production Stack:
|
||||
# docker compose -f docker-compose.base.yml \
|
||||
# -f docker-compose.production.yml \
|
||||
# -f docker-compose.postgres-override.yml up
|
||||
#
|
||||
# Prerequisites:
|
||||
# - PostgreSQL Production Stack must be running (creates postgres-production-internal network)
|
||||
# - postgres-production-internal network must exist as external network
|
||||
# - PostgreSQL Production Stack: deployment/stacks/postgresql-production/docker-compose.yml
|
||||
|
||||
services:
|
||||
# Production Stack Services
|
||||
# These services will be merged with existing definitions from base.yml + production.yml
|
||||
php:
|
||||
networks:
|
||||
postgres-production-internal: {} # Add postgres-production-internal network for PostgreSQL access (merged with existing networks)
|
||||
queue-worker:
|
||||
networks:
|
||||
postgres-production-internal: {} # Add postgres-production-internal network for PostgreSQL access (merged with existing networks)
|
||||
scheduler:
|
||||
networks:
|
||||
postgres-production-internal: {} # Add postgres-production-internal network for PostgreSQL access
|
||||
|
||||
networks:
|
||||
postgres-production-internal:
|
||||
external: true
|
||||
name: postgres-production-internal
|
||||
app-internal:
|
||||
external: true
|
||||
name: app-internal
|
||||
@@ -0,0 +1,184 @@
|
||||
# Production Base Docker Compose Configuration
|
||||
# This file is identical to docker-compose.base.yml but WITHOUT build sections
|
||||
# Use with docker-compose.production.yml for production deployments
|
||||
#
|
||||
# Usage:
|
||||
# Production: docker-compose -f docker-compose.production-base.yml -f docker-compose.production.yml up
|
||||
|
||||
services:
|
||||
web:
|
||||
# Build section removed for production - use pre-built images from registry
|
||||
healthcheck:
|
||||
test: ["CMD", "nc", "-z", "127.0.0.1", "443"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
depends_on:
|
||||
php:
|
||||
condition: service_started
|
||||
networks:
|
||||
- frontend
|
||||
- backend
|
||||
|
||||
php:
|
||||
# Build section removed for production - use pre-built images from registry
|
||||
healthcheck:
|
||||
test: [ "CMD", "php", "-v" ]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
networks:
|
||||
- backend
|
||||
- cache
|
||||
volumes:
|
||||
# Shared Volume für Composer-Cache über Container-Neustarts hinweg
|
||||
- composer-cache:/root/.composer/cache
|
||||
# Persistent volumes for queue and logs
|
||||
- storage-queue:/var/www/html/storage/queue:rw
|
||||
- var-data:/var/www/html/var/logs:rw
|
||||
tmpfs:
|
||||
# tmpfs for cache and runtime directories (RAM-based, faster I/O)
|
||||
- /var/www/html/storage/cache
|
||||
- /var/www/html/storage/discovery
|
||||
- /var/www/html/var/cache
|
||||
- /tmp
|
||||
|
||||
php-test:
|
||||
# Build section removed for production - use pre-built images from registry
|
||||
user: "1000:1000"
|
||||
profiles:
|
||||
- test
|
||||
volumes:
|
||||
- composer-cache:/home/appuser/.composer/cache
|
||||
# Persistent volumes for queue and logs
|
||||
- storage-queue:/var/www/html/storage/queue:rw
|
||||
- var-data:/var/www/html/var/logs:rw
|
||||
tmpfs:
|
||||
# tmpfs for cache and runtime directories (RAM-based, faster I/O)
|
||||
- /var/www/html/storage/cache
|
||||
- /var/www/html/storage/discovery
|
||||
- /var/www/html/var/cache
|
||||
- /tmp
|
||||
environment:
|
||||
APP_ENV: testing
|
||||
APP_DEBUG: true
|
||||
DB_HOST: postgres # External PostgreSQL Stack service
|
||||
REDIS_HOST: redis
|
||||
networks:
|
||||
- backend
|
||||
- cache
|
||||
entrypoint: []
|
||||
command: ["php", "-v"]
|
||||
|
||||
# Database service removed - all environments use external PostgreSQL Stack
|
||||
# Local: deployment/stacks/postgresql/
|
||||
# Staging: deployment/stacks/postgresql/
|
||||
# Production: deployment/stacks/postgresql/
|
||||
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
volumes:
|
||||
- "${REDIS_CONFIG_PATH:-./docker/redis/redis.conf}:/usr/local/etc/redis/redis.conf:ro"
|
||||
- redis_data:/data
|
||||
command: ["redis-server", "/usr/local/etc/redis/redis.conf"]
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
networks:
|
||||
- cache
|
||||
|
||||
queue-worker:
|
||||
# Build section removed for production - use pre-built images from registry
|
||||
entrypoint: "" # Override any entrypoint
|
||||
command: ["php", "/var/www/html/worker.php"] # Direct command execution
|
||||
depends_on:
|
||||
php:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
# Note: PostgreSQL is external service, connection via app-internal network
|
||||
volumes:
|
||||
# Use same storage volumes as PHP container for consistency
|
||||
# Persistent volumes for queue and logs
|
||||
- storage-queue:/var/www/html/storage/queue:rw
|
||||
- var-data:/var/www/html/var/logs:rw
|
||||
tmpfs:
|
||||
# tmpfs for cache and runtime directories (RAM-based, faster I/O)
|
||||
- /var/www/html/storage/cache
|
||||
- /var/www/html/storage/discovery
|
||||
- /var/www/html/var/cache
|
||||
- /tmp
|
||||
networks:
|
||||
- backend
|
||||
- cache
|
||||
# Graceful shutdown timeout
|
||||
stop_grace_period: 30s
|
||||
|
||||
minio:
|
||||
image: minio/minio:latest
|
||||
environment:
|
||||
- TZ=Europe/Berlin
|
||||
# SECURITY: MINIO credentials must be set explicitly (no hardcoded fallback)
|
||||
# Set MINIO_ROOT_USER and MINIO_ROOT_PASSWORD in .env.local for local development
|
||||
# Use Docker Secrets in production/staging for production deployments
|
||||
- MINIO_ROOT_USER=${MINIO_ROOT_USER}
|
||||
- MINIO_ROOT_PASSWORD=${MINIO_ROOT_PASSWORD}
|
||||
command: server /data --console-address ":9001"
|
||||
volumes:
|
||||
- minio_data:/data
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 10s
|
||||
networks:
|
||||
- backend
|
||||
|
||||
networks:
|
||||
frontend:
|
||||
driver: bridge
|
||||
backend:
|
||||
driver: bridge
|
||||
cache:
|
||||
driver: bridge
|
||||
|
||||
volumes:
|
||||
redis_data:
|
||||
composer-cache:
|
||||
storage-queue: # Queue-Verzeichnis (Performance-kritisch, persistent)
|
||||
var-data: # Runtime logs (persistent)
|
||||
db_data:
|
||||
project-data:
|
||||
worker-logs:
|
||||
worker-queue:
|
||||
worker-storage: # Complete separate storage for worker with correct permissions
|
||||
minio_data: # MinIO object storage data
|
||||
|
||||
# Docker Secrets Configuration
|
||||
# Secrets are defined here but activated in environment-specific override files
|
||||
secrets:
|
||||
db_root_password:
|
||||
file: ./secrets/db_root_password.txt
|
||||
external: false
|
||||
db_user_password:
|
||||
file: ./secrets/db_user_password.txt
|
||||
external: false
|
||||
redis_password:
|
||||
file: ./secrets/redis_password.txt
|
||||
external: false
|
||||
app_key:
|
||||
file: ./secrets/app_key.txt
|
||||
external: false
|
||||
vault_encryption_key:
|
||||
file: ./secrets/vault_encryption_key.txt
|
||||
external: false
|
||||
git_token:
|
||||
file: ./secrets/git_token.txt
|
||||
external: false
|
||||
|
||||
@@ -0,0 +1,370 @@
|
||||
# Production Environment Override
|
||||
# Usage: docker-compose -f docker-compose.base.yml -f docker-compose.production.yml --env-file .env.production up -d
|
||||
#
|
||||
# This file overrides base configuration with production-specific settings:
|
||||
# - Stricter resource limits
|
||||
# - Production restart policies (always)
|
||||
# - JSON logging with proper rotation
|
||||
# - No host mounts (security)
|
||||
# - Production PostgreSQL configuration
|
||||
# - Certbot for SSL certificates
|
||||
# - Production port mappings (80, 443 for Let's Encrypt)
|
||||
|
||||
services:
|
||||
web:
|
||||
# Use pre-built image from registry (override build from base)
|
||||
image: localhost:5000/framework:latest
|
||||
# Build section removed - production-base.yml has no build sections
|
||||
|
||||
# Production restart policy
|
||||
restart: always
|
||||
|
||||
# Note: Port mappings removed - Traefik handles all external routing
|
||||
# No direct port bindings needed, Traefik proxies traffic to this container
|
||||
|
||||
# Override volumes - use Let's Encrypt certificates and mount application code
|
||||
volumes:
|
||||
- certbot-conf:/etc/letsencrypt:ro
|
||||
- certbot-www:/var/www/certbot:ro
|
||||
# Application code via rsync deployment
|
||||
- /home/deploy/michaelschiemer/current:/var/www/html:ro
|
||||
|
||||
environment:
|
||||
- APP_ENV=production
|
||||
- APP_DEBUG=false
|
||||
|
||||
# Security hardening
|
||||
# Note: no-new-privileges prevents PHP-FPM from switching to www-data
|
||||
# We need to allow privilege escalation for PHP-FPM user switching
|
||||
# security_opt:
|
||||
# - no-new-privileges:true
|
||||
cap_drop:
|
||||
- ALL
|
||||
cap_add:
|
||||
- CHOWN
|
||||
- DAC_OVERRIDE
|
||||
- NET_BIND_SERVICE # Required for binding to ports 80/443
|
||||
- SETGID # Required for PHP-FPM to switch to www-data
|
||||
- SETUID # Required for PHP-FPM to switch to www-data
|
||||
|
||||
# Stricter health checks for production
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "https://localhost/health"]
|
||||
interval: 15s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 30s
|
||||
|
||||
# JSON logging with rotation
|
||||
logging:
|
||||
driver: json-file
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "5"
|
||||
compress: "true"
|
||||
labels: "service,environment"
|
||||
|
||||
# Production resource limits (Nginx is lightweight)
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 512M
|
||||
cpus: '1.0'
|
||||
reservations:
|
||||
memory: 256M
|
||||
cpus: '0.5'
|
||||
|
||||
depends_on:
|
||||
php:
|
||||
condition: service_healthy
|
||||
certbot:
|
||||
condition: service_started
|
||||
|
||||
php:
|
||||
# Use pre-built image from registry (override build from base)
|
||||
image: localhost:5000/framework:latest
|
||||
# Build section removed - production-base.yml has no build sections
|
||||
|
||||
# Production restart policy
|
||||
restart: always
|
||||
|
||||
# Override user setting - container must start as root for gosu to work
|
||||
# The entrypoint script will use gosu to switch to appuser after setup
|
||||
user: "root"
|
||||
|
||||
# Security hardening (applied after gosu switches to appuser)
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
cap_drop:
|
||||
- ALL
|
||||
cap_add:
|
||||
- CHOWN
|
||||
- DAC_OVERRIDE
|
||||
|
||||
# Load environment variables from .env file (generated by Ansible)
|
||||
# Use absolute path to ensure .env is found regardless of working directory
|
||||
env_file:
|
||||
- /home/deploy/deployment/stacks/production/.env
|
||||
environment:
|
||||
- APP_ENV=production
|
||||
- APP_DEBUG=false
|
||||
- PHP_MEMORY_LIMIT=512M
|
||||
- PHP_MAX_EXECUTION_TIME=30
|
||||
# Disable Xdebug in production
|
||||
- XDEBUG_MODE=off
|
||||
# Use Docker Secrets via *_FILE pattern (Framework supports this automatically)
|
||||
- DB_PASSWORD_FILE=/run/secrets/db_user_password
|
||||
- REDIS_PASSWORD_FILE=/run/secrets/redis_password
|
||||
- APP_KEY_FILE=/run/secrets/app_key
|
||||
- VAULT_ENCRYPTION_KEY_FILE=/run/secrets/vault_encryption_key
|
||||
secrets:
|
||||
- db_user_password
|
||||
- redis_password
|
||||
- app_key
|
||||
- vault_encryption_key
|
||||
|
||||
# Stricter health checks
|
||||
healthcheck:
|
||||
test: ["CMD", "php", "-v"]
|
||||
interval: 15s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 30s
|
||||
|
||||
# JSON logging
|
||||
logging:
|
||||
driver: json-file
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "10"
|
||||
compress: "true"
|
||||
labels: "service,environment"
|
||||
|
||||
# Production resource limits
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 1G
|
||||
cpus: '2.0'
|
||||
reservations:
|
||||
memory: 512M
|
||||
cpus: '1.0'
|
||||
|
||||
# Production volumes
|
||||
volumes:
|
||||
# Mount application code from rsync deployment (read-write for storage/var directories)
|
||||
- /home/deploy/michaelschiemer/current:/var/www/html:rw
|
||||
|
||||
# Database service removed - using external PostgreSQL Stack (deployment/stacks/postgresql/)
|
||||
# Connection via app-internal network using docker-compose.postgres-override.yml
|
||||
|
||||
# Redis service removed - using external Redis Stack (deployment/stacks/redis/)
|
||||
# Connection via app-internal network using docker-compose.redis-override.yml
|
||||
|
||||
queue-worker:
|
||||
# Use pre-built image from registry (override build from base)
|
||||
image: localhost:5000/framework:latest
|
||||
# Build section removed - production-base.yml has no build sections
|
||||
|
||||
# Production restart policy
|
||||
restart: always
|
||||
|
||||
# Override user setting - container must start as root for gosu to work
|
||||
# The entrypoint script will use gosu to switch to appuser after setup
|
||||
user: "root"
|
||||
|
||||
# Override entrypoint to skip PHP-FPM/Nginx startup - queue-worker only needs PHP CLI
|
||||
entrypoint: ""
|
||||
|
||||
# Worker command - direct PHP execution
|
||||
command: ["php", "/var/www/html/worker.php"]
|
||||
|
||||
# Production volumes
|
||||
volumes:
|
||||
# Mount application code from rsync deployment (read-write for storage/var directories)
|
||||
- /home/deploy/michaelschiemer/current:/var/www/html:rw
|
||||
|
||||
# Load environment variables from .env file (generated by Ansible)
|
||||
# Use absolute path to ensure .env is found regardless of working directory
|
||||
env_file:
|
||||
- /home/deploy/deployment/stacks/production/.env
|
||||
environment:
|
||||
- APP_ENV=production
|
||||
- WORKER_DEBUG=false
|
||||
- WORKER_SLEEP_TIME=100000
|
||||
- WORKER_MAX_JOBS=10000
|
||||
# Use Docker Secrets via *_FILE pattern (Framework supports this automatically)
|
||||
- DB_PASSWORD_FILE=/run/secrets/db_user_password
|
||||
- REDIS_PASSWORD_FILE=/run/secrets/redis_password
|
||||
- APP_KEY_FILE=/run/secrets/app_key
|
||||
- VAULT_ENCRYPTION_KEY_FILE=/run/secrets/vault_encryption_key
|
||||
secrets:
|
||||
- db_user_password
|
||||
- redis_password
|
||||
- app_key
|
||||
- vault_encryption_key
|
||||
|
||||
# Production resource limits
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 2G
|
||||
cpus: '2.0'
|
||||
reservations:
|
||||
memory: 1G
|
||||
cpus: '1.0'
|
||||
# Note: replicas removed due to conflict with container_name
|
||||
# To scale queue workers, use separate docker-compose service definitions
|
||||
|
||||
# JSON logging
|
||||
logging:
|
||||
driver: json-file
|
||||
options:
|
||||
max-size: "20m"
|
||||
max-file: "10"
|
||||
compress: "true"
|
||||
labels: "service,environment"
|
||||
|
||||
# Graceful shutdown for long-running jobs
|
||||
stop_grace_period: 60s
|
||||
|
||||
# Wait for dependencies to be healthy before starting
|
||||
depends_on:
|
||||
php:
|
||||
condition: service_healthy
|
||||
# Note: PostgreSQL and Redis are external services, connection via app-internal network
|
||||
|
||||
# php-test service removed for production (test profiles not used in production)
|
||||
php-test:
|
||||
image: localhost:5000/framework:latest
|
||||
# Build section removed - production-base.yml has no build sections
|
||||
profiles:
|
||||
- never # Disable php-test in production
|
||||
|
||||
# Scheduler (Cron Jobs)
|
||||
scheduler:
|
||||
# Use pre-built image from registry (override build from base if exists)
|
||||
image: localhost:5000/framework:latest
|
||||
# Build section removed - production-base.yml has no build sections
|
||||
container_name: scheduler
|
||||
|
||||
# Production restart policy
|
||||
restart: always
|
||||
|
||||
# Override user setting - container must start as root for gosu to work
|
||||
# The entrypoint script will use gosu to switch to appuser after setup
|
||||
user: "root"
|
||||
|
||||
# Override entrypoint to skip PHP-FPM/Nginx startup - scheduler only needs PHP CLI
|
||||
entrypoint: ""
|
||||
|
||||
# Scheduler command - direct PHP execution
|
||||
command: php console.php scheduler:run
|
||||
|
||||
# Production volumes
|
||||
volumes:
|
||||
# Mount application code from rsync deployment (read-write for storage/var directories)
|
||||
- /home/deploy/michaelschiemer/current:/var/www/html:rw
|
||||
|
||||
# Load environment variables from .env file (generated by Ansible)
|
||||
# Use absolute path to ensure .env is found regardless of working directory
|
||||
env_file:
|
||||
- /home/deploy/deployment/stacks/production/.env
|
||||
environment:
|
||||
- TZ=Europe/Berlin
|
||||
- APP_ENV=production
|
||||
- APP_DEBUG=false
|
||||
# Use Docker Secrets via *_FILE pattern (Framework supports this automatically)
|
||||
- DB_PASSWORD_FILE=/run/secrets/db_user_password
|
||||
- REDIS_PASSWORD_FILE=/run/secrets/redis_password
|
||||
- APP_KEY_FILE=/run/secrets/app_key
|
||||
- VAULT_ENCRYPTION_KEY_FILE=/run/secrets/vault_encryption_key
|
||||
secrets:
|
||||
- db_user_password
|
||||
- redis_password
|
||||
- app_key
|
||||
- vault_encryption_key
|
||||
|
||||
# Production resource limits
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 512M
|
||||
cpus: '0.5'
|
||||
reservations:
|
||||
memory: 256M
|
||||
cpus: '0.25'
|
||||
|
||||
# Health checks
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "php -r 'exit(0);' && test -f /var/www/html/console.php || exit 1"]
|
||||
interval: 60s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
|
||||
# JSON logging
|
||||
logging:
|
||||
driver: json-file
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "5"
|
||||
compress: "true"
|
||||
labels: "service,environment"
|
||||
|
||||
# Graceful shutdown
|
||||
stop_grace_period: 30s
|
||||
|
||||
# Wait for dependencies to be healthy before starting
|
||||
depends_on:
|
||||
php:
|
||||
condition: service_healthy
|
||||
# Note: PostgreSQL and Redis are external services, connection via app-internal network
|
||||
|
||||
# Certbot Sidecar Container for Let's Encrypt
|
||||
certbot:
|
||||
image: certbot/certbot:latest
|
||||
container_name: certbot
|
||||
restart: always
|
||||
|
||||
volumes:
|
||||
# Share certificates with Nginx
|
||||
- certbot-conf:/etc/letsencrypt
|
||||
- certbot-www:/var/www/certbot
|
||||
# Logs for debugging
|
||||
- certbot-logs:/var/log/letsencrypt
|
||||
|
||||
# Auto-renewal every 12 hours
|
||||
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew --webroot -w /var/www/certbot --quiet; sleep 12h & wait $${!}; done;'"
|
||||
|
||||
networks:
|
||||
- frontend
|
||||
|
||||
# JSON logging
|
||||
logging:
|
||||
driver: json-file
|
||||
options:
|
||||
max-size: "5m"
|
||||
max-file: "3"
|
||||
compress: "true"
|
||||
labels: "service,environment"
|
||||
|
||||
networks:
|
||||
cache:
|
||||
internal: true # Cache network is internal in production
|
||||
|
||||
volumes:
|
||||
# Let's Encrypt SSL Certificates
|
||||
certbot-conf:
|
||||
driver: local
|
||||
certbot-www:
|
||||
driver: local
|
||||
certbot-logs:
|
||||
driver: local
|
||||
|
||||
# Application storage volume (single volume for entire storage directory)
|
||||
storage:
|
||||
driver: local
|
||||
|
||||
# Database volume removed - using external PostgreSQL Stack
|
||||
# PostgreSQL data is managed by deployment/stacks/postgresql/
|
||||
@@ -0,0 +1,34 @@
|
||||
# Redis Stack Integration Override
|
||||
# Usage: docker compose -f docker-compose.base.yml -f docker-compose.production.yml -f docker-compose.postgres-override.yml -f docker-compose.redis-override.yml up -d
|
||||
#
|
||||
# This file overrides the application stack configuration to connect to the external Redis stack.
|
||||
# It follows the same pattern as docker-compose.postgres-override.yml for consistency.
|
||||
|
||||
services:
|
||||
php:
|
||||
environment:
|
||||
REDIS_HOST: redis-stack # External Redis container name
|
||||
REDIS_PORT: 6379
|
||||
# REDIS_PASSWORD comes from Docker Secrets (not changed)
|
||||
networks:
|
||||
- app-internal
|
||||
|
||||
queue-worker:
|
||||
environment:
|
||||
REDIS_HOST: redis-stack
|
||||
REDIS_PORT: 6379
|
||||
# REDIS_PASSWORD comes from Docker Secrets (not changed)
|
||||
networks:
|
||||
- app-internal
|
||||
|
||||
scheduler:
|
||||
environment:
|
||||
REDIS_HOST: redis-stack
|
||||
REDIS_PORT: 6379
|
||||
# REDIS_PASSWORD comes from Docker Secrets (not changed)
|
||||
networks:
|
||||
- app-internal
|
||||
|
||||
networks:
|
||||
app-internal:
|
||||
external: true
|
||||
@@ -0,0 +1,137 @@
|
||||
# Secure Docker Compose Configuration
|
||||
# This file contains security hardening for the infrastructure
|
||||
# Use: docker-compose -f docker-compose.yml -f docker-compose.security.yml up
|
||||
|
||||
services:
|
||||
# Hardened Database Configuration
|
||||
db:
|
||||
image: mariadb:11.4-jammy # Pinned version for security
|
||||
environment:
|
||||
# Use Docker secrets instead of hardcoded passwords
|
||||
MYSQL_ROOT_PASSWORD_FILE: /run/secrets/db_root_password
|
||||
MYSQL_DATABASE: ${DB_DATABASE:-framework}
|
||||
MYSQL_USER: ${DB_USERNAME:-app_user}
|
||||
MYSQL_PASSWORD_FILE: /run/secrets/db_user_password
|
||||
MYSQL_INITDB_SKIP_TZINFO: 1
|
||||
# Remove exposed ports - only internal container access
|
||||
ports: []
|
||||
expose:
|
||||
- "3306"
|
||||
volumes:
|
||||
- ./docker/mysql/conf.d:/etc/mysql/conf.d:ro
|
||||
secrets:
|
||||
- db_root_password
|
||||
- db_user_password
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
user: "999:999" # mysql user
|
||||
cap_drop:
|
||||
- ALL
|
||||
cap_add:
|
||||
- CHOWN
|
||||
- DAC_OVERRIDE
|
||||
- SETGID
|
||||
- SETUID
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 1G
|
||||
cpus: '1.0'
|
||||
reservations:
|
||||
memory: 512M
|
||||
|
||||
# Hardened Redis Configuration
|
||||
redis:
|
||||
image: redis:7-alpine # Stable version
|
||||
volumes:
|
||||
- ./docker/redis/redis-secure.conf:/usr/local/etc/redis/redis.conf:ro
|
||||
secrets:
|
||||
- redis_password
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "--no-auth-warning", "-a", "$(cat /run/secrets/redis_password)", "ping"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
user: "999:1000"
|
||||
cap_drop:
|
||||
- ALL
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 256M
|
||||
cpus: '0.5'
|
||||
|
||||
# Hardened Queue Worker
|
||||
queue-worker:
|
||||
user: "1000:1000"
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
cap_drop:
|
||||
- ALL
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 512M
|
||||
cpus: '0.5'
|
||||
reservations:
|
||||
memory: 256M
|
||||
|
||||
# Hardened PHP Container
|
||||
php:
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
cap_drop:
|
||||
- ALL
|
||||
cap_add:
|
||||
- CHOWN
|
||||
- DAC_OVERRIDE
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 1G
|
||||
cpus: '1.0'
|
||||
|
||||
# Hardened Web Container
|
||||
web:
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
cap_drop:
|
||||
- ALL
|
||||
cap_add:
|
||||
- CHOWN
|
||||
- DAC_OVERRIDE
|
||||
- NET_BIND_SERVICE
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 256M
|
||||
cpus: '0.5'
|
||||
|
||||
# Docker Secrets Configuration
|
||||
secrets:
|
||||
db_root_password:
|
||||
file: ./secrets/db_root_password.txt
|
||||
db_user_password:
|
||||
file: ./secrets/db_user_password.txt
|
||||
redis_password:
|
||||
file: ./secrets/redis_password.txt
|
||||
|
||||
# Secure Networks
|
||||
networks:
|
||||
frontend:
|
||||
driver: bridge
|
||||
driver_opts:
|
||||
com.docker.network.enable_ipv6: "false"
|
||||
internal: false
|
||||
backend:
|
||||
driver: bridge
|
||||
driver_opts:
|
||||
com.docker.network.enable_ipv6: "false"
|
||||
internal: true
|
||||
cache:
|
||||
driver: bridge
|
||||
driver_opts:
|
||||
com.docker.network.enable_ipv6: "false"
|
||||
internal: true
|
||||
@@ -0,0 +1,26 @@
|
||||
# PostgreSQL Staging Connection Override
|
||||
#
|
||||
# This file provides network configuration for connecting to the PostgreSQL Staging Stack.
|
||||
# Used by Staging Stack.
|
||||
#
|
||||
# Usage:
|
||||
# Staging Stack:
|
||||
# docker compose -f docker-compose.base.yml \
|
||||
# -f docker-compose.staging.yml \
|
||||
# -f docker-compose.staging-postgres-override.yml up
|
||||
#
|
||||
# Prerequisites:
|
||||
# - PostgreSQL Staging Stack must be running (creates postgres-staging-internal network)
|
||||
# - postgres-staging-internal network must exist as external network
|
||||
# - PostgreSQL Staging Stack: deployment/stacks/postgresql-staging/docker-compose.yml
|
||||
|
||||
services:
|
||||
# Staging Stack Services
|
||||
# These services will be merged with existing definitions from base.yml + staging.yml
|
||||
# Note: postgres-staging-internal network is already defined in docker-compose.staging.yml
|
||||
# This override file is kept for backward compatibility but may not be needed anymore
|
||||
|
||||
networks:
|
||||
postgres-staging-internal:
|
||||
external: true
|
||||
name: postgres-staging-internal
|
||||
Reference in New Issue
Block a user