it0/Dockerfile.service

122 lines
6.3 KiB
Desktop File

# 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/
COPY packages/services/billing-service/package.json packages/services/billing-service/
COPY packages/services/version-service/package.json packages/services/version-service/
COPY packages/services/presence-service/package.json packages/services/presence-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
# Install bash (required by Claude Agent SDK Bash tool) + openssh-client (for SSH to managed servers) + su-exec (for privilege drop)
RUN apk add --no-cache bash openssh-client su-exec openssl
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/
COPY --from=builder /app/packages/services/billing-service/package.json packages/services/billing-service/
COPY --from=builder /app/packages/services/version-service/package.json packages/services/version-service/
COPY --from=builder /app/packages/services/presence-service/package.json packages/services/presence-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/
# Copy SQL migration templates alongside compiled shared code in each service dist
COPY --from=builder /app/packages/shared/database/src/migrations packages/services/${SERVICE_NAME}/dist/shared/database/src/migrations/
# Copy Prisma schema and generate client if this service uses @prisma/client.
# prisma is kept in dependencies so it is available after --prod install.
# NOTE: use /app/node_modules/.bin/prisma (workspace root) — pnpm does not hoist
# binaries into each service's node_modules/.bin in a workspace setup.
ARG SERVICE_NAME
COPY --from=builder /app/packages/services/${SERVICE_NAME}/prisma packages/services/${SERVICE_NAME}/prisma/
RUN if [ -f "packages/services/${SERVICE_NAME}/prisma/schema.prisma" ]; then \
echo "Running prisma generate for ${SERVICE_NAME}..." && \
/app/node_modules/.bin/prisma generate \
--schema /app/packages/services/${SERVICE_NAME}/prisma/schema.prisma && \
echo "Prisma generate completed."; \
else \
echo "No prisma/schema.prisma found skipping prisma generate."; \
fi
WORKDIR /app/packages/services/${SERVICE_NAME}
# Create non-root user for service runtime
RUN adduser -D -h /home/appuser appuser && \
mkdir -p /data/claude-tenants && \
mkdir -p /data/versions/android /data/versions/ios && \
mkdir -p /home/appuser/.ssh && chmod 700 /home/appuser/.ssh && \
chown -R appuser:appuser /app /data/claude-tenants /data/versions /home/appuser/.ssh
# Copy entrypoint script (runs as root to fix SSH key permissions, then drops to appuser)
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ARG SERVICE_PORT=3000
EXPOSE ${SERVICE_PORT}
ENV SERVICE_NAME=${SERVICE_NAME}
ENV NODE_OPTIONS="--experimental-global-webcrypto"
ENV SHELL=/bin/bash
ENTRYPOINT ["/entrypoint.sh"]