build: docker compose (app + postgres) with healthchecks and .env
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BwxdSt4reTm7Dj1oxRvpP3
This commit is contained in:
@@ -0,0 +1,11 @@
|
|||||||
|
# PostgreSQL
|
||||||
|
POSTGRES_USER=dnsar
|
||||||
|
POSTGRES_PASSWORD=change-me-strong-password
|
||||||
|
POSTGRES_DB=dnsar
|
||||||
|
|
||||||
|
# Порт публикации приложения на хосте
|
||||||
|
APP_PORT=8080
|
||||||
|
|
||||||
|
# Ключ шифрования секретов провайдеров/каналов — РОВНО 32 байта в base64.
|
||||||
|
# Сгенерировать: openssl rand -base64 32
|
||||||
|
DNS_AR_ENC_KEY=
|
||||||
@@ -14,3 +14,16 @@ web:
|
|||||||
|
|
||||||
.PHONY: build-all
|
.PHONY: build-all
|
||||||
build-all: web build
|
build-all: web build
|
||||||
|
|
||||||
|
.PHONY: docker-build docker-up docker-down docker-logs
|
||||||
|
docker-build:
|
||||||
|
docker build -t dns-autoresolver:local .
|
||||||
|
|
||||||
|
docker-up:
|
||||||
|
docker compose up -d --build
|
||||||
|
|
||||||
|
docker-down:
|
||||||
|
docker compose down
|
||||||
|
|
||||||
|
docker-logs:
|
||||||
|
docker compose logs -f app
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
# DNS Autoresolver
|
||||||
|
|
||||||
|
Утилита автонастройки и проверки DNS-зон: multi-tenant сервис, который сверяет
|
||||||
|
фактическое состояние зоны у провайдера (Selectel DNS API v2) с шаблоном
|
||||||
|
записей, показывает диф и применяет изменения только вручную — никакого
|
||||||
|
автоматического apply без подтверждения оператора.
|
||||||
|
|
||||||
|
## Возможности
|
||||||
|
|
||||||
|
- **Multi-tenant**: проекты, аккаунты провайдера, домены — с авторизацией
|
||||||
|
(регистрация/логин, сессии).
|
||||||
|
- **Провайдер Selectel**: чтение зон/RRSet, диф против шаблона, ручной apply.
|
||||||
|
- **Шаблоны записей**: неймспейс-независимая модель `Record`, движок диффа
|
||||||
|
шаблон ↔ зона.
|
||||||
|
- **Диф + ручной apply**: изменения показываются перед применением, apply —
|
||||||
|
явное действие оператора.
|
||||||
|
- **Расписание проверок**: планировщик периодически гоняет read-only
|
||||||
|
check+notify (без Apply), пишет историю проверок и статус drift.
|
||||||
|
- **Уведомления**: каналы Telegram и Webhook, per-channel статус доставки.
|
||||||
|
- **Метрики**: Prometheus `/metrics` (публичный, без auth, только агрегаты).
|
||||||
|
- **Health-check**: `/healthz` — liveness-проба, используется как
|
||||||
|
Docker `HEALTHCHECK` через встроенный CLI-режим `app -healthcheck`.
|
||||||
|
|
||||||
|
## Стек
|
||||||
|
|
||||||
|
Go 1.26 (statically-linked бинарь, SPA встроена через `embed`), React +
|
||||||
|
Vite (SPA), PostgreSQL 17, Prometheus client, distroless/static-debian12
|
||||||
|
рантайм-образ.
|
||||||
|
|
||||||
|
## Запуск в Docker
|
||||||
|
|
||||||
|
Требуется Docker Engine + Docker Compose v2.
|
||||||
|
|
||||||
|
1. Скопировать пример конфигурации:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp .env.example .env
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Сгенерировать ключ шифрования секретов (провайдеров/каналов) — ровно
|
||||||
|
32 байта в base64 — и вписать его в `.env` как `DNS_AR_ENC_KEY`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
openssl rand -base64 32
|
||||||
|
```
|
||||||
|
|
||||||
|
Также задать `POSTGRES_PASSWORD` (без дефолта — сервис не поднимется без
|
||||||
|
явного пароля).
|
||||||
|
|
||||||
|
3. Поднять стек (postgres + app), сборка образа приложения — на лету:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose up -d --build
|
||||||
|
# или: make docker-up
|
||||||
|
```
|
||||||
|
|
||||||
|
`app` стартует только после того, как `postgres` станет healthy;
|
||||||
|
миграции схемы БД приложение накатывает само при старте.
|
||||||
|
|
||||||
|
4. Открыть UI: http://localhost:8080
|
||||||
|
|
||||||
|
- Метрики (Prometheus): http://localhost:8080/metrics
|
||||||
|
- Health-check: http://localhost:8080/healthz
|
||||||
|
|
||||||
|
Остановить стек: `docker compose down` (или `make docker-down`).
|
||||||
|
Логи приложения: `docker compose logs -f app` (или `make docker-logs`).
|
||||||
|
|
||||||
|
### Переменные окружения (`.env`)
|
||||||
|
|
||||||
|
| Переменная | Назначение | По умолчанию |
|
||||||
|
|---------------------|----------------------------------------------------------|--------------|
|
||||||
|
| `POSTGRES_USER` | пользователь PostgreSQL | `dnsar` |
|
||||||
|
| `POSTGRES_PASSWORD` | пароль PostgreSQL — **обязателен**, без дефолта | — |
|
||||||
|
| `POSTGRES_DB` | имя БД | `dnsar` |
|
||||||
|
| `APP_PORT` | порт публикации приложения на хосте | `8080` |
|
||||||
|
| `DNS_AR_ENC_KEY` | ключ шифрования секретов, base64 → ровно 32 байта — **обязателен** | — |
|
||||||
|
|
||||||
|
Секреты передаются только через переменные окружения, никогда — в образ,
|
||||||
|
логи или git.
|
||||||
|
|
||||||
|
## Локальная разработка (без Docker)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make build # go build ./...
|
||||||
|
make test # go test ./...
|
||||||
|
make web # сборка SPA (npm ci && npm run build) в internal/web/dist
|
||||||
|
make build-all # web + build
|
||||||
|
```
|
||||||
|
|
||||||
|
Для запуска бинаря напрямую нужны те же переменные окружения:
|
||||||
|
`DNS_AR_DB_DSN`, `DNS_AR_ENC_KEY` (обязательные), `DNS_AR_LISTEN`
|
||||||
|
(по умолчанию `:8080`).
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
services:
|
||||||
|
postgres:
|
||||||
|
image: postgres:17-alpine
|
||||||
|
environment:
|
||||||
|
POSTGRES_USER: ${POSTGRES_USER:-dnsar}
|
||||||
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set in .env}
|
||||||
|
POSTGRES_DB: ${POSTGRES_DB:-dnsar}
|
||||||
|
volumes:
|
||||||
|
- pgdata:/var/lib/postgresql/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-dnsar} -d ${POSTGRES_DB:-dnsar}"]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 3s
|
||||||
|
retries: 10
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
app:
|
||||||
|
build: .
|
||||||
|
depends_on:
|
||||||
|
postgres:
|
||||||
|
condition: service_healthy
|
||||||
|
environment:
|
||||||
|
DNS_AR_DB_DSN: postgres://${POSTGRES_USER:-dnsar}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-dnsar}?sslmode=disable
|
||||||
|
DNS_AR_ENC_KEY: ${DNS_AR_ENC_KEY:?base64 32 bytes, see .env.example}
|
||||||
|
DNS_AR_LISTEN: ":8080"
|
||||||
|
ports:
|
||||||
|
- "${APP_PORT:-8080}:8080"
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "/app", "-healthcheck"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 4s
|
||||||
|
retries: 5
|
||||||
|
start_period: 15s
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
pgdata:
|
||||||
Reference in New Issue
Block a user