From d51cd5e9216df98977d12379b544233e17a78ab0 Mon Sep 17 00:00:00 2001 From: Jeremy Bernard Date: Thu, 8 Jan 2026 13:10:37 +0100 Subject: [PATCH 1/5] feat: improve docker build --- .github/workflows/docker-build.yml | 53 ++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index 493805d..686dcc2 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -74,36 +74,23 @@ jobs: username: ${{ secrets.username }} password: ${{ secrets.password }} - - name: Build Docker Image + - name: Build Docker image uses: docker/build-push-action@v6 with: build-args: ${{ inputs.build-args }} context: ${{ inputs.context }} file: ${{ inputs.dockerfile }} platforms: ${{ inputs.platforms }} - push: ${{ inputs.push }} + load: true # Make the image available on runner + push: false # Don't push yet, wait for security checks tags: ${{ inputs.image-name }}:${{ inputs.image-tag }} - - name: Build Docker Image as Tarball - if: ${{ inputs.security-scan }} - run: | - BUILD_ARGS="" - if [ -n "${{ inputs.build-args }}" ]; then - while IFS= read -r line; do - if [ -n "$line" ]; then - BUILD_ARGS="$BUILD_ARGS --build-arg $line" - fi - done <<< "${{ inputs.build-args }}" - fi - docker build $BUILD_ARGS -t ${{ inputs.image-name }}:${{ inputs.image-tag }} -f ${{ inputs.dockerfile }} ${{ inputs.context }} - docker save -o vuln-image.tar ${{ inputs.image-name }}:${{ inputs.image-tag }} - - name: Run Trivy vulnerability scanner id: trivy if: ${{ inputs.security-scan }} - uses: aquasecurity/trivy-action@0.29.0 + uses: aquasecurity/trivy-action@0.33.1 with: - input: vuln-image.tar + image-ref: ${{ inputs.image-name }}:${{ inputs.image-tag }} format: ${{ (inputs.security-report == 'sarif' && 'sarif') || 'table' }} ignore-unfixed: true vuln-type: "os,library" @@ -196,3 +183,33 @@ jobs: ${{ steps.read_hadolint.outputs.report }} ``` + + - name: Fail build on CRITICAL or HIGH vulnerabilities + if: ${{ inputs.security-scan }} + uses: aquasecurity/trivy-action@0.33.1 + with: + image-ref: ${{ inputs.image-name }}:${{ inputs.image-tag }} + format: ${{ (inputs.security-report == 'sarif' && 'sarif') || 'table' }} + ignore-unfixed: true + vuln-type: "os,library" + severity: "CRITICAL,HIGH" + hide-progress: true + skip-setup-trivy: true + exit-code: 1 + + - name: Build and push Docker image + if: ${{ inputs.push }} + uses: docker/build-push-action@v6 + with: + build-args: ${{ inputs.build-args }} + context: ${{ inputs.context }} + file: ${{ inputs.dockerfile }} + platforms: ${{ inputs.platforms }} + push: true + tags: ${{ inputs.image-name }}:${{ inputs.image-tag }} + + - name: Cleanup files + if: always() + run: | + rm -f trivy.txt trivy-results.sarif + docker image rm -f ${{ inputs.image-name }}:${{ inputs.image-tag }} From 0d1811667e1656f6f6e7742e4800559693faadbe Mon Sep 17 00:00:00 2001 From: Jeremy Bernard Date: Mon, 12 Jan 2026 13:02:43 +0100 Subject: [PATCH 2/5] fix: docker build needs to be single-platform to load --- .github/workflows/docker-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index 686dcc2..66dced4 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -80,7 +80,7 @@ jobs: build-args: ${{ inputs.build-args }} context: ${{ inputs.context }} file: ${{ inputs.dockerfile }} - platforms: ${{ inputs.platforms }} + platforms: "linux/amd64" load: true # Make the image available on runner push: false # Don't push yet, wait for security checks tags: ${{ inputs.image-name }}:${{ inputs.image-tag }} From 7e1a11142b3bbf612ff28cc5197822c3bf90f732 Mon Sep 17 00:00:00 2001 From: Jeremy Bernard Date: Mon, 12 Jan 2026 13:03:13 +0100 Subject: [PATCH 3/5] fix: more comprehensive first Trivy analysis --- .github/workflows/docker-build.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index 66dced4..b829a3c 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -92,9 +92,7 @@ jobs: with: image-ref: ${{ inputs.image-name }}:${{ inputs.image-tag }} format: ${{ (inputs.security-report == 'sarif' && 'sarif') || 'table' }} - ignore-unfixed: true vuln-type: "os,library" - severity: "CRITICAL,HIGH" hide-progress: true output: ${{ (inputs.security-report == 'sarif' && 'trivy-results.sarif') || 'trivy.txt' }} From 19edc5ccebe9b8799093c22af9dc6af286812e27 Mon Sep 17 00:00:00 2001 From: Jeremy Bernard Date: Mon, 2 Feb 2026 09:31:13 +0100 Subject: [PATCH 4/5] refactor!: enforce and optimize single platform build --- .github/workflows/docker-build.yml | 35 +++++++++++++---------- docker-build/README.md | 46 +++++++++++++++++------------- 2 files changed, 46 insertions(+), 35 deletions(-) diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index b829a3c..2fe644b 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -43,9 +43,9 @@ on: description: "Enable Hadolint" default: true type: boolean - platforms: - description: "Build platforms" - default: "linux/amd64,linux/arm64" + platform: + description: "Build platform" + default: "linux/amd64" type: string secrets: username: @@ -57,6 +57,18 @@ jobs: build: runs-on: ubuntu-latest steps: + - name: Validate platform input + run: | + platform="${{ inputs.platform }}" + + if [ "$platform" != "linux/amd64" ] && [ "$platform" != "linux/arm64" ] ; then + echo "❌ Error: Invalid platform: $platform" + echo "Valid platforms are 'linux/amd64' or 'linux/arm64'" + exit 1 + fi + + echo "✅ Platform validation passed: $platform" + - name: Checkout Repository uses: actions/checkout@v4 @@ -80,7 +92,7 @@ jobs: build-args: ${{ inputs.build-args }} context: ${{ inputs.context }} file: ${{ inputs.dockerfile }} - platforms: "linux/amd64" + platforms: ${{ inputs.platform }} load: true # Make the image available on runner push: false # Don't push yet, wait for security checks tags: ${{ inputs.image-name }}:${{ inputs.image-tag }} @@ -111,7 +123,7 @@ jobs: with: issue-number: ${{ github.event.pull_request.number }} comment-author: "github-actions[bot]" - body-includes: "Trivy Security Scan Results" + body-includes: "Trivy Security ${{ inputs.platform }} Scan Results" - name: Create or update Trivy comment if: github.event_name == 'pull_request' && inputs.security-scan && inputs.security-report == 'comment' @@ -123,7 +135,7 @@ jobs: edit-mode: replace body: | - ### 🔒 Trivy Security Scan Results + ### 🔒 Trivy Security ${{ inputs.platform }} Scan Results
Click to expand detailed results ```bash @@ -195,16 +207,9 @@ jobs: skip-setup-trivy: true exit-code: 1 - - name: Build and push Docker image + - name: Push Docker image if: ${{ inputs.push }} - uses: docker/build-push-action@v6 - with: - build-args: ${{ inputs.build-args }} - context: ${{ inputs.context }} - file: ${{ inputs.dockerfile }} - platforms: ${{ inputs.platforms }} - push: true - tags: ${{ inputs.image-name }}:${{ inputs.image-tag }} + run: docker push ${{ inputs.image-name }}:${{ inputs.image-tag }} - name: Cleanup files if: always() diff --git a/docker-build/README.md b/docker-build/README.md index 4605f3f..8d47eb6 100644 --- a/docker-build/README.md +++ b/docker-build/README.md @@ -2,34 +2,40 @@ ## 🔍 Overview -This reusable GitHub Actions workflow automates the process of building and pushing Docker images to Docker Hub. It simplifies the Docker build process in your CI/CD pipeline by handling authentication, building, and tagging in a standardized way. Perfect for teams looking to streamline their containerization workflow with minimal configuration. +This reusable GitHub Actions workflow automates the process of building and pushing Docker images to a Docker Registry. +It simplifies the Docker build process in your CI/CD pipeline by handling authentication, building, and tagging in a standardized way. +Perfect for teams looking to streamline their containerization workflow with minimal configuration. ## ✨ Features -- 🔐 Securely authenticates with Docker Hub using best practices +- 🔐 Securely authenticates with a Docker Registry using best practices - 🏗️ Builds optimized Docker images from a specified Dockerfile -- 🏷️ Intelligently tags and pushes images to Docker Hub -- 🔎 Scan for vulnerabilities +- 🏷️ Intelligently tags and pushes images to a Docker Registry +- 🔎 Scan for vulnerabilities with Trivy - 👍 Lint dockerfile - 🛡️ Handles authentication securely using GitHub Secrets - 🚀 Optimizes build performance with layer caching -- 📦 Supports multi-platform builds (AMD64, ARM64) +- 📦 Supports AMD64 and ARM64 platforms (one per workflow run) + +> [!IMPORTANT] +> Due to a limitation on Trivy analysis, the workflow targets a single platform. +> A workflow instance should be configured for each intended targeted platform. ## ⚙️ Inputs -| Name | Description | Required | Default | -| ----------------- | ---------------------------------------------------------------------------------- | -------- | --------------------------- | -| `build-args` | Docker build arguments (multiline format: `KEY1=value1\nKEY2=value2`) | No | `""` | -| `context` | Path to Docker Build Context | No | `"."` | -| `dockerfile` | Path to the Dockerfile to build (e.g., './Dockerfile', './docker/Dockerfile') | No | `"Dockerfile"` | -| `hadolint` | Enable Hadolint | No | `true` | -| `image-name` | Name of Docker Image (e.g., 'myimage', 'myorg/myimage') | true | - | -| `image-tag` | Tag to apply to the built image (e.g., 'latest', 'v1.2.3') | No | `"latest"` | -| `platforms` | Indicates which platforms the image should be built for | No | `"linux/amd64,linux/arm64"` | -| `push` | Push Docker Image to Registry | No | `false` | -| `registry` | Docker Registry | No | `"docker.io"` | -| `security-report` | Security Report Mode (`"sarif"` \| `"comment"`; ignored if `security-scan: false`) | No | `"sarif"` | -| `security-scan` | Enable Trivy Security Scan | No | `true` | +| Name | Description | Required | Default | +| ----------------- | ---------------------------------------------------------------------------------- | -------- | --------------- | +| `build-args` | Docker build arguments (multiline format: `KEY1=value1\nKEY2=value2`) | No | `""` | +| `context` | Path to Docker Build Context | No | `"."` | +| `dockerfile` | Path to the Dockerfile to build (e.g., './Dockerfile', './docker/Dockerfile') | No | `"Dockerfile"` | +| `hadolint` | Enable Hadolint | No | `true` | +| `image-name` | Name of Docker Image (e.g., 'myimage', 'myorg/myimage') | true | - | +| `image-tag` | Tag to apply to the built image (e.g., 'latest', 'v1.2.3') | No | `"latest"` | +| `platform` | Indicates which platform the image should be built for | No | `"linux/amd64"` | +| `push` | Push Docker Image to Registry | No | `false` | +| `registry` | Docker Registry | No | `"docker.io"` | +| `security-report` | Security Report Mode (`"sarif"` \| `"comment"`; ignored if `security-scan: false`) | No | `"sarif"` | +| `security-scan` | Enable Trivy Security Scan | No | `true` | ## 🔐 Secrets @@ -73,7 +79,7 @@ jobs: ## 📝 Notes -- 🔒 Ensure your Docker Hub credentials are stored securely as GitHub Secrets +- 🔒 Ensure your Docker Registry credentials are stored securely as GitHub Secrets - 🔄 The workflow will automatically handle the Docker build and push process - 🏷️ You can specify any valid Docker tag format in the `tag` input - 📅 Consider using dynamic tags based on git tags, commit SHAs, or dates @@ -81,7 +87,7 @@ jobs: ## 🛠️ Troubleshooting -- If you encounter authentication issues, verify your Docker Hub credentials are correct and have appropriate permissions +- If you encounter authentication issues, verify your Docker Registry credentials are correct and have appropriate permissions - For build failures, check your Dockerfile syntax and ensure all referenced files exist - Large images may take longer to push - consider optimizing your Dockerfile with multi-stage builds - If you need to debug the build process, you can add the `ACTIONS_STEP_DEBUG` secret set to `true` in your repository From 359da29d35effdbaf6ecd2a4102d1c83b24b25d9 Mon Sep 17 00:00:00 2001 From: Jeremy Bernard Date: Mon, 2 Feb 2026 11:24:37 +0100 Subject: [PATCH 5/5] fix: review comments --- .github/workflows/docker-build.yml | 32 ++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index 2fe644b..2754a7d 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -56,18 +56,34 @@ on: jobs: build: runs-on: ubuntu-latest + + # avoid shell injection through string interpolation + env: + PLATFORM: ${{ inputs.platform }} + OCI_IMAGE: ${{ inputs.image-name }}:${{ inputs.image-tag }} + REPORT_MODE: ${{ inputs.security-report }} + steps: - name: Validate platform input run: | - platform="${{ inputs.platform }}" - - if [ "$platform" != "linux/amd64" ] && [ "$platform" != "linux/arm64" ] ; then - echo "❌ Error: Invalid platform: $platform" + if [ "$PLATFORM" != "linux/amd64" ] && [ "$PLATFORM" != "linux/arm64" ] ; then + echo "❌ Error: Invalid platform: $PLATFORM" echo "Valid platforms are 'linux/amd64' or 'linux/arm64'" exit 1 fi - echo "✅ Platform validation passed: $platform" + echo "✅ Platform validation passed: $PLATFORM" + + - name: Validate security report mode input + if: ${{ inputs.security-scan }} + run: | + if [ "$REPORT_MODE" != "comment" ] && [ "$REPORT_MODE" != "sarif" ] ; then + echo "❌ Error: Invalid security report mode: $REPORT_MODE" + echo "Valid modes are 'comment' or 'sarif'" + exit 1 + fi + + echo "✅ Security report mode validation passed: $REPORT_MODE" - name: Checkout Repository uses: actions/checkout@v4 @@ -199,7 +215,7 @@ jobs: uses: aquasecurity/trivy-action@0.33.1 with: image-ref: ${{ inputs.image-name }}:${{ inputs.image-tag }} - format: ${{ (inputs.security-report == 'sarif' && 'sarif') || 'table' }} + format: table ignore-unfixed: true vuln-type: "os,library" severity: "CRITICAL,HIGH" @@ -209,10 +225,10 @@ jobs: - name: Push Docker image if: ${{ inputs.push }} - run: docker push ${{ inputs.image-name }}:${{ inputs.image-tag }} + run: docker push "$OCI_IMAGE" - name: Cleanup files if: always() run: | rm -f trivy.txt trivy-results.sarif - docker image rm -f ${{ inputs.image-name }}:${{ inputs.image-tag }} + docker image rm -f "$OCI_IMAGE"