fix: add Dockerfiles and fix docker-compose build configuration
- Add shared Dockerfile.service for all 7 NestJS microservices using multi-stage build with pnpm workspace support - Add Dockerfile for web-admin (Next.js standalone output) - Add .dockerignore files for root and web-admin - Fix docker-compose.yml: use monorepo root as build context with SERVICE_NAME build arg instead of per-service Dockerfiles - Fix postgres/redis missing network config (services couldn't reach them) - Use .env variables for DB credentials instead of hardcoded values - Add JWT_REFRESH_SECRET and REDIS_URL to services that were missing them - Add DB init script volume mount for postgres - Remove deprecated version: '3.8' from all compose files - Add output: 'standalone' to next.config.js for optimized Docker builds Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
8116f17fd0
commit
9120f4927e
|
|
@ -0,0 +1,46 @@
|
|||
node_modules
|
||||
.next
|
||||
dist
|
||||
build
|
||||
out
|
||||
coverage
|
||||
.turbo
|
||||
.git
|
||||
.gitignore
|
||||
.claude
|
||||
.vscode
|
||||
.idea
|
||||
|
||||
# Flutter (not needed for backend builds)
|
||||
it0_app
|
||||
|
||||
# Docker
|
||||
deploy
|
||||
docker-compose*.yml
|
||||
Dockerfile*
|
||||
.dockerignore
|
||||
|
||||
# Docs
|
||||
docs
|
||||
*.md
|
||||
|
||||
# Environment
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
|
||||
# Models
|
||||
models
|
||||
|
||||
# Python cache
|
||||
__pycache__
|
||||
*.pyc
|
||||
venv
|
||||
.venv
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
# Shared multi-stage Dockerfile for all NestJS microservices
|
||||
# Usage: docker build --build-arg SERVICE_NAME=auth-service --build-arg SERVICE_PORT=3001 -f Dockerfile.service .
|
||||
|
||||
# ===== Build Stage =====
|
||||
FROM node:18-alpine AS builder
|
||||
|
||||
RUN corepack enable
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy workspace configuration and lockfile (for dependency caching)
|
||||
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml turbo.json tsconfig.base.json ./
|
||||
|
||||
# Copy all package.json files first (Docker layer cache: deps reinstall only when these change)
|
||||
COPY packages/shared/common/package.json packages/shared/common/
|
||||
COPY packages/shared/database/package.json packages/shared/database/
|
||||
COPY packages/shared/events/package.json packages/shared/events/
|
||||
COPY packages/shared/proto/package.json packages/shared/proto/
|
||||
COPY packages/shared/testing/package.json packages/shared/testing/
|
||||
COPY packages/services/auth-service/package.json packages/services/auth-service/
|
||||
COPY packages/services/agent-service/package.json packages/services/agent-service/
|
||||
COPY packages/services/ops-service/package.json packages/services/ops-service/
|
||||
COPY packages/services/inventory-service/package.json packages/services/inventory-service/
|
||||
COPY packages/services/monitor-service/package.json packages/services/monitor-service/
|
||||
COPY packages/services/comm-service/package.json packages/services/comm-service/
|
||||
COPY packages/services/audit-service/package.json packages/services/audit-service/
|
||||
|
||||
# Install all dependencies (cached unless package.json changes)
|
||||
RUN pnpm install --frozen-lockfile
|
||||
|
||||
# Copy source code and tsconfig files
|
||||
COPY packages/shared/ packages/shared/
|
||||
COPY packages/services/ packages/services/
|
||||
|
||||
# Build all shared libraries + target service
|
||||
ARG SERVICE_NAME
|
||||
RUN pnpm turbo build --filter='./packages/shared/*' --filter=@it0/${SERVICE_NAME}
|
||||
|
||||
# ===== Production Stage =====
|
||||
FROM node:18-alpine
|
||||
|
||||
RUN corepack enable
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy workspace config and all package.jsons (required for pnpm workspace resolution)
|
||||
COPY --from=builder /app/package.json /app/pnpm-lock.yaml /app/pnpm-workspace.yaml ./
|
||||
COPY --from=builder /app/packages/shared/common/package.json packages/shared/common/
|
||||
COPY --from=builder /app/packages/shared/database/package.json packages/shared/database/
|
||||
COPY --from=builder /app/packages/shared/events/package.json packages/shared/events/
|
||||
COPY --from=builder /app/packages/shared/proto/package.json packages/shared/proto/
|
||||
COPY --from=builder /app/packages/shared/testing/package.json packages/shared/testing/
|
||||
COPY --from=builder /app/packages/services/auth-service/package.json packages/services/auth-service/
|
||||
COPY --from=builder /app/packages/services/agent-service/package.json packages/services/agent-service/
|
||||
COPY --from=builder /app/packages/services/ops-service/package.json packages/services/ops-service/
|
||||
COPY --from=builder /app/packages/services/inventory-service/package.json packages/services/inventory-service/
|
||||
COPY --from=builder /app/packages/services/monitor-service/package.json packages/services/monitor-service/
|
||||
COPY --from=builder /app/packages/services/comm-service/package.json packages/services/comm-service/
|
||||
COPY --from=builder /app/packages/services/audit-service/package.json packages/services/audit-service/
|
||||
|
||||
# Install production dependencies only
|
||||
RUN pnpm install --frozen-lockfile --prod
|
||||
|
||||
# Copy built shared libraries (dist/ produced by tsc)
|
||||
COPY --from=builder /app/packages/shared/common/dist packages/shared/common/dist/
|
||||
COPY --from=builder /app/packages/shared/database/dist packages/shared/database/dist/
|
||||
COPY --from=builder /app/packages/shared/events/dist packages/shared/events/dist/
|
||||
COPY --from=builder /app/packages/shared/proto/dist packages/shared/proto/dist/
|
||||
|
||||
# Copy target service build output
|
||||
ARG SERVICE_NAME
|
||||
COPY --from=builder /app/packages/services/${SERVICE_NAME}/dist packages/services/${SERVICE_NAME}/dist/
|
||||
|
||||
WORKDIR /app/packages/services/${SERVICE_NAME}
|
||||
|
||||
ARG SERVICE_PORT=3000
|
||||
EXPOSE ${SERVICE_PORT}
|
||||
|
||||
CMD ["node", "dist/main"]
|
||||
|
|
@ -1,5 +1,3 @@
|
|||
version: '3.8'
|
||||
|
||||
# SSL overlay — adds Nginx reverse proxy + Certbot for Let's Encrypt
|
||||
# Usage: docker compose -f docker-compose.yml -f docker-compose.ssl.yml up -d
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
version: '3.8'
|
||||
|
||||
# GPU-enabled voice service overlay
|
||||
# Usage: docker compose -f docker-compose.yml -f docker-compose.voice.yml up voice-service
|
||||
|
||||
|
|
|
|||
|
|
@ -1,22 +1,23 @@
|
|||
version: '3.8'
|
||||
|
||||
services:
|
||||
# ===== Infrastructure =====
|
||||
postgres:
|
||||
image: postgres:16-alpine
|
||||
environment:
|
||||
POSTGRES_USER: it0
|
||||
POSTGRES_PASSWORD: it0_dev
|
||||
POSTGRES_DB: it0
|
||||
POSTGRES_USER: ${POSTGRES_USER:-it0}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-it0_dev}
|
||||
POSTGRES_DB: ${POSTGRES_DB:-it0}
|
||||
ports:
|
||||
- "5432:5432"
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
- ./scripts/init-databases.sh:/docker-entrypoint-initdb.d/init-databases.sh
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U it0"]
|
||||
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-it0}"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
networks:
|
||||
- it0-network
|
||||
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
|
|
@ -27,22 +28,31 @@ services:
|
|||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
networks:
|
||||
- it0-network
|
||||
|
||||
# ===== API Gateway =====
|
||||
api-gateway:
|
||||
build: ../../packages/gateway
|
||||
build:
|
||||
context: ../../packages/gateway
|
||||
ports:
|
||||
- "8000:8000"
|
||||
- "8001:8001"
|
||||
depends_on:
|
||||
- auth-service
|
||||
- agent-service
|
||||
- ops-service
|
||||
- inventory-service
|
||||
- monitor-service
|
||||
- comm-service
|
||||
- audit-service
|
||||
- redis
|
||||
auth-service:
|
||||
condition: service_started
|
||||
agent-service:
|
||||
condition: service_started
|
||||
ops-service:
|
||||
condition: service_started
|
||||
inventory-service:
|
||||
condition: service_started
|
||||
monitor-service:
|
||||
condition: service_started
|
||||
comm-service:
|
||||
condition: service_started
|
||||
audit-service:
|
||||
condition: service_started
|
||||
healthcheck:
|
||||
test: ["CMD", "kong", "health"]
|
||||
interval: 10s
|
||||
|
|
@ -51,19 +61,25 @@ services:
|
|||
networks:
|
||||
- it0-network
|
||||
|
||||
# ===== Backend Services =====
|
||||
# ===== Backend Services (shared Dockerfile.service) =====
|
||||
auth-service:
|
||||
build: ../../packages/services/auth-service
|
||||
build:
|
||||
context: ../..
|
||||
dockerfile: Dockerfile.service
|
||||
args:
|
||||
SERVICE_NAME: auth-service
|
||||
SERVICE_PORT: 3001
|
||||
ports:
|
||||
- "3001:3001"
|
||||
environment:
|
||||
- DB_HOST=postgres
|
||||
- DB_PORT=5432
|
||||
- DB_USERNAME=it0
|
||||
- DB_PASSWORD=it0_dev
|
||||
- DB_DATABASE=it0
|
||||
- DB_USERNAME=${POSTGRES_USER:-it0}
|
||||
- DB_PASSWORD=${POSTGRES_PASSWORD:-it0_dev}
|
||||
- DB_DATABASE=${POSTGRES_DB:-it0}
|
||||
- REDIS_URL=redis://redis:6379
|
||||
- JWT_SECRET=${JWT_SECRET:-dev-jwt-secret}
|
||||
- JWT_REFRESH_SECRET=${JWT_REFRESH_SECRET:-dev-jwt-refresh-secret}
|
||||
- AUTH_SERVICE_PORT=3001
|
||||
depends_on:
|
||||
postgres:
|
||||
|
|
@ -74,15 +90,20 @@ services:
|
|||
- it0-network
|
||||
|
||||
agent-service:
|
||||
build: ../../packages/services/agent-service
|
||||
build:
|
||||
context: ../..
|
||||
dockerfile: Dockerfile.service
|
||||
args:
|
||||
SERVICE_NAME: agent-service
|
||||
SERVICE_PORT: 3002
|
||||
ports:
|
||||
- "3002:3002"
|
||||
environment:
|
||||
- DB_HOST=postgres
|
||||
- DB_PORT=5432
|
||||
- DB_USERNAME=it0
|
||||
- DB_PASSWORD=it0_dev
|
||||
- DB_DATABASE=it0
|
||||
- DB_USERNAME=${POSTGRES_USER:-it0}
|
||||
- DB_PASSWORD=${POSTGRES_PASSWORD:-it0_dev}
|
||||
- DB_DATABASE=${POSTGRES_DB:-it0}
|
||||
- REDIS_URL=redis://redis:6379
|
||||
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
|
||||
- AGENT_ENGINE_TYPE=claude_code_cli
|
||||
|
|
@ -96,15 +117,20 @@ services:
|
|||
- it0-network
|
||||
|
||||
ops-service:
|
||||
build: ../../packages/services/ops-service
|
||||
build:
|
||||
context: ../..
|
||||
dockerfile: Dockerfile.service
|
||||
args:
|
||||
SERVICE_NAME: ops-service
|
||||
SERVICE_PORT: 3003
|
||||
ports:
|
||||
- "3003:3003"
|
||||
environment:
|
||||
- DB_HOST=postgres
|
||||
- DB_PORT=5432
|
||||
- DB_USERNAME=it0
|
||||
- DB_PASSWORD=it0_dev
|
||||
- DB_DATABASE=it0
|
||||
- DB_USERNAME=${POSTGRES_USER:-it0}
|
||||
- DB_PASSWORD=${POSTGRES_PASSWORD:-it0_dev}
|
||||
- DB_DATABASE=${POSTGRES_DB:-it0}
|
||||
- REDIS_URL=redis://redis:6379
|
||||
- OPS_SERVICE_PORT=3003
|
||||
depends_on:
|
||||
|
|
@ -116,15 +142,21 @@ services:
|
|||
- it0-network
|
||||
|
||||
inventory-service:
|
||||
build: ../../packages/services/inventory-service
|
||||
build:
|
||||
context: ../..
|
||||
dockerfile: Dockerfile.service
|
||||
args:
|
||||
SERVICE_NAME: inventory-service
|
||||
SERVICE_PORT: 3004
|
||||
ports:
|
||||
- "3004:3004"
|
||||
environment:
|
||||
- DB_HOST=postgres
|
||||
- DB_PORT=5432
|
||||
- DB_USERNAME=it0
|
||||
- DB_PASSWORD=it0_dev
|
||||
- DB_DATABASE=it0
|
||||
- DB_USERNAME=${POSTGRES_USER:-it0}
|
||||
- DB_PASSWORD=${POSTGRES_PASSWORD:-it0_dev}
|
||||
- DB_DATABASE=${POSTGRES_DB:-it0}
|
||||
- REDIS_URL=redis://redis:6379
|
||||
- VAULT_MASTER_KEY=${VAULT_MASTER_KEY:-dev-vault-key}
|
||||
- INVENTORY_SERVICE_PORT=3004
|
||||
depends_on:
|
||||
|
|
@ -134,15 +166,20 @@ services:
|
|||
- it0-network
|
||||
|
||||
monitor-service:
|
||||
build: ../../packages/services/monitor-service
|
||||
build:
|
||||
context: ../..
|
||||
dockerfile: Dockerfile.service
|
||||
args:
|
||||
SERVICE_NAME: monitor-service
|
||||
SERVICE_PORT: 3005
|
||||
ports:
|
||||
- "3005:3005"
|
||||
environment:
|
||||
- DB_HOST=postgres
|
||||
- DB_PORT=5432
|
||||
- DB_USERNAME=it0
|
||||
- DB_PASSWORD=it0_dev
|
||||
- DB_DATABASE=it0
|
||||
- DB_USERNAME=${POSTGRES_USER:-it0}
|
||||
- DB_PASSWORD=${POSTGRES_PASSWORD:-it0_dev}
|
||||
- DB_DATABASE=${POSTGRES_DB:-it0}
|
||||
- REDIS_URL=redis://redis:6379
|
||||
- MONITOR_SERVICE_PORT=3005
|
||||
depends_on:
|
||||
|
|
@ -152,15 +189,20 @@ services:
|
|||
- it0-network
|
||||
|
||||
comm-service:
|
||||
build: ../../packages/services/comm-service
|
||||
build:
|
||||
context: ../..
|
||||
dockerfile: Dockerfile.service
|
||||
args:
|
||||
SERVICE_NAME: comm-service
|
||||
SERVICE_PORT: 3006
|
||||
ports:
|
||||
- "3006:3006"
|
||||
environment:
|
||||
- DB_HOST=postgres
|
||||
- DB_PORT=5432
|
||||
- DB_USERNAME=it0
|
||||
- DB_PASSWORD=it0_dev
|
||||
- DB_DATABASE=it0
|
||||
- DB_USERNAME=${POSTGRES_USER:-it0}
|
||||
- DB_PASSWORD=${POSTGRES_PASSWORD:-it0_dev}
|
||||
- DB_DATABASE=${POSTGRES_DB:-it0}
|
||||
- REDIS_URL=redis://redis:6379
|
||||
- TWILIO_ACCOUNT_SID=${TWILIO_ACCOUNT_SID}
|
||||
- TWILIO_AUTH_TOKEN=${TWILIO_AUTH_TOKEN}
|
||||
|
|
@ -175,15 +217,21 @@ services:
|
|||
- it0-network
|
||||
|
||||
audit-service:
|
||||
build: ../../packages/services/audit-service
|
||||
build:
|
||||
context: ../..
|
||||
dockerfile: Dockerfile.service
|
||||
args:
|
||||
SERVICE_NAME: audit-service
|
||||
SERVICE_PORT: 3007
|
||||
ports:
|
||||
- "3007:3007"
|
||||
environment:
|
||||
- DB_HOST=postgres
|
||||
- DB_PORT=5432
|
||||
- DB_USERNAME=it0
|
||||
- DB_PASSWORD=it0_dev
|
||||
- DB_DATABASE=it0
|
||||
- DB_USERNAME=${POSTGRES_USER:-it0}
|
||||
- DB_PASSWORD=${POSTGRES_PASSWORD:-it0_dev}
|
||||
- DB_DATABASE=${POSTGRES_DB:-it0}
|
||||
- REDIS_URL=redis://redis:6379
|
||||
- AUDIT_SERVICE_PORT=3007
|
||||
depends_on:
|
||||
postgres:
|
||||
|
|
@ -192,15 +240,16 @@ services:
|
|||
- it0-network
|
||||
|
||||
voice-service:
|
||||
build: ../../packages/services/voice-service
|
||||
build:
|
||||
context: ../../packages/services/voice-service
|
||||
ports:
|
||||
- "3008:3008"
|
||||
environment:
|
||||
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
|
||||
- AGENT_SERVICE_URL=http://agent-service:3002
|
||||
- WHISPER_MODEL=large-v3
|
||||
- KOKORO_MODEL=kokoro-82m
|
||||
- DEVICE=cpu
|
||||
- WHISPER_MODEL=${WHISPER_MODEL:-large-v3}
|
||||
- KOKORO_MODEL=${KOKORO_MODEL:-kokoro-82m}
|
||||
- DEVICE=${VOICE_DEVICE:-cpu}
|
||||
depends_on:
|
||||
- agent-service
|
||||
networks:
|
||||
|
|
@ -208,7 +257,8 @@ services:
|
|||
|
||||
# ===== Frontend =====
|
||||
web-admin:
|
||||
build: ../../it0-web-admin
|
||||
build:
|
||||
context: ../../it0-web-admin
|
||||
ports:
|
||||
- "3000:3000"
|
||||
environment:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
node_modules
|
||||
.next
|
||||
out
|
||||
coverage
|
||||
.git
|
||||
.gitignore
|
||||
.vscode
|
||||
.idea
|
||||
*.md
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
*.log
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
# Next.js standalone production Dockerfile
|
||||
FROM node:18-alpine AS builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY package.json package-lock.json ./
|
||||
RUN npm ci
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN npm run build
|
||||
|
||||
# ===== Production =====
|
||||
FROM node:18-alpine
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
ENV NODE_ENV=production
|
||||
|
||||
# Copy standalone server output (includes node_modules subset)
|
||||
COPY --from=builder /app/.next/standalone ./
|
||||
COPY --from=builder /app/.next/static ./.next/static
|
||||
COPY --from=builder /app/public ./public
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
CMD ["node", "server.js"]
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
output: 'standalone',
|
||||
experimental: {
|
||||
serverActions: true,
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in New Issue