Docker
Руководство по работе с Docker для Integ API.
Unified Docker Image
Проект использует единый Docker образ для всех окружений (local/dev/prod). Секреты инжектятся в runtime через Doppler.
Dockerfile
dockerfile
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:20-alpine
WORKDIR /app
# Doppler CLI для runtime injection
RUN apk add --no-cache curl && \
curl -sLf https://cli.doppler.com/install.sh | sh && \
apk del curl
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./package.json
EXPOSE 3000
CMD ["sh", "-c", "doppler run --config ${DOPPLER_CONFIG:-local} -- node ./dist/main.js"]Преимущества
- Один образ — билдится один раз, запускается где угодно
- Безопасность — секреты не в образе, инжектятся в runtime
- Гибкость — переключение окружения через переменную
DOPPLER_CONFIG - Консистентность — идентичный образ в CI/CD и локально
Запуск контейнера
С Doppler (рекомендуется)
bash
# Pull образ
docker pull ghcr.io/happ-ai/integ-api:dev
# Запуск с Doppler
docker run -d \
--name integ-api \
-p 3000:3000 \
-e DOPPLER_TOKEN=dp.st.xxxx \
-e DOPPLER_CONFIG=local \
ghcr.io/happ-ai/integ-api:devС переменными окружения напрямую
Если не хотите использовать Doppler, можно передать переменные напрямую:
bash
docker run -d \
--name integ-api \
-p 3000:3000 \
-e POSTGRES_HOST=localhost \
-e POSTGRES_PORT=5432 \
-e POSTGRES_USERNAME=user \
-e POSTGRES_PASSWORD=password \
-e POSTGRES_NAME=integ-db \
-e JWT_SECRET=your-secret \
ghcr.io/happ-ai/integ-api:dev \
node ./dist/main.jsВАЖНО
При запуске без Doppler нужно переопределить CMD, убрав doppler run.
Docker Compose
Для integ-core (полный стек)
yaml
services:
postgres:
image: postgres:16-alpine
ports:
- "5432:5432"
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
POSTGRES_DB: integ-db
volumes:
- postgres-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user -d integ-db"]
interval: 5s
timeout: 5s
retries: 5
networks:
- integ-network
happ-integ-api:
image: ghcr.io/happ-ai/integ-api:${IMAGE_TAG:-dev}
ports:
- "3000:3000"
environment:
- DOPPLER_TOKEN=${DOPPLER_TOKEN_API}
- DOPPLER_CONFIG=${DOPPLER_CONFIG:-local}
# Override для Docker networking
- POSTGRES_HOST=postgres
- INNGEST_URL=http://inngest:8288
depends_on:
postgres:
condition: service_healthy
networks:
- integ-network
networks:
integ-network:
driver: bridge
volumes:
postgres-data:.env файл
env
DOPPLER_TOKEN_API=dp.st.xxxx
DOPPLER_CONFIG=local
IMAGE_TAG=devЗапуск
bash
# Pull и запуск
docker compose pull
docker compose up -d
# Логи
docker compose logs -f happ-integ-api
# Остановка
docker compose downЛокальная разработка
Только PostgreSQL
Для локальной разработки без Docker образа API:
bash
# Запуск только БД
npm run docker:up
# Остановка
npm run docker:downС Doppler локально
bash
# Запуск приложения с Doppler
doppler run --config local -- npm start
# Или production build
doppler run --config local -- npm run start:prodСборка образа локально
bash
# Сборка
docker build -t integ-api:local .
# Запуск с Doppler
docker run -p 3000:3000 \
-e DOPPLER_TOKEN=dp.st.xxxx \
-e DOPPLER_CONFIG=local \
integ-api:local
# Запуск без Doppler (с env переменными)
docker run -p 3000:3000 \
-e POSTGRES_HOST=host.docker.internal \
-e POSTGRES_PORT=5432 \
-e POSTGRES_USERNAME=user \
-e POSTGRES_PASSWORD=password \
-e POSTGRES_NAME=integ-db \
integ-api:local \
node ./dist/main.jsПеременные окружения
Полный список переменных для runtime:
| Переменная | Описание | Default |
|---|---|---|
PORT | Порт сервера | 3000 |
MODE | Режим (local/dev/prod) | local |
POSTGRES_HOST | Хост БД | - |
POSTGRES_PORT | Порт БД | 5432 |
POSTGRES_USERNAME | Пользователь БД | - |
POSTGRES_PASSWORD | Пароль БД | - |
POSTGRES_NAME | Имя БД | - |
POSTGRES_CERTIFICATE | Использовать SSL | - |
POSTGRES_CERTIFICATE_BASE64 | CA сертификат в base64 | - |
JWT_SECRET | Секрет для JWT | - |
CRYPTO_KEY | Ключ шифрования | - |
CRYPTO_SALT | Соль шифрования | - |
CLOUDFLARE_ACCOUNT_ID | Cloudflare Account ID | - |
CLOUDFLARE_WORKERS_API_TOKEN | Cloudflare API Token | - |
CLOUDFLARE_INTEG_DB_ID | D1 Database ID | - |
CLOUDFLARE_INTEG_KV_ID | KV Namespace ID | - |
INNGEST_URL | URL Inngest | http://localhost:8288 |
CI/CD
GitHub Actions
Образ билдится и пушится автоматически:
- dev branch →
ghcr.io/happ-ai/integ-api:dev - main branch →
ghcr.io/happ-ai/integ-api:latest
yaml
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile
push: true
tags: ghcr.io/happ-ai/integ-api:dev
cache-from: type=gha
cache-to: type=gha,mode=maxTIP
Doppler не используется на этапе build. Секреты инжектятся только при запуске контейнера.
Health Checks
bash
# Проверка health endpoint
curl http://localhost:3000/health
# Docker health check
docker inspect --format='{{.State.Health.Status}}' integ-apiTroubleshooting
Контейнер не стартует
bash
# Проверка логов
docker logs integ-api
# Проверка Doppler
docker exec integ-api doppler secrets --only-namesОшибка подключения к БД
bash
# Проверка переменных
docker exec integ-api env | grep POSTGRES
# Проверка сети
docker exec integ-api ping postgresDoppler не работает
bash
# Проверка токена
docker exec integ-api doppler whoami
# Проверка конфига
docker exec integ-api doppler configsBest Practices
✅ DO:
- Используйте Doppler для управления секретами
- Используйте health checks
- Используйте named volumes для данных
- Используйте networks для изоляции
❌ DON'T:
- Не храните секреты в образе
- Не используйте
latesttag в production - Не запускайте как root в production
Следующие шаги
- Окружения - Настройка переменных окружения
- Deployment Overview - Общий обзор деплоя