Skip to content
Latchkey

Docker workflow (GH05TCREW/pentestagent)

The Docker workflow from GH05TCREW/pentestagent, explained and optimized by Latchkey.

C

CI health: C - fair

Point runs-on at Latchkey and get run de-duplication, job timeouts, SHA-pinned actions, self-healing for flaky steps, and up to 58% lower cost, applied automatically.

Grade your own workflow free or run it on Latchkey →
Source: GH05TCREW/pentestagent.github/workflows/docker.ymlLicense MITView source

What it does

This is the Docker workflow from the GH05TCREW/pentestagent repository, a real project running GitHub Actions. It is shown here with attribution under its MIT license.

Below, Latchkey shows a faster, safer version produced by its optimization engine.

The workflow

workflow (.yml)
name: Docker

on:
  push:
    tags: ['v*']
  workflow_dispatch:  # Allow manual trigger

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  build-base:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    
    steps:
      - name: Checkout
        uses: actions/checkout@v7
      
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v4
      
      - name: Login to GHCR
        uses: docker/login-action@v4
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Set lowercase image name
        run: echo "IMAGE_NAME_LOWER=${IMAGE_NAME,,}" >> $GITHUB_ENV
      
      - name: Extract metadata
        id: meta
        uses: docker/metadata-action@v6
        with:
            images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LOWER }}
            tags: |
              type=semver,pattern={{version}}
              type=raw,value=latest
      
      - name: Build and push base image
        uses: docker/build-push-action@v7
        with:
          context: .
          file: Dockerfile
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  build-kali:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    
    steps:
      - name: Checkout
        uses: actions/checkout@v7
      
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v4
      
      - name: Login to GHCR
        uses: docker/login-action@v4
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      
      - name: Set lowercase image name
        run: echo "IMAGE_NAME_LOWER=${IMAGE_NAME,,}" >> $GITHUB_ENV

      - name: Build and push Kali image
        uses: docker/build-push-action@v7
        with:
          context: .
          file: Dockerfile.kali
          push: true
          tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LOWER }}:kali
          cache-from: type=gha
          cache-to: type=gha,mode=max

  build-kali-arm64:
    runs-on: ubuntu-24.04-arm
    permissions:
      contents: read
      packages: write
    
    steps:
      - name: Checkout
        uses: actions/checkout@v7
      
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v4
      
      - name: Login to GHCR
        uses: docker/login-action@v4
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      
      - name: Set lowercase image name
        run: echo "IMAGE_NAME_LOWER=${IMAGE_NAME,,}" >> $GITHUB_ENV

      - name: Build and push Kali ARM64 image
        uses: docker/build-push-action@v7
        with:
          context: .
          file: Dockerfile.kali
          push: true
          platforms: linux/arm64
          tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LOWER }}:kali-arm64
          cache-from: type=gha
          cache-to: type=gha,mode=max

The same workflow, on Latchkey

Removes redundant runs and caps runaway jobs. Added and changed lines are highlighted.

name: Docker
 
on:
  push:
    tags: ['v*']
  workflow_dispatch:  # Allow manual trigger
 
env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}
 
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true
 
jobs:
  build-base:
    timeout-minutes: 30
    runs-on: latchkey-small
    permissions:
      contents: read
      packages: write
    
    steps:
      - name: Checkout
        uses: actions/checkout@v7
      
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v4
      
      - name: Login to GHCR
        uses: docker/login-action@v4
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
 
      - name: Set lowercase image name
        run: echo "IMAGE_NAME_LOWER=${IMAGE_NAME,,}" >> $GITHUB_ENV
      
      - name: Extract metadata
        id: meta
        uses: docker/metadata-action@v6
        with:
            images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LOWER }}
            tags: |
              type=semver,pattern={{version}}
              type=raw,value=latest
      
      - name: Build and push base image
        uses: docker/build-push-action@v7
        with:
          context: .
          file: Dockerfile
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max
 
  build-kali:
    timeout-minutes: 30
    runs-on: latchkey-small
    permissions:
      contents: read
      packages: write
    
    steps:
      - name: Checkout
        uses: actions/checkout@v7
      
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v4
      
      - name: Login to GHCR
        uses: docker/login-action@v4
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      
      - name: Set lowercase image name
        run: echo "IMAGE_NAME_LOWER=${IMAGE_NAME,,}" >> $GITHUB_ENV
 
      - name: Build and push Kali image
        uses: docker/build-push-action@v7
        with:
          context: .
          file: Dockerfile.kali
          push: true
          tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LOWER }}:kali
          cache-from: type=gha
          cache-to: type=gha,mode=max
 
  build-kali-arm64:
    timeout-minutes: 30
    runs-on: latchkey-small-arm
    permissions:
      contents: read
      packages: write
    
    steps:
      - name: Checkout
        uses: actions/checkout@v7
      
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v4
      
      - name: Login to GHCR
        uses: docker/login-action@v4
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      
      - name: Set lowercase image name
        run: echo "IMAGE_NAME_LOWER=${IMAGE_NAME,,}" >> $GITHUB_ENV
 
      - name: Build and push Kali ARM64 image
        uses: docker/build-push-action@v7
        with:
          context: .
          file: Dockerfile.kali
          push: true
          platforms: linux/arm64
          tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LOWER }}:kali-arm64
          cache-from: type=gha
          cache-to: type=gha,mode=max
 

What changed

4 third-party actions are referenced by a movable tag. Pin them to the commit SHA (Latchkey resolves and applies this automatically) so a repointed tag cannot change what runs.

What Latchkey heals here

This workflow has steps that commonly fail on transient issues (network, registries, flaky browsers). On Latchkey managed runners they are detected, retried, and self-healed instead of failing your build:

This workflow runs 3 jobs per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.

Actions used in this workflow