2026-10-15 20:08:15 +08:00
|
|
|
name: chublog
|
|
|
|
|
x-logging: &logging
|
|
|
|
|
driver: json-file
|
|
|
|
|
options:
|
|
|
|
|
max-size: "10m"
|
|
|
|
|
max-file: "3"
|
2026-10-17 13:13:26 +08:00
|
|
|
x-backend-build: &backend-build
|
|
|
|
|
context: ..
|
|
|
|
|
dockerfile: deploy/Dockerfile
|
|
|
|
|
args:
|
|
|
|
|
DEBIAN_MIRROR: ${DEBIAN_MIRROR:-mirrors.tencentyun.com}
|
|
|
|
|
DEBIAN_IMAGE: ${REGISTRY_PREFIX-mirror.ccs.tencentyun.com/library/}debian:trixie-slim
|
|
|
|
|
RUST_IMAGE: ${REGISTRY_PREFIX-mirror.ccs.tencentyun.com/library/}rust:1-trixie
|
|
|
|
|
HASKELL_IMAGE: ${REGISTRY_PREFIX-mirror.ccs.tencentyun.com/library/}haskell:9.10.3-slim-bookworm
|
|
|
|
|
CARGO_MIRROR_INDEX: ${CARGO_MIRROR_INDEX-sparse+https://rsproxy.cn/index/}
|
2026-10-15 20:08:15 +08:00
|
|
|
services:
|
|
|
|
|
init:
|
2026-10-17 13:13:26 +08:00
|
|
|
build: { <<: *backend-build, target: init }
|
2026-10-15 20:08:15 +08:00
|
|
|
volumes:
|
|
|
|
|
- content:/data
|
|
|
|
|
- authorization:/auth
|
|
|
|
|
- ingress:/srv/ingress
|
|
|
|
|
- database:/db-data
|
|
|
|
|
- db-logs:/db-logs
|
|
|
|
|
restart: "no"
|
|
|
|
|
network_mode: none
|
|
|
|
|
logging: *logging
|
|
|
|
|
api:
|
2026-10-17 13:13:26 +08:00
|
|
|
build: { <<: *backend-build, target: api }
|
2026-10-15 20:08:15 +08:00
|
|
|
depends_on:
|
|
|
|
|
init: { condition: service_completed_successfully }
|
|
|
|
|
environment:
|
|
|
|
|
PUBLIC_ORIGIN: ${PUBLIC_ORIGIN:?Set PUBLIC_ORIGIN}
|
|
|
|
|
CHUSQL_ADDRESS: db:7777
|
|
|
|
|
CHUSQL_USER: chublog_index
|
|
|
|
|
CHUSQL_PASSWORD: ${CHUSQL_PASSWORD:?Set CHUSQL_PASSWORD}
|
|
|
|
|
CHUSQL_DATABASE: chublog
|
2026-10-17 14:21:52 +08:00
|
|
|
ALLOW_REGISTRATION: ${ALLOW_REGISTRATION:-true}
|
2026-10-15 20:08:15 +08:00
|
|
|
volumes:
|
|
|
|
|
- content:/data
|
|
|
|
|
- authorization:/auth
|
|
|
|
|
- ingress:/srv/ingress:ro
|
|
|
|
|
read_only: true
|
|
|
|
|
tmpfs: ["/tmp:size=16m,noexec,nosuid"]
|
|
|
|
|
cap_drop: [ALL]
|
|
|
|
|
security_opt: [no-new-privileges:true]
|
|
|
|
|
pids_limit: 128
|
|
|
|
|
mem_limit: 512m
|
|
|
|
|
cpus: 1.0
|
|
|
|
|
networks: [backend]
|
|
|
|
|
restart: unless-stopped
|
|
|
|
|
healthcheck:
|
|
|
|
|
test: [CMD, curl, -fsS, http://127.0.0.1:3001/api/health]
|
|
|
|
|
interval: 10s
|
|
|
|
|
timeout: 3s
|
|
|
|
|
retries: 3
|
|
|
|
|
logging: *logging
|
2026-10-16 23:36:56 +08:00
|
|
|
web:
|
2026-10-17 13:13:26 +08:00
|
|
|
build:
|
|
|
|
|
context: ../apps/web
|
|
|
|
|
args:
|
|
|
|
|
NODE_IMAGE: ${REGISTRY_PREFIX-mirror.ccs.tencentyun.com/library/}node:24-bookworm-slim
|
|
|
|
|
NPM_REGISTRY: ${NPM_REGISTRY:-https://mirrors.tencentyun.com/npm/}
|
2026-10-16 23:36:56 +08:00
|
|
|
depends_on:
|
|
|
|
|
api: { condition: service_healthy }
|
|
|
|
|
environment:
|
|
|
|
|
API_BASE_URL: http://api:3001
|
|
|
|
|
PUBLIC_ORIGIN: ${PUBLIC_ORIGIN:?Set PUBLIC_ORIGIN}
|
|
|
|
|
SITE_TITLE: ${SITE_TITLE:-ChuBlog}
|
|
|
|
|
SSH_PORT: ${SSH_PORT:-2222}
|
|
|
|
|
read_only: true
|
|
|
|
|
tmpfs: ["/tmp:size=16m,noexec,nosuid"]
|
|
|
|
|
cap_drop: [ALL]
|
|
|
|
|
security_opt: [no-new-privileges:true]
|
|
|
|
|
pids_limit: 64
|
|
|
|
|
mem_limit: 256m
|
|
|
|
|
cpus: 1.0
|
|
|
|
|
networks: [backend]
|
|
|
|
|
restart: unless-stopped
|
|
|
|
|
healthcheck:
|
|
|
|
|
test: [CMD, node, -e, "fetch('http://127.0.0.1:4321/').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"]
|
|
|
|
|
interval: 10s
|
|
|
|
|
timeout: 5s
|
|
|
|
|
retries: 3
|
|
|
|
|
logging: *logging
|
2026-10-15 20:08:15 +08:00
|
|
|
ssh:
|
2026-10-17 13:13:26 +08:00
|
|
|
build: { <<: *backend-build, target: ssh }
|
2026-10-15 20:08:15 +08:00
|
|
|
depends_on:
|
|
|
|
|
init: { condition: service_completed_successfully }
|
|
|
|
|
api: { condition: service_healthy }
|
|
|
|
|
environment:
|
|
|
|
|
CHUBLOG_SSH_CONFIG: /auth/publishers.json
|
|
|
|
|
ports: ["${SSH_BIND:-0.0.0.0}:${SSH_PORT:-2222}:2222"]
|
|
|
|
|
volumes:
|
|
|
|
|
- ingress:/srv/ingress
|
|
|
|
|
- authorization:/auth:ro
|
|
|
|
|
- ssh-host-keys:/host-keys
|
|
|
|
|
read_only: true
|
|
|
|
|
tmpfs: ["/run:size=8m,noexec,nosuid", "/tmp:size=16m,noexec,nosuid"]
|
|
|
|
|
cap_drop: [ALL]
|
|
|
|
|
cap_add: [SETUID, SETGID, SYS_CHROOT]
|
|
|
|
|
security_opt: [no-new-privileges:true]
|
|
|
|
|
pids_limit: 64
|
|
|
|
|
mem_limit: 256m
|
|
|
|
|
cpus: 1.0
|
|
|
|
|
networks: [ssh]
|
|
|
|
|
restart: unless-stopped
|
|
|
|
|
logging: *logging
|
|
|
|
|
db:
|
2026-10-17 13:13:26 +08:00
|
|
|
build: { <<: *backend-build, target: database }
|
2026-10-15 20:08:15 +08:00
|
|
|
depends_on:
|
|
|
|
|
init: { condition: service_completed_successfully }
|
|
|
|
|
environment:
|
|
|
|
|
CHUSQL_ROOT_PASSWORD: ${CHUSQL_ROOT_PASSWORD:?Set CHUSQL_ROOT_PASSWORD}
|
|
|
|
|
volumes:
|
|
|
|
|
- database:/var/lib/chusql
|
|
|
|
|
- db-logs:/var/log/chusql
|
|
|
|
|
read_only: true
|
|
|
|
|
tmpfs: ["/tmp:size=16m,noexec,nosuid"]
|
|
|
|
|
cap_drop: [ALL]
|
|
|
|
|
security_opt: [no-new-privileges:true]
|
|
|
|
|
pids_limit: 64
|
|
|
|
|
mem_limit: 512m
|
|
|
|
|
cpus: 1.0
|
|
|
|
|
networks: [backend]
|
|
|
|
|
restart: unless-stopped
|
|
|
|
|
logging: *logging
|
|
|
|
|
db-init:
|
2026-10-17 13:13:26 +08:00
|
|
|
build: { <<: *backend-build, target: api }
|
2026-10-15 20:08:15 +08:00
|
|
|
profiles: [setup]
|
|
|
|
|
entrypoint: [chublog-api, provision-db]
|
|
|
|
|
environment:
|
|
|
|
|
CHUSQL_ADDRESS: db:7777
|
|
|
|
|
CHUSQL_ROOT_PASSWORD: ${CHUSQL_ROOT_PASSWORD:?Set CHUSQL_ROOT_PASSWORD}
|
|
|
|
|
CHUSQL_PASSWORD: ${CHUSQL_PASSWORD:?Set CHUSQL_PASSWORD}
|
|
|
|
|
depends_on: [db]
|
|
|
|
|
networks: [backend]
|
|
|
|
|
cap_drop: [ALL]
|
|
|
|
|
security_opt: [no-new-privileges:true]
|
|
|
|
|
read_only: true
|
|
|
|
|
restart: "no"
|
|
|
|
|
logging: *logging
|
|
|
|
|
caddy:
|
2026-10-17 13:13:26 +08:00
|
|
|
image: ${REGISTRY_PREFIX-mirror.ccs.tencentyun.com/library/}caddy:2
|
2026-10-15 20:08:15 +08:00
|
|
|
environment:
|
|
|
|
|
SITE_ADDRESS: ${SITE_ADDRESS:-localhost}
|
|
|
|
|
ports: ["${HTTP_BIND:-0.0.0.0}:${HTTP_PORT:-80}:80", "${HTTP_BIND:-0.0.0.0}:${HTTPS_PORT:-443}:443"]
|
|
|
|
|
volumes:
|
|
|
|
|
- ./Caddyfile:/etc/caddy/Caddyfile:ro
|
|
|
|
|
- caddy-data:/data
|
|
|
|
|
- caddy-config:/config
|
|
|
|
|
cap_drop: [ALL]
|
|
|
|
|
cap_add: [NET_BIND_SERVICE]
|
|
|
|
|
security_opt: [no-new-privileges:true]
|
|
|
|
|
networks: [backend, edge]
|
|
|
|
|
depends_on:
|
|
|
|
|
api: { condition: service_healthy }
|
2026-10-16 23:36:56 +08:00
|
|
|
web: { condition: service_healthy }
|
2026-10-15 20:08:15 +08:00
|
|
|
restart: unless-stopped
|
|
|
|
|
logging: *logging
|
|
|
|
|
networks:
|
|
|
|
|
backend: { internal: true }
|
|
|
|
|
ssh: {}
|
|
|
|
|
edge: {}
|
|
|
|
|
volumes:
|
|
|
|
|
content: {}
|
|
|
|
|
ingress: {}
|
|
|
|
|
authorization: {}
|
|
|
|
|
ssh-host-keys: {}
|
|
|
|
|
database: {}
|
|
|
|
|
db-logs: {}
|
|
|
|
|
caddy-data: {}
|
|
|
|
|
caddy-config: {}
|