feat: add containerized application delivery #11 #12
@@ -0,0 +1,12 @@
|
||||
# Copy to a restricted, untracked file. Never commit filled values.
|
||||
# Full release image references; use published version tags, not latest.
|
||||
FRONTEND_IMAGE=git.personal.ksv741.ru/wealthledger/frontend:0.1.0
|
||||
BACKEND_IMAGE=git.personal.ksv741.ru/wealthledger/backend:0.1.0
|
||||
FRONTEND_PORT=8080
|
||||
FRONTEND_ORIGIN=https://wealthledger.example.com
|
||||
# Absolute directory, pre-created with owner UID/GID 1000:1000 and mode 0700.
|
||||
DATA_DIRECTORY=/srv/wealthledger/data
|
||||
# Generate once and keep across updates. Store an independent key backup.
|
||||
JWT_SECRET=
|
||||
TOKEN_ENCRYPTION_KEY=
|
||||
LOG_LEVEL=info
|
||||
@@ -0,0 +1,10 @@
|
||||
# Local-only fixture values. Never use this file for a server deployment.
|
||||
# Base-file interpolation happens before overrides; these references are replaced.
|
||||
FRONTEND_IMAGE=wealthledger-frontend:development
|
||||
BACKEND_IMAGE=wealthledger-backend:development
|
||||
DATA_DIRECTORY=/unused-development-volume
|
||||
FRONTEND_PORT=5173
|
||||
FRONTEND_ORIGIN=http://localhost:5173
|
||||
JWT_SECRET=local-development-only-not-a-server-secret
|
||||
TOKEN_ENCRYPTION_KEY=MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY=
|
||||
LOG_LEVEL=info
|
||||
@@ -3,6 +3,10 @@
|
||||
!/.gitignore
|
||||
!/AGENTS.md
|
||||
!/README.md
|
||||
!/compose.yaml
|
||||
!/compose.development.yaml
|
||||
!/.env.compose.example
|
||||
!/.env.development.example
|
||||
!/.ai/
|
||||
/.ai/*
|
||||
!/.ai/conventions/
|
||||
|
||||
@@ -41,7 +41,7 @@ git clone ssh://git@git.personal.ksv741.ru:2222/WealthLedger/specs.git specs
|
||||
|
||||
Root отслеживает входные документы, собственные engineering conventions и исторический migration
|
||||
inventory в `.ai/`, npm/release-конфигурацию, changelog,
|
||||
один CI workflow с commitlint. Точный allowlist — в `.gitignore`.
|
||||
Compose configuration, безопасные env examples и один CI workflow с commitlint. Точный allowlist — в `.gitignore`.
|
||||
Остальные root-пути игнорируются по умолчанию:
|
||||
вложенные repos, `.env`, базы и WAL, импорты выписок, PDF, `references/`,
|
||||
`design/`, `todo/` и локальные настройки инструментов.
|
||||
@@ -53,6 +53,35 @@ inventory в `.ai/`, npm/release-конфигурацию, changelog,
|
||||
Не запускайте очистку workspace через `git clean -fdx`: ignored-пути содержат
|
||||
локальные данные. Правила tracking не удаляют файлы и вложенные `.git`.
|
||||
|
||||
## Запуск через Docker Compose
|
||||
|
||||
Нужны Docker Engine и Compose >= 2.24.4, а для development — checkout
|
||||
`frontend/` и `backend/` рядом с root. Компоненты собираются независимо:
|
||||
|
||||
```bash
|
||||
docker compose --env-file .env.development.example \
|
||||
-f compose.yaml -f compose.development.yaml up -d --build --wait --wait-timeout 180
|
||||
```
|
||||
|
||||
Откройте `http://localhost:5173`: Vite HMR и `/api/` используют один origin,
|
||||
Nest работает в watch mode. Host `node_modules` и `.env` не монтируются.
|
||||
Данные development хранятся отдельно в named volume `development-data` проекта `wealthledger-dev`;
|
||||
обычные restart/down их сохраняют. Изменение dependencies/config требует rebuild.
|
||||
|
||||
Production использует `compose.yaml` и restricted env по `.env.compose.example`:
|
||||
две ссылки на опубликованные версии images, persistent absolute host data path,
|
||||
постоянные JWT/encryption secrets и публичный HTTPS origin. Каталог данных
|
||||
должен существовать и принадлежать UID/GID 1000:1000. Только frontend публикует
|
||||
`127.0.0.1:8080`; серверный Caddy направляет туда весь домен. Backend port
|
||||
остаётся внутренним, migration service использует тот же backend image.
|
||||
|
||||
Полная процедура установки, независимых обновлений, stopped-backend backup
|
||||
и explicit restore — [документация](https://git.personal.ksv741.ru/WealthLedger/docs),
|
||||
страница `architecture/deployment.md`.
|
||||
Перед backend update обязательны остановка, backup и успешная migration.
|
||||
Image rollback не восстанавливает старую базу. Публикация component images
|
||||
принадлежит их Gitea workflows; root CI остаётся только commitlint.
|
||||
|
||||
## Подготовка и запуск
|
||||
|
||||
Нужны nvm и Node из `.nvmrc` каждого npm-repo (сейчас 24.21.0, npm 11.19).
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
# Requires Compose >= 2.24.4 for !override. Always use a separate project name.
|
||||
name: wealthledger-dev
|
||||
|
||||
x-development-backend: &development-backend
|
||||
image: wealthledger-backend:development
|
||||
pull_policy: build
|
||||
build:
|
||||
context: ./backend
|
||||
target: development
|
||||
read_only: false
|
||||
environment:
|
||||
NODE_ENV: development
|
||||
volumes: !override
|
||||
- development-data:/data
|
||||
|
||||
services:
|
||||
migration:
|
||||
<<: *development-backend
|
||||
|
||||
backend:
|
||||
<<: *development-backend
|
||||
healthcheck:
|
||||
test: [CMD, node, -e, 'fetch("http://127.0.0.1:3000/api/v1/auth/me").then(async r=>{await r.arrayBuffer();process.exit(r.status===401?0:1)}).catch(()=>process.exit(1))']
|
||||
interval: 10s
|
||||
timeout: 3s
|
||||
start_period: 20s
|
||||
retries: 6
|
||||
volumes: !override
|
||||
- development-data:/data
|
||||
- ./backend/src:/app/src:ro
|
||||
|
||||
frontend:
|
||||
image: wealthledger-frontend:development
|
||||
pull_policy: build
|
||||
build:
|
||||
context: ./frontend
|
||||
target: development
|
||||
read_only: false
|
||||
volumes:
|
||||
- ./frontend/src:/app/src:ro
|
||||
- ./frontend/public:/app/public:ro
|
||||
environment:
|
||||
VITE_API_BASE_URL: ''
|
||||
API_PROXY_TARGET: http://backend:3000
|
||||
healthcheck:
|
||||
test: [CMD, node, -e, 'fetch("http://127.0.0.1:8080/").then(async r=>{await r.arrayBuffer();process.exit(r.ok?0:1)}).catch(()=>process.exit(1))']
|
||||
interval: 10s
|
||||
timeout: 3s
|
||||
start_period: 10s
|
||||
retries: 6
|
||||
|
||||
volumes:
|
||||
development-data:
|
||||
@@ -0,0 +1,51 @@
|
||||
name: wealthledger
|
||||
|
||||
x-backend: &backend
|
||||
image: ${BACKEND_IMAGE:?Set versioned backend image}
|
||||
environment:
|
||||
NODE_ENV: production
|
||||
PORT: '3000'
|
||||
DATABASE_URL: file:/data/wealthledger.db
|
||||
FRONTEND_ORIGIN: ${FRONTEND_ORIGIN:?Set browser-visible origin}
|
||||
JWT_SECRET: ${JWT_SECRET:?Set persistent JWT secret}
|
||||
TOKEN_ENCRYPTION_KEY: ${TOKEN_ENCRYPTION_KEY:?Set persistent encryption key}
|
||||
LOG_LEVEL: ${LOG_LEVEL:-info}
|
||||
volumes:
|
||||
- type: bind
|
||||
source: ${DATA_DIRECTORY:?Set persistent absolute host data directory}
|
||||
target: /data
|
||||
bind:
|
||||
create_host_path: false
|
||||
read_only: true
|
||||
init: true
|
||||
security_opt: [no-new-privileges:true]
|
||||
cap_drop: [ALL]
|
||||
|
||||
services:
|
||||
migration:
|
||||
<<: *backend
|
||||
command: [node, node_modules/prisma/build/index.js, migrate, deploy]
|
||||
restart: 'no'
|
||||
healthcheck:
|
||||
disable: true
|
||||
|
||||
backend:
|
||||
<<: *backend
|
||||
scale: 1
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
migration:
|
||||
condition: service_completed_successfully
|
||||
|
||||
frontend:
|
||||
image: ${FRONTEND_IMAGE:?Set versioned frontend image}
|
||||
ports:
|
||||
- '127.0.0.1:${FRONTEND_PORT:-8080}:8080'
|
||||
read_only: true
|
||||
tmpfs: [/tmp]
|
||||
security_opt: [no-new-privileges:true]
|
||||
cap_drop: [ALL]
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
backend:
|
||||
condition: service_healthy
|
||||
Reference in New Issue
Block a user