Skip to content

Docker Image

Docker Image #25

# Github workflow to build a docker image from a branch
name: Docker Image
on:
workflow_dispatch:
schedule:
- cron: "00 05 * * *" # 0500 UTC daily (nightly develop build)
- cron: "00 02 * * *" # 0200 UTC daily == 10pm ET (EDT) (pox-wf-integration build)
# Set default permissions
permissions:
contents: read
# Set default shell
defaults:
run:
shell: bash
# Set default env vars
# - transferred to composite action steps
env:
# Build for both x64 and arm64 arch
DOCKER_PLATFORMS: "linux/amd64,linux/arm64"
# Publish images to ghcr
DOCKER_REGISTRY: "ghcr.io"
# Set a default command to build. we'll define specific build config options later per arch.
CMD: "cargo build --features monitoring_prom,slog_json --profile release --workspace"
# Do not generate provenance from the docker build step, instead attest the image specifically
PROVENANCE: false
# Configure concurrency
concurrency:
group: docker-image-${{ github.head_ref || github.ref || github.run_id }}
# Always cancel duplicate jobs
cancel-in-progress: true
jobs:
# Build arch dependent binaries from source
build-binaries:
name: Build Binaries
# Only run this if it's the public repo or manually triggered
if: github.event_name == 'workflow_dispatch' || github.event.repository.visibility == 'public'
runs-on: ubuntu-latest
strategy:
max-parallel: 2
matrix:
arch:
- linux-glibc
cpu:
- x86-64
- arm64
permissions:
contents: read # required for checkout
id-token: write # required for attestation
attestations: write # required for attestation
outputs:
branch: ${{ steps.set-vars.outputs.branch }}
steps:
# Set local env vars.
# - For a manual run, use the selected ref_name
# - For the 0500 UTC schedule, use develop (nightly)
# - For the 0200 UTC schedule (10pm ET), use pox-wf-integration
- name: Set Local Vars
id: set-vars
run: |
var_branch="${{ github.ref_name }}"
if [ "${{ github.event_name }}" == "schedule" ]; then
if [ "${{ github.event.schedule }}" == "00 02 * * *" ]; then
var_branch="pox-wf-integration"
else
var_branch="develop"
fi
fi
echo "branch=${var_branch}" >> "$GITHUB_OUTPUT"
# Checkout the code
# - Checkout a specified branch or develop for scheduled jobs
- name: Checkout the latest code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ steps.set-vars.outputs.branch }}
# Configure target platform, install Rust toolchain, and build binaries
- name: Build Binaries
id: build-binaries
env:
MATRIX_CPU: ${{ matrix.cpu }}
# Set the build target statically, since we only need to build for linux-glibc
MATRIX_ARCH: linux-glibc
CMD: ${{ env.CMD }}
SIGNER_ONLY: "false"
run: bash ./.github/scripts/build_binaries.sh
# Compress the binary artifacts
- name: Compress binaries
run: |
# compress all binaries in the target directory for any architecture
file -0 ./target/${{ steps.build-binaries.outputs.target }}/release/* | sed -nE 's/\x0:\s*(ELF|PE32+|Mach).*//p' | zip --junk-paths ${{ steps.build-binaries.outputs.zipfile_name }}.zip -@
# Upload the binary archive using the commit sha as the key
- name: Upload Artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: ${{ github.sha }}-${{ steps.build-binaries.outputs.zipfile_name }}
path: ${{ steps.build-binaries.outputs.zipfile_name }}.zip
# Attest the binary archive
- name: Attest Artifact
uses: actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 # v4.1.0
with:
subject-path: ${{ steps.build-binaries.outputs.zipfile_name }}.zip
# Build and publish the docker images using the binary archives
image:
name: Build Image
needs:
- build-binaries
# Only run this if it's the public repo or manually triggered
if: github.event_name == 'workflow_dispatch' || github.event.repository.visibility == 'public'
runs-on: ubuntu-latest
permissions:
contents: read # required for checkout
id-token: write # required for attestation
attestations: write # required for attestation
packages: write # required for image push
steps:
# Retrieve repository description for image annotation
- name: Get repository description
id: repo-desc
run: |
DESCRIPTION=$(gh api repos/${{ github.repository }} --jq '.description')
echo "description=$DESCRIPTION" >> $GITHUB_OUTPUT
env:
GH_TOKEN: ${{ github.token }}
# Set local env vars
- name: Set Local Vars
id: set-vars
run: |
var_annotation_pattern="${{ needs.build-binaries.outputs.branch }}" # default to use the branch name
var_default_image="${{ env.DOCKER_REGISTRY }}/${{ github.repository }}"
if [ "${{ github.event_name }}" == "schedule" ]; then
if [ "${{ github.event.schedule }}" == "00 02 * * *" ]; then
# 10pm ET pox-wf-integration build: publish to the default image, tagged by branch name
var_annotation_pattern="pox-wf-integration"
else
var_default_image="${{ env.DOCKER_REGISTRY }}/${{ github.repository_owner }}/stacks-nightly"
var_annotation_pattern="Nightly" # for scheduled (nightly) builds, use 'Nightly'
fi
fi
{
echo "docker_images=${var_default_image}"
echo "annotation_pattern=${var_annotation_pattern}"
} >> "${GITHUB_OUTPUT}"
# Checkout the code
# - only .github is required for this job
- name: Checkout the latest code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ needs.build-binaries.outputs.branch }} # use the output in case we're building a nightly image
sparse-checkout: |
.github
# Download binary artifacts
- name: Download Artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
# linux-glibc variants are the only artifacts produced. Download for both architectures (Dockerfile will choose specific architecture archive)
pattern: ${{ github.sha }}-*
path: /tmp/release
merge-multiple: true
# Setup Docker for the builds
- name: Docker setup
id: docker-setup
uses: ./.github/actions/docker
with:
registry: ${{ env.DOCKER_REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# Set docker metadata
- name: Docker Metadata
id: docker-metadata
uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf #v6.0.0
env:
DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index
with:
images: ${{ steps.set-vars.outputs.docker_images }}
labels: |
org.opencontainers.image.created={{commit_date 'YYYY-MM-DDTHH:mm:ss.SSS[Z]'}}
org.opencontainers.image.revision=${{ github.sha }}
annotations: |
org.opencontainers.image.description=${{ steps.repo-desc.outputs.description }} | ${{ steps.set-vars.outputs.annotation_pattern }} Image
org.opencontainers.image.title=Stacks Core ${{ steps.set-vars.outputs.annotation_pattern }}
tags: |
# if trigger is workflow_dispatch
type=ref,event=branch,enable=${{ github.event_name == 'workflow_dispatch' }}
# if trigger is the nightly (0500 UTC) schedule, use a timestamp
type=schedule,pattern={{date 'YYYYMMDD'}},enable=${{ github.event.schedule == '00 05 * * *' }}
# if trigger is the 10pm ET (0200 UTC) schedule, tag with the branch name
type=raw,value=pox-wf-integration,enable=${{ github.event.schedule == '00 02 * * *' }}
# Build and push the docker image(s)
- name: Build and Push
id: docker-build
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
with:
sbom: false
provenance: ${{ env.PROVENANCE }}
context: /tmp
file: ./.github/dockerfiles/debian/Dockerfile
platforms: ${{ env.DOCKER_PLATFORMS }}
tags: ${{ steps.docker-metadata.outputs.tags }}
labels: ${{ steps.docker-metadata.outputs.labels }}
annotations: ${{ steps.docker-metadata.outputs.annotations }} # Note: annotations are used for multi-architecture ghcr images
push: ${{ steps.docker-setup.outputs.docker_push }} # Defined in .github/actions/docker/action.yml
# Generate docker image attestation(s)
- name: Attest Image
if: |
env.PROVENANCE != true
uses: actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 # v4.1.0
with:
subject-name: |
${{ steps.set-vars.outputs.docker_images }}
subject-digest: ${{ steps.docker-build.outputs.digest }}
push-to-registry: ${{ steps.docker-setup.outputs.docker_push }} # defined in .github/actions/docker composite
# Sign the images with GitHub OIDC Token
# - https://github.blog/security/supply-chain-security/safeguard-container-signing-capability-actions/
- name: Install Cosign
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
# Sign the images with Github OIDC token
- name: Sign the images OIDC Token
env:
DIGEST: ${{ steps.docker-build.outputs.digest }}
TAGS: ${{ steps.docker-metadata.outputs.tags }}
run: |
images=""
for tag in ${TAGS}; do
images+="${tag}@${DIGEST} "
done
cosign sign \
-a "repo=${{ github.repository }}" \
-a "ref=${{ github.sha }}" \
--yes \
${images}