| 1 |
version: '3.8' |
| 2 |
|
| 3 |
services: |
| 4 |
# Frontend (Vue.js + nginx) |
| 5 |
web-client: |
| 6 |
image: zephyrfs/web-client:latest |
| 7 |
deploy: |
| 8 |
replicas: 2 |
| 9 |
restart_policy: |
| 10 |
condition: on-failure |
| 11 |
delay: 5s |
| 12 |
max_attempts: 3 |
| 13 |
resources: |
| 14 |
limits: |
| 15 |
memory: 512M |
| 16 |
cpus: '0.5' |
| 17 |
reservations: |
| 18 |
memory: 256M |
| 19 |
cpus: '0.25' |
| 20 |
environment: |
| 21 |
- NODE_ENV=production |
| 22 |
networks: |
| 23 |
- zephyrfs-frontend |
| 24 |
- zephyrfs-backend |
| 25 |
volumes: |
| 26 |
- web-logs:/var/log/nginx |
| 27 |
healthcheck: |
| 28 |
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8080/health"] |
| 29 |
interval: 30s |
| 30 |
timeout: 10s |
| 31 |
retries: 3 |
| 32 |
start_period: 40s |
| 33 |
|
| 34 |
# Backend API server |
| 35 |
web-server: |
| 36 |
image: zephyrfs/web-server:latest |
| 37 |
deploy: |
| 38 |
replicas: 3 |
| 39 |
restart_policy: |
| 40 |
condition: on-failure |
| 41 |
delay: 5s |
| 42 |
max_attempts: 3 |
| 43 |
resources: |
| 44 |
limits: |
| 45 |
memory: 1G |
| 46 |
cpus: '1.0' |
| 47 |
reservations: |
| 48 |
memory: 512M |
| 49 |
cpus: '0.5' |
| 50 |
environment: |
| 51 |
- NODE_ENV=production |
| 52 |
- ZEPHYRFS_NODE_URL=http://zephyrfs-node:8080 |
| 53 |
- JWT_SECRET=${JWT_SECRET} |
| 54 |
- LOG_LEVEL=info |
| 55 |
- CORS_ORIGINS=${CORS_ORIGINS:-https://your-domain.com} |
| 56 |
- PORT=3000 |
| 57 |
secrets: |
| 58 |
- jwt_secret |
| 59 |
volumes: |
| 60 |
- web-logs:/app/logs |
| 61 |
networks: |
| 62 |
- zephyrfs-backend |
| 63 |
healthcheck: |
| 64 |
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000/api/health"] |
| 65 |
interval: 30s |
| 66 |
timeout: 10s |
| 67 |
retries: 3 |
| 68 |
start_period: 40s |
| 69 |
|
| 70 |
# ZephyrFS core node |
| 71 |
zephyrfs-node: |
| 72 |
image: zephyrfs/node:latest |
| 73 |
deploy: |
| 74 |
replicas: 1 |
| 75 |
restart_policy: |
| 76 |
condition: on-failure |
| 77 |
delay: 10s |
| 78 |
max_attempts: 3 |
| 79 |
resources: |
| 80 |
limits: |
| 81 |
memory: 2G |
| 82 |
cpus: '2.0' |
| 83 |
reservations: |
| 84 |
memory: 1G |
| 85 |
cpus: '1.0' |
| 86 |
environment: |
| 87 |
- RUST_LOG=info |
| 88 |
- ZEPHYRFS_DATA_DIR=/data |
| 89 |
- ZEPHYRFS_BIND_ADDR=0.0.0.0:8080 |
| 90 |
volumes: |
| 91 |
- zephyrfs-data:/data |
| 92 |
- node-logs:/logs |
| 93 |
networks: |
| 94 |
- zephyrfs-backend |
| 95 |
healthcheck: |
| 96 |
test: ["CMD", "curl", "-f", "http://localhost:8080/health"] |
| 97 |
interval: 30s |
| 98 |
timeout: 10s |
| 99 |
retries: 3 |
| 100 |
start_period: 60s |
| 101 |
|
| 102 |
# Load balancer with TLS termination |
| 103 |
nginx-proxy: |
| 104 |
image: nginx:alpine |
| 105 |
ports: |
| 106 |
- "443:443" |
| 107 |
- "80:80" |
| 108 |
deploy: |
| 109 |
replicas: 2 |
| 110 |
restart_policy: |
| 111 |
condition: on-failure |
| 112 |
delay: 5s |
| 113 |
max_attempts: 3 |
| 114 |
resources: |
| 115 |
limits: |
| 116 |
memory: 256M |
| 117 |
cpus: '0.5' |
| 118 |
reservations: |
| 119 |
memory: 128M |
| 120 |
cpus: '0.25' |
| 121 |
volumes: |
| 122 |
- ./nginx/production.conf:/etc/nginx/nginx.conf:ro |
| 123 |
- ssl-certs:/etc/nginx/ssl:ro |
| 124 |
- nginx-logs:/var/log/nginx |
| 125 |
networks: |
| 126 |
- zephyrfs-frontend |
| 127 |
depends_on: |
| 128 |
- web-client |
| 129 |
healthcheck: |
| 130 |
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost/health"] |
| 131 |
interval: 30s |
| 132 |
timeout: 10s |
| 133 |
retries: 3 |
| 134 |
|
| 135 |
# Monitoring and logging |
| 136 |
prometheus: |
| 137 |
image: prom/prometheus:latest |
| 138 |
ports: |
| 139 |
- "9090:9090" |
| 140 |
deploy: |
| 141 |
replicas: 1 |
| 142 |
resources: |
| 143 |
limits: |
| 144 |
memory: 512M |
| 145 |
cpus: '0.5' |
| 146 |
volumes: |
| 147 |
- ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml:ro |
| 148 |
- prometheus-data:/prometheus |
| 149 |
networks: |
| 150 |
- zephyrfs-monitoring |
| 151 |
command: |
| 152 |
- '--config.file=/etc/prometheus/prometheus.yml' |
| 153 |
- '--storage.tsdb.path=/prometheus' |
| 154 |
- '--web.console.libraries=/etc/prometheus/console_libraries' |
| 155 |
- '--web.console.templates=/etc/prometheus/consoles' |
| 156 |
- '--web.enable-lifecycle' |
| 157 |
|
| 158 |
grafana: |
| 159 |
image: grafana/grafana:latest |
| 160 |
ports: |
| 161 |
- "3001:3000" |
| 162 |
deploy: |
| 163 |
replicas: 1 |
| 164 |
resources: |
| 165 |
limits: |
| 166 |
memory: 256M |
| 167 |
cpus: '0.25' |
| 168 |
environment: |
| 169 |
- GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD:-admin} |
| 170 |
- GF_INSTALL_PLUGINS=grafana-piechart-panel |
| 171 |
volumes: |
| 172 |
- grafana-data:/var/lib/grafana |
| 173 |
- ./monitoring/grafana/dashboards:/etc/grafana/provisioning/dashboards:ro |
| 174 |
- ./monitoring/grafana/datasources:/etc/grafana/provisioning/datasources:ro |
| 175 |
networks: |
| 176 |
- zephyrfs-monitoring |
| 177 |
|
| 178 |
# Log aggregation |
| 179 |
loki: |
| 180 |
image: grafana/loki:latest |
| 181 |
ports: |
| 182 |
- "3100:3100" |
| 183 |
deploy: |
| 184 |
replicas: 1 |
| 185 |
resources: |
| 186 |
limits: |
| 187 |
memory: 512M |
| 188 |
cpus: '0.5' |
| 189 |
volumes: |
| 190 |
- ./monitoring/loki.yml:/etc/loki/local-config.yaml:ro |
| 191 |
- loki-data:/loki |
| 192 |
networks: |
| 193 |
- zephyrfs-monitoring |
| 194 |
command: -config.file=/etc/loki/local-config.yaml |
| 195 |
|
| 196 |
promtail: |
| 197 |
image: grafana/promtail:latest |
| 198 |
deploy: |
| 199 |
replicas: 1 |
| 200 |
resources: |
| 201 |
limits: |
| 202 |
memory: 128M |
| 203 |
cpus: '0.25' |
| 204 |
volumes: |
| 205 |
- /var/log:/var/log:ro |
| 206 |
- web-logs:/var/log/web:ro |
| 207 |
- node-logs:/var/log/node:ro |
| 208 |
- nginx-logs:/var/log/nginx:ro |
| 209 |
- ./monitoring/promtail.yml:/etc/promtail/config.yml:ro |
| 210 |
networks: |
| 211 |
- zephyrfs-monitoring |
| 212 |
command: -config.file=/etc/promtail/config.yml |
| 213 |
|
| 214 |
volumes: |
| 215 |
zephyrfs-data: |
| 216 |
driver: local |
| 217 |
driver_opts: |
| 218 |
type: none |
| 219 |
o: bind |
| 220 |
device: ${DATA_PATH:-/opt/zephyrfs/data} |
| 221 |
web-logs: |
| 222 |
driver: local |
| 223 |
node-logs: |
| 224 |
driver: local |
| 225 |
nginx-logs: |
| 226 |
driver: local |
| 227 |
prometheus-data: |
| 228 |
driver: local |
| 229 |
grafana-data: |
| 230 |
driver: local |
| 231 |
loki-data: |
| 232 |
driver: local |
| 233 |
ssl-certs: |
| 234 |
driver: local |
| 235 |
driver_opts: |
| 236 |
type: none |
| 237 |
o: bind |
| 238 |
device: ${SSL_CERTS_PATH:-/opt/zephyrfs/ssl} |
| 239 |
|
| 240 |
networks: |
| 241 |
zephyrfs-frontend: |
| 242 |
driver: overlay |
| 243 |
attachable: true |
| 244 |
zephyrfs-backend: |
| 245 |
driver: overlay |
| 246 |
internal: true |
| 247 |
zephyrfs-monitoring: |
| 248 |
driver: overlay |
| 249 |
internal: true |
| 250 |
|
| 251 |
secrets: |
| 252 |
jwt_secret: |
| 253 |
external: true |
| 254 |
|
| 255 |
configs: |
| 256 |
nginx_config: |
| 257 |
external: true |