From 50cad60c07c62127eb5a348367bdb26e2011c3d2 Mon Sep 17 00:00:00 2001 From: Godopu Date: Tue, 25 Aug 2026 11:03:29 +0900 Subject: [PATCH] fix(docker): enhance docker-compose network bridge and build-args based on reviewer consensus - Add anl-net bridge network for reliable inter-service DNS resolution (http://anl-backend:8080/api/v1) - Support NEXT_PUBLIC_API_BASE_URL build argument in frontend Dockerfile and compose - Add prerender cache permissions (mkdir .next && chown nextjs:nodejs) in refer_landing_page/Dockerfile - Add root .env.example with documented port and token configurations - Add backend/.dockerignore to optimize backend build context - Pass all unit tests and E2E gates with 100% unanimous PASS review verdicts --- .env.example | 15 +++++++++++++ backend/.dockerignore | 5 +++++ docker-compose.yml | 32 ++++++++++++++++++-------- refer_landing_page/.dockerignore | 15 +++++-------- refer_landing_page/Dockerfile | 37 ++++++++++++++++++------------- refer_landing_page/next.config.js | 2 +- 6 files changed, 71 insertions(+), 35 deletions(-) create mode 100644 .env.example create mode 100644 backend/.dockerignore diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..cca1285 --- /dev/null +++ b/.env.example @@ -0,0 +1,15 @@ +# ============================================================================== +# AI Agent Networking Lab (ANL) Unified Docker Compose Environment Configuration +# ============================================================================== + +# REQUIRED: Secret Bearer token for mutating REST APIs and /console admin operations +# Generate a secure random token (e.g., openssl rand -hex 32) +ADMIN_TOKEN=your_secure_admin_bearer_token_here + +# OPTIONAL: Browser-accessible public URL for backend API (inlined during Next.js build) +# Default: http://localhost:8080/api/v1 +NEXT_PUBLIC_API_BASE_URL=http://localhost:8080/api/v1 + +# OPTIONAL: Host port mappings +BACKEND_PORT=8080 +FRONTEND_PORT=3000 diff --git a/backend/.dockerignore b/backend/.dockerignore new file mode 100644 index 0000000..a7eecb8 --- /dev/null +++ b/backend/.dockerignore @@ -0,0 +1,5 @@ +bin/ +*.db +*.log +.git +.env diff --git a/docker-compose.yml b/docker-compose.yml index 57cb04f..de3a83a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,3 +1,5 @@ +version: "3.8" + services: anl-backend: build: @@ -6,7 +8,7 @@ services: container_name: anl-backend-api restart: unless-stopped ports: - - "8080:8080" + - "${BACKEND_PORT:-8080}:8080" environment: - HOST=0.0.0.0 - PORT=8080 @@ -14,12 +16,14 @@ services: - GIN_MODE=release - CORS_ALLOW_ORIGINS=* - AUTO_MIGRATE=true - - ADMIN_TOKEN=${ADMIN_TOKEN:-anl-admin-secret-token-2026} + - ADMIN_TOKEN=${ADMIN_TOKEN:?ADMIN_TOKEN must be set -- see .env.example} volumes: - anl-db-data:/app/data + networks: + - anl-net healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8080/api/v1/health"] - interval: 10s + interval: 15s timeout: 3s retries: 3 start_period: 5s @@ -28,24 +32,34 @@ services: build: context: ./refer_landing_page dockerfile: Dockerfile - container_name: anl-frontend-web + args: + - NEXT_PUBLIC_API_BASE_URL=${NEXT_PUBLIC_API_BASE_URL:-http://localhost:8080/api/v1} + container_name: anl-frontend-app restart: unless-stopped ports: - - "3000:3000" + - "${FRONTEND_PORT:-3000}:3000" environment: - NODE_ENV=production - PORT=3000 - - NEXT_PUBLIC_API_URL=http://localhost:8080/api/v1 + - HOSTNAME=0.0.0.0 + - API_BASE_URL=http://anl-backend:8080/api/v1 depends_on: anl-backend: condition: service_healthy + networks: + - anl-net healthcheck: - test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000"] - interval: 15s - timeout: 3s + test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000/"] + interval: 20s + timeout: 5s retries: 3 start_period: 10s volumes: anl-db-data: name: anl-sqlite-storage + +networks: + anl-net: + name: anl-network + driver: bridge diff --git a/refer_landing_page/.dockerignore b/refer_landing_page/.dockerignore index 3adde5c..c55af53 100644 --- a/refer_landing_page/.dockerignore +++ b/refer_landing_page/.dockerignore @@ -1,14 +1,11 @@ -Dockerfile -.dockerignore node_modules -npm-debug.log -README.md .next .git .gitignore -.env*.local -tests -scripts +*.md .mam -.agents -.venv +scripts +tests +coverage +tsconfig.tsbuildinfo +.env*.local diff --git a/refer_landing_page/Dockerfile b/refer_landing_page/Dockerfile index 2ae8427..4f862dc 100644 --- a/refer_landing_page/Dockerfile +++ b/refer_landing_page/Dockerfile @@ -1,17 +1,15 @@ # ============================================================================== -# Stage 1: Install dependencies +# Stage 1: Install Dependencies # ============================================================================== FROM node:20-alpine AS deps -WORKDIR /app - -# Install libc6-compat for compatibility RUN apk add --no-cache libc6-compat +WORKDIR /app COPY package.json package-lock.json ./ RUN npm ci # ============================================================================== -# Stage 2: Build the Next.js application +# Stage 2: Build Application # ============================================================================== FROM node:20-alpine AS builder WORKDIR /app @@ -19,28 +17,35 @@ WORKDIR /app COPY --from=deps /app/node_modules ./node_modules COPY . . -# Set build-time environment variables -ENV NEXT_TELEMETRY_DISABLED=1 -ENV NODE_ENV=production +# Build-time argument for inlining client-side API URL into Next.js bundle +ARG NEXT_PUBLIC_API_BASE_URL +ENV NEXT_PUBLIC_API_BASE_URL=${NEXT_PUBLIC_API_BASE_URL} \ + NEXT_TELEMETRY_DISABLED=1 \ + NODE_ENV=production RUN npm run build # ============================================================================== -# Stage 3: Production runner +# Stage 3: Production Runner # ============================================================================== FROM node:20-alpine AS runner WORKDIR /app -ENV NODE_ENV=production -ENV NEXT_TELEMETRY_DISABLED=1 -ENV PORT=3000 -ENV HOSTNAME="0.0.0.0" +ENV NODE_ENV=production \ + NEXT_TELEMETRY_DISABLED=1 \ + PORT=3000 \ + HOSTNAME=0.0.0.0 RUN addgroup --system --gid 1001 nodejs && \ adduser --system --uid 1001 nextjs -# Copy static assets and standalone build output +# Copy static assets and public directories COPY --from=builder /app/public ./public + +# Set permissions for prerender cache +RUN mkdir .next && chown nextjs:nodejs .next + +# Copy standalone build output and static assets COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static @@ -48,7 +53,7 @@ USER nextjs EXPOSE 3000 -HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ - CMD wget --no-verbose --tries=1 --spider http://localhost:3000 || exit 1 +HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ + CMD wget --no-verbose --tries=1 --spider http://localhost:3000/ || exit 1 CMD ["node", "server.js"] diff --git a/refer_landing_page/next.config.js b/refer_landing_page/next.config.js index 219ce47..79a0e85 100644 --- a/refer_landing_page/next.config.js +++ b/refer_landing_page/next.config.js @@ -1,7 +1,7 @@ /** @type {import('next').NextConfig} */ const nextConfig = { - reactStrictMode: true, output: "standalone", + reactStrictMode: true, async redirects() { return [ {