# # Multi-stage Dockerfile for Pentest Agent # Uses Chainguard Wolfi for minimal attack surface and supply chain security # Builder stage - Install tools and dependencies FROM cgr.dev/chainguard/wolfi-base:latest AS builder # Install system dependencies available in Wolfi RUN apk update && apk add --no-cache \ # Core build tools build-base \ git \ curl \ wget \ ca-certificates \ # Network libraries for Go tools libpcap-dev \ linux-headers \ # Language runtimes go \ nodejs-22 \ npm \ python3 \ py3-pip \ ruby \ ruby-dev \ # Security tools available in Wolfi nmap \ # Additional utilities bash # Set environment variables for Go ENV GOPATH=/go ENV PATH=$GOPATH/bin:/usr/local/go/bin:$PATH ENV CGO_ENABLED=1 # Create directories RUN mkdir -p $GOPATH/bin # Install Go-based security tools RUN go install -v github.com/projectdiscovery/subfinder/v2/cmd/subfinder@latest # Install WhatWeb from GitHub (Ruby-based tool) RUN git clone --depth 1 https://github.com/urbanadventurer/WhatWeb.git /opt/whatweb && \ chmod +x /opt/whatweb/whatweb && \ gem install addressable && \ echo '#!/bin/bash' > /usr/local/bin/whatweb && \ echo 'cd /opt/whatweb && exec ./whatweb "$@"' >> /usr/local/bin/whatweb && \ chmod +x /usr/local/bin/whatweb # Install Python-based tools RUN pip3 install --no-cache-dir schemathesis # Install pnpm RUN npm install -g pnpm@10.12.1 # Build Node.js application in builder to avoid QEMU emulation failures in CI WORKDIR /app # Copy workspace manifests for install layer caching COPY package.json pnpm-workspace.yaml pnpm-lock.yaml .npmrc ./ COPY apps/worker/package.json ./apps/worker/ COPY apps/cli/package.json ./apps/cli/ COPY packages/mcp-server/package.json ./packages/mcp-server/ RUN pnpm install --frozen-lockfile COPY . . # Build mcp-server (dependency) then worker. CLI not needed in Docker RUN pnpm --filter @shannon/mcp-server run build && \ pnpm --filter @shannon/worker run build RUN pnpm prune --prod # Runtime stage - Minimal production image FROM cgr.dev/chainguard/wolfi-base:latest AS runtime # Install only runtime dependencies USER root RUN apk update && apk add --no-cache \ # Core utilities git \ bash \ curl \ ca-certificates \ # Network libraries (runtime) libpcap \ # Security tools nmap \ # Language runtimes (minimal) nodejs-22 \ npm \ python3 \ ruby \ # Chromium browser and dependencies for Playwright chromium \ # Additional libraries Chromium needs nss \ freetype \ harfbuzz \ # X11 libraries for headless browser libx11 \ libxcomposite \ libxdamage \ libxext \ libxfixes \ libxrandr \ mesa-gbm \ # Font rendering fontconfig # Copy Go binaries from builder COPY --from=builder /go/bin/subfinder /usr/local/bin/ # Copy WhatWeb from builder COPY --from=builder /opt/whatweb /opt/whatweb COPY --from=builder /usr/local/bin/whatweb /usr/local/bin/whatweb # Install WhatWeb Ruby dependencies in runtime stage RUN gem install addressable # Copy Python packages from builder COPY --from=builder /usr/lib/python3.*/site-packages /usr/lib/python3.12/site-packages COPY --from=builder /usr/bin/schemathesis /usr/bin/ # Create non-root user RUN addgroup -g 1001 pentest && \ adduser -u 1001 -G pentest -s /bin/bash -D pentest # System-level git config (survives UID remapping in entrypoint) RUN git config --system user.email "agent@localhost" && \ git config --system user.name "Pentest Agent" && \ git config --system --add safe.directory '*' # Set working directory WORKDIR /app # Copy only what the worker needs (skip CLI source, infra, tsdown artifacts) COPY --from=builder /app/package.json /app/pnpm-workspace.yaml /app/pnpm-lock.yaml /app/.npmrc /app/ COPY --from=builder /app/node_modules /app/node_modules COPY --from=builder /app/apps/worker /app/apps/worker COPY --from=builder /app/apps/cli/package.json /app/apps/cli/package.json COPY --from=builder /app/packages /app/packages RUN npm install -g @anthropic-ai/claude-code # Create directories for session data and ensure proper permissions RUN mkdir -p /app/sessions /app/deliverables /app/repos /app/workspaces && \ mkdir -p /tmp/.cache /tmp/.config /tmp/.npm && \ chmod 777 /app && \ chmod 777 /tmp/.cache && \ chmod 777 /tmp/.config && \ chmod 777 /tmp/.npm && \ chown -R pentest:pentest /app COPY entrypoint.sh /app/entrypoint.sh RUN chmod +x /app/entrypoint.sh # Set environment variables ENV NODE_ENV=production ENV PATH="/usr/local/bin:$PATH" ENV SHANNON_DOCKER=true ENV PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 ENV PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH=/usr/bin/chromium-browser ENV npm_config_cache=/tmp/.npm ENV HOME=/tmp ENV XDG_CACHE_HOME=/tmp/.cache ENV XDG_CONFIG_HOME=/tmp/.config ENTRYPOINT ["/app/entrypoint.sh"] CMD ["node", "apps/worker/dist/temporal/worker.js"]