The servers bind IPv4 (0.0.0.0) only. busybox wget resolves `localhost` to ::1 first and does not fall back to IPv4, so the healthcheck failed with "connection refused" and the container showed as unhealthy while serving fine. Verified on the production api container. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
36 lines
1.4 KiB
Docker
36 lines
1.4 KiB
Docker
# syntax=docker/dockerfile:1
|
|
# Control plane (Fastify). Runs via tsx — workspace packages are consumed as raw
|
|
# TypeScript, so there is no separate compile step (same model as runner-template).
|
|
# Build context must be the repo root: docker build -f apps/api/Dockerfile .
|
|
|
|
FROM node:20-alpine AS base
|
|
RUN corepack enable && corepack prepare pnpm@9.12.0 --activate
|
|
WORKDIR /app
|
|
|
|
# ---- deps: install the whole workspace from the lockfile ----
|
|
FROM base AS deps
|
|
COPY pnpm-lock.yaml pnpm-workspace.yaml package.json ./
|
|
COPY apps/api/package.json apps/api/
|
|
COPY apps/web/package.json apps/web/
|
|
COPY apps/generator/package.json apps/generator/
|
|
COPY apps/runner-template/package.json apps/runner-template/
|
|
COPY packages/auth/package.json packages/auth/
|
|
COPY packages/db/package.json packages/db/
|
|
COPY packages/llm/package.json packages/llm/
|
|
COPY packages/types/package.json packages/types/
|
|
RUN pnpm install --frozen-lockfile
|
|
|
|
# ---- runtime ----
|
|
FROM deps AS runtime
|
|
# docker CLI: the API stops/removes generated MCP containers via the host daemon.
|
|
RUN apk add --no-cache docker-cli
|
|
ENV NODE_ENV=production
|
|
COPY . .
|
|
WORKDIR /app/apps/api
|
|
EXPOSE 4000
|
|
# Use 127.0.0.1, not localhost: the server binds IPv4 only, and busybox wget
|
|
# resolves localhost to ::1 first — which would refuse and fail the check.
|
|
HEALTHCHECK --interval=20s --timeout=4s --start-period=20s --retries=3 \
|
|
CMD wget -qO- http://127.0.0.1:4000/health || exit 1
|
|
CMD ["pnpm", "start"]
|