diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 667bf33..61c6b04 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -153,6 +153,10 @@ jobs: name: "Run Integration Tests - ${{ matrix.agent.agent_name }}" runs-on: ubuntu-latest needs: discover-agent-images + permissions: + id-token: write + contents: read + packages: read strategy: fail-fast: false # Continue testing other agents even if one fails matrix: @@ -170,6 +174,17 @@ jobs: username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} + - name: Configure AWS credentials for ECR access + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: arn:aws:iam::307185671274:role/github-action-scale-agentex-ecr-read + aws-region: us-west-2 + + - name: Login to egp-prod ECR for golden base images + uses: aws-actions/amazon-ecr-login@v2 + with: + registries: "022465994601" + - name: Pull agent image run: | echo "🐳 Pulling agent image: ${{ matrix.agent.image }}" diff --git a/agentex-ui/Dockerfile b/agentex-ui/Dockerfile index d8e617e..3f568e3 100644 --- a/agentex-ui/Dockerfile +++ b/agentex-ui/Dockerfile @@ -1,14 +1,15 @@ -# Use the official Node.js 20 Debian image -FROM node:20 - -# Update package lists and install Sharp dependencies -RUN apt-get update && apt-get install -y \ +# NOTE: -dev variant required at runtime for libvips (Sharp image processing) +FROM 022465994601.dkr.ecr.us-west-2.amazonaws.com/golden/chainguard/node:20-dev +ARG SOURCE_DIR=public/agentex-ui +ENTRYPOINT [] + +# Install dependencies as root +USER root +RUN apk add --no-cache \ libvips-dev \ python3 \ make \ - g++ \ - && apt-get clean \ - && rm -rf /var/lib/apt/lists/* + build-base WORKDIR /app @@ -20,7 +21,7 @@ ENV NODE_ENV=production ENV NEXT_TELEMETRY_DISABLED=1 # Copy package files -COPY package.json package-lock.json ./ +COPY ${SOURCE_DIR}/package.json ${SOURCE_DIR}/package-lock.json ./ ENV npm_config_cache=/tmp/.npm RUN npm config set maxsockets 3 @@ -30,7 +31,7 @@ RUN npm config set registry https://registry.npmjs.org/ && \ npm ci --omit=dev --verbose # Copy source code (node_modules and .next excluded by .dockerignore) -COPY . . +COPY ${SOURCE_DIR} . COPY LICENSE /app/LICENSE # Build the application (creates fresh .next directory) @@ -42,15 +43,11 @@ RUN echo "=== Build verification ===" && \ echo "=== Final container structure ===" && \ ls -la /app/ -# Create non-root user (Debian syntax) -RUN groupadd --system --gid 1001 nodejs && \ - useradd --system --uid 1001 --gid nodejs nextjs - -# Change ownership of the entire app directory to nextjs user -RUN chown -R nextjs:nodejs /app +# Use Chainguard's default nonroot user (65532) +RUN chown -R 65532:65532 /app # Switch to non-root user -USER nextjs +USER nonroot EXPOSE 3000 @@ -58,4 +55,4 @@ ENV PORT=3000 ENV HOSTNAME="0.0.0.0" # Start the application -CMD ["npm", "start"] +CMD ["npm", "start"] diff --git a/agentex/Dockerfile b/agentex/Dockerfile index da6cdc5..ea3e8d5 100644 --- a/agentex/Dockerfile +++ b/agentex/Dockerfile @@ -1,62 +1,89 @@ -FROM python:3.12-slim AS base -COPY --from=ghcr.io/astral-sh/uv:0.6.9 /uv /uvx /bin/ +FROM 022465994601.dkr.ecr.us-west-2.amazonaws.com/golden/chainguard/python:3.12-dev AS base +ARG SOURCE_DIR=public/agentex +# Install uv package manager +COPY --from=ghcr.io/astral-sh/uv:0.6.9 /uv /uvx /bin/ -RUN apt-get update && apt-get install -y \ - htop \ - vim \ +# Install system dependencies +USER root +RUN apk add --no-cache \ + bash \ curl \ - tar \ - python3-dev \ postgresql-client \ - build-essential \ - libpq-dev \ - gcc \ - netcat-openbsd \ - && apt-get clean \ - && rm -rf /var/lib/apt/lists/* + build-base \ + libpq \ + gcc WORKDIR /app # Copy dependency management files -COPY agentex/pyproject.toml agentex/README.md ./ +COPY ${SOURCE_DIR}/pyproject.toml ${SOURCE_DIR}/README.md ./ -# Install core dependencies -ENV UV_PROJECT_ENVIRONMENT=/usr/local -RUN uv sync +# Install core dependencies to system Python (Chainguard prefix is /usr) +ENV UV_PROJECT_ENVIRONMENT=/usr +RUN uv sync --no-dev # Development stage (for docker-compose) FROM base AS dev +ENTRYPOINT [] +ARG SOURCE_DIR=public/agentex -# Install dev dependencies +# Install dev dependencies to system Python RUN uv sync --group dev -COPY agentex/src/ ./src/ +COPY ${SOURCE_DIR}/src/ ./src/ EXPOSE 5003 ENV PYTHONPATH=/app CMD ["ddtrace-run", "uvicorn", "src.api.app:app", "--host", "0.0.0.0", "--port", "5003", "--reload"] # Docs builder stage FROM base AS docs-builder +ARG SOURCE_DIR=public/agentex -# Install docs dependencies +# Install docs dependencies to system Python RUN uv sync --group docs -COPY agentex/docs/ docs/ -COPY agentex/src/ src/ +COPY ${SOURCE_DIR}/docs/ docs/ +COPY ${SOURCE_DIR}/src/ src/ RUN cd docs && mkdocs build # Production stage -FROM base AS production +# NOTE: -dev variant required at runtime for apk (libpq, postgresql-client needed by psycopg2) +FROM 022465994601.dkr.ecr.us-west-2.amazonaws.com/golden/chainguard/python:3.12-dev AS production +ENTRYPOINT [] ARG INCLUDE_DOCS=false +ARG SOURCE_DIR=public/agentex + +# Install runtime system dependencies only (no build tools) +USER root +RUN apk add --no-cache \ + postgresql-client \ + libpq + +WORKDIR /app + +# Copy Python packages and console_scripts from base stage (Chainguard installs to /usr/lib/python3.12) +COPY --from=base /usr/lib/python3.12 /usr/lib/python3.12 +# Copy only the Python-installed console_scripts (e.g. uvicorn, ddtrace-run), not build tools +COPY --from=base /usr/bin/uvicorn /usr/bin/uvicorn +COPY --from=base /usr/bin/ddtrace-run /usr/bin/ddtrace-run +COPY --from=base /usr/bin/python3 /usr/bin/python3 +COPY --from=base /usr/bin/python3.12 /usr/bin/python3.12 + +# Copy application files +COPY ${SOURCE_DIR}/pyproject.toml ${SOURCE_DIR}/README.md ./ +COPY ${SOURCE_DIR}/src/ src/ +COPY ${SOURCE_DIR}/database/ database/ +COPY ${SOURCE_DIR}/logging_config.conf logging_config.conf +COPY LICENSE /app/LICENSE # Conditionally copy docs from builder stage COPY --from=docs-builder /app/docs/site /app/docs/site -COPY agentex/src/ src/ -COPY agentex/database/ database/ -COPY agentex/logging_config.conf logging_config.conf -COPY LICENSE /app/LICENSE +# Set ownership to Chainguard's default nonroot user (UID 65532) +RUN chown -R 65532:65532 /app + +USER nonroot EXPOSE 5003 ENV PYTHONPATH=/app diff --git a/agentex/docker-compose.yml b/agentex/docker-compose.yml index da5d73d..b3a935b 100644 --- a/agentex/docker-compose.yml +++ b/agentex/docker-compose.yml @@ -154,6 +154,8 @@ services: context: .. dockerfile: agentex/Dockerfile target: dev + args: + SOURCE_DIR: agentex environment: - ENVIRONMENT=development - UVICORN_PORT=5003 @@ -215,6 +217,8 @@ services: context: .. dockerfile: agentex/Dockerfile target: dev + args: + SOURCE_DIR: agentex environment: - ENVIRONMENT=development - DATABASE_URL=postgresql://postgres:postgres@agentex-postgres:5432/agentex