From ee0f1b961da2b1b58cd693d9ebce67f4052837a9 Mon Sep 17 00:00:00 2001 From: Ash Davies Date: Fri, 4 Jul 2025 14:28:00 +0100 Subject: [PATCH 1/4] Update Dockerfile with latest template --- Dockerfile | 68 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 38 insertions(+), 30 deletions(-) diff --git a/Dockerfile b/Dockerfile index 0301741..5458bbd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,52 +1,60 @@ -ARG PROJECT_NAME="Dfe.CaseAggregationService.Api" -ARG REPO_ORIGIN="https://github.com/DFE-Digital/rsd-ddd-clean-architecture" -ARG DOTNET_SDK_TAG=8.0 -ARG DOTNET_EF_TAG=8.0.8 -ARG DOTNET_ASPNET_TAG=8.0-bookworm-slim -ARG NUGET_SOURCE="https://nuget.pkg.github.com/DFE-Digital/index.json" -ARG CI +# Set the major version of dotnet +ARG DOTNET_VERSION=8.0 # ============================================== -# Base SDK +# .NET SDK: Build # ============================================== -FROM "mcr.microsoft.com/dotnet/sdk:${DOTNET_SDK_TAG}" AS builder -ENV CI=${CI} +FROM mcr.microsoft.com/dotnet/sdk:${DOTNET_VERSION}-azurelinux3.0 AS build WORKDIR /build -COPY . . -RUN --mount=type=secret,id=github_token dotnet nuget add source --username USERNAME --password $(cat /run/secrets/github_token) --store-password-in-clear-text --name github ${NUGET_SOURCE} -RUN dotnet restore ${PROJECT_NAME} -RUN dotnet build -c Release ${PROJECT_NAME} -p:CI=${CI} -RUN dotnet publish ${PROJECT_NAME} -c Release -o /app --no-build +ARG CI +ENV CI=${CI} + +# Mount GitHub Token as a Docker secret so that NuGet Feed can be accessed +RUN --mount=type=secret,id=github_token dotnet nuget add source --username USERNAME --password $(cat /run/secrets/github_token) --store-password-in-clear-text --name github "https://nuget.pkg.github.com/DFE-Digital/index.json" + +# Copy the application code +COPY ./src/ ./src/ +COPY Directory.Build.props ./ +COPY Dfe.CaseAggregationService.sln ./ + +# Build and publish the dotnet solution +RUN dotnet restore Dfe.CaseAggregationService.sln && \ + dotnet build ./src/Dfe.CaseAggregationService.Api --no-restore -c Release && \ + dotnet publish ./src/Dfe.CaseAggregationService.Api --no-build -o /app # ============================================== # Entity Framework: Migration Builder # ============================================== -FROM builder AS efbuilder +FROM build AS efbuilder WORKDIR /build +ARG DOTNET_EF_TAG=8.0.8 + ENV PATH=$PATH:/root/.dotnet/tools -RUN dotnet tool install --global dotnet-ef --version ${DOTNET_EF_TAG} +RUN dotnet tool install --global dotnet-ef RUN mkdir /sql -RUN dotnet ef migrations bundle -r linux-x64 --configuration Release -p ${PROJECT_NAME} --no-build -o /sql/migratedb +RUN dotnet ef migrations bundle -r linux-x64 \ + --configuration Release \ + --project ./src/Dfe.CaseAggregationService.Api \ + --no-build -o /sql/migratedb # ============================================== # Entity Framework: Migration Runner # ============================================== -FROM "mcr.microsoft.com/dotnet/aspnet:${DOTNET_ASPNET_TAG}" AS initcontainer +FROM mcr.microsoft.com/dotnet/aspnet:${DOTNET_VERSION}-azurelinux3.0 AS initcontainer WORKDIR /sql COPY --from=efbuilder /sql /sql -COPY --from=builder /app/appsettings* /${PROJECT_NAME}/ +COPY --from=build /app/appsettings* /Dfe.CaseAggregationService.Api/ # ============================================== -# Application +# .NET Runtime: Publish # ============================================== -FROM "mcr.microsoft.com/dotnet/aspnet:${DOTNET_ASPNET_TAG}" AS final -LABEL org.opencontainers.image.source=${REPO_ORIGIN} -ARG COMMIT_SHA -COPY --from=builder /app /app -COPY ./script/docker-entrypoint.sh /app/docker-entrypoint.sh +FROM mcr.microsoft.com/dotnet/aspnet:${DOTNET_VERSION}-azurelinux3.0 AS final WORKDIR /app -RUN chown -R app:app /app +LABEL org.opencontainers.image.source="https://github.com/DFE-Digital/case-aggregation-api" +LABEL org.opencontainers.image.description="Dfe.CaseAggregationService" + +COPY --from=build /app /app +COPY ./script/docker-entrypoint.sh /app/docker-entrypoint.sh RUN chmod +x ./docker-entrypoint.sh -USER app -ENV ASPNETCORE_HTTP_PORTS 80 -EXPOSE 80/tcp + +USER $APP_UID From fe90f66b18f754b41e46f5613adb833052b5d5d1 Mon Sep 17 00:00:00 2001 From: Ash Davies Date: Fri, 4 Jul 2025 14:29:05 +0100 Subject: [PATCH 2/4] Update docker build workflow with new options --- .github/workflows/docker-test.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/docker-test.yml b/.github/workflows/docker-test.yml index cc85f49..6cc4214 100644 --- a/.github/workflows/docker-test.yml +++ b/.github/workflows/docker-test.yml @@ -2,7 +2,7 @@ name: Dockerfile on: push: - branches: main + branches: [ main ] paths: - Dockerfile pull_request: @@ -34,6 +34,7 @@ jobs: with: secrets: github_token=${{ secrets.GITHUB_TOKEN }} load: true + build-args: CI=true cache-from: type=gha cache-to: type=gha target: ${{ matrix.stage }} From 6c3c417a716063333d6370ee33d2799d6c1dd7dd Mon Sep 17 00:00:00 2001 From: Ash Davies Date: Fri, 4 Jul 2025 14:33:07 +0100 Subject: [PATCH 3/4] Remove reference to initContainer as there is no DbContext --- .github/workflows/docker-test.yml | 7 ------- Dockerfile | 23 ----------------------- 2 files changed, 30 deletions(-) diff --git a/.github/workflows/docker-test.yml b/.github/workflows/docker-test.yml index 6cc4214..c205bff 100644 --- a/.github/workflows/docker-test.yml +++ b/.github/workflows/docker-test.yml @@ -13,12 +13,6 @@ on: jobs: build: runs-on: ubuntu-latest - strategy: - matrix: - stage: [ - "final", - "initcontainer" - ] outputs: image: ${{ steps.build.outputs.imageid }} steps: @@ -37,5 +31,4 @@ jobs: build-args: CI=true cache-from: type=gha cache-to: type=gha - target: ${{ matrix.stage }} push: false diff --git a/Dockerfile b/Dockerfile index 5458bbd..8fe9762 100644 --- a/Dockerfile +++ b/Dockerfile @@ -22,29 +22,6 @@ RUN dotnet restore Dfe.CaseAggregationService.sln && \ dotnet build ./src/Dfe.CaseAggregationService.Api --no-restore -c Release && \ dotnet publish ./src/Dfe.CaseAggregationService.Api --no-build -o /app -# ============================================== -# Entity Framework: Migration Builder -# ============================================== -FROM build AS efbuilder -WORKDIR /build -ARG DOTNET_EF_TAG=8.0.8 - -ENV PATH=$PATH:/root/.dotnet/tools -RUN dotnet tool install --global dotnet-ef -RUN mkdir /sql -RUN dotnet ef migrations bundle -r linux-x64 \ - --configuration Release \ - --project ./src/Dfe.CaseAggregationService.Api \ - --no-build -o /sql/migratedb - -# ============================================== -# Entity Framework: Migration Runner -# ============================================== -FROM mcr.microsoft.com/dotnet/aspnet:${DOTNET_VERSION}-azurelinux3.0 AS initcontainer -WORKDIR /sql -COPY --from=efbuilder /sql /sql -COPY --from=build /app/appsettings* /Dfe.CaseAggregationService.Api/ - # ============================================== # .NET Runtime: Publish # ============================================== From df55e16e5ac0b53113000f67f57699e79fd96427 Mon Sep 17 00:00:00 2001 From: Ash Davies Date: Fri, 4 Jul 2025 14:34:20 +0100 Subject: [PATCH 4/4] Add Trivy container scanning --- .github/workflows/docker-test.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/.github/workflows/docker-test.yml b/.github/workflows/docker-test.yml index c205bff..9f410d4 100644 --- a/.github/workflows/docker-test.yml +++ b/.github/workflows/docker-test.yml @@ -32,3 +32,23 @@ jobs: cache-from: type=gha cache-to: type=gha push: false + + - name: Export docker image as tar + run: docker save -o ${{ steps.build.outputs.imageid }}.tar ${{ steps.build.outputs.imageid }} + + - name: Scan Docker image for CVEs + uses: aquasecurity/trivy-action@6c175e9c4083a92bbca2f9724c8a5e33bc2d97a5 # 0.30.0 + with: + input: ${{ steps.build.outputs.imageid }}.tar + format: 'sarif' + output: 'trivy-results.sarif' + limit-severities-for-sarif: true + ignore-unfixed: true + severity: 'CRITICAL,HIGH' + github-pat: ${{ secrets.GITHUB_TOKEN }} + + - name: Upload scan results to GitHub Security + uses: github/codeql-action/upload-sarif@181d5eefc20863364f96762470ba6f862bdef56b # v3 + if: always() + with: + sarif_file: 'trivy-results.sarif'