version: '3.8' services: # Frontend (Vue.js + nginx) web-client: build: context: ./client dockerfile: Dockerfile ports: - "80:8080" environment: - NODE_ENV=production depends_on: - web-server networks: - zephyrfs restart: unless-stopped healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8080/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s # Backend API server web-server: build: context: ./server dockerfile: Dockerfile ports: - "3000:3000" environment: - NODE_ENV=production - ZEPHYRFS_NODE_URL=http://zephyrfs-node:8080 - JWT_SECRET=${JWT_SECRET:-change-this-in-production-min-32-chars-long} - LOG_LEVEL=info - CORS_ORIGINS=http://localhost volumes: - web-logs:/app/logs depends_on: - zephyrfs-node networks: - zephyrfs restart: unless-stopped healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000/api/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s # ZephyrFS core node zephyrfs-node: image: zephyrfs-node:latest ports: - "8080:8080" volumes: - zephyrfs-data:/data - node-logs:/logs environment: - RUST_LOG=info - ZEPHYRFS_DATA_DIR=/data networks: - zephyrfs restart: unless-stopped healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8080/health"] interval: 30s timeout: 10s retries: 3 start_period: 60s # Reverse proxy with TLS termination nginx-proxy: image: nginx:alpine ports: - "443:443" - "80:80" volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro - ./nginx/ssl:/etc/nginx/ssl:ro - nginx-logs:/var/log/nginx depends_on: - web-client networks: - zephyrfs restart: unless-stopped healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost/health"] interval: 30s timeout: 10s retries: 3 volumes: zephyrfs-data: driver: local web-logs: driver: local node-logs: driver: local nginx-logs: driver: local networks: zephyrfs: driver: bridge ipam: config: - subnet: 172.20.0.0/16