Skip to content

feat: initial multiarch image #16

feat: initial multiarch image

feat: initial multiarch image #16

name: Build and Push Application Image
on:
pull_request:
push:
branches: ["main"]
workflow_dispatch:
permissions:
contents: read
packages: write
defaults:
run:
shell: bash
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}/my-cuda-app
jobs:
create_local_images:
strategy:
fail-fast: false
matrix:
arch: ["amd64", "arm64"]
runs-on: ${{ matrix.arch == 'arm64' && 'ubuntu-24.04-arm' || 'ubuntu-24.04' }}
steps:
- name: Free Disk Space (Ubuntu)
uses: jlumbroso/free-disk-space@main
with:
# this might remove tools that are actually needed,
# if set to "true" but frees about 6 GB
tool-cache: true
# all of these default to true, but feel free to set to
# "false" if necessary for your workflow
android: true
dotnet: true
haskell: true
large-packages: true
docker-images: true
swap-storage: true
- name: Checkout
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
driver-opts: |
image=moby/buildkit:v0.12.0
network=host
- name: Install Pack CLI
uses: buildpacks/github-actions/setup-pack@v5.9.4
- name: Build CUDA Build Image (local only)
run: |
docker build -t cuda-build-run:latest -f Dockerfile \
--platform linux/${{ matrix.arch }} .
- name: Create Builder Image (local only)
run: |
pack builder create cuda-builder:latest \
--config builder.toml \
--pull-policy if-not-present
- name: Export Docker images from the Docker daemon
run: |
docker save cuda-builder:latest cuda-build-run:latest | \
zstd -T0 --long=31 -o images.tar.zst
- name: Save Docker images to the cache
uses: actions/cache/save@v4
with:
key: ${{ github.run_id }}-cuda-images-${{ matrix.arch }}
path: images.tar.zst
build_application_image:
runs-on: ${{ matrix.arch == 'arm64' && 'ubuntu-24.04-arm' || 'ubuntu-24.04' }}
needs: create_local_images
strategy:
fail-fast: false
matrix:
arch: ["amd64", "arm64"]
steps:
- name: Free Disk Space (Ubuntu)
uses: jlumbroso/free-disk-space@main
with:
# this might remove tools that are actually needed,
# if set to "true" but frees about 6 GB
tool-cache: true
# all of these default to true, but feel free to set to
# "false" if necessary for your workflow
android: true
dotnet: true
haskell: true
large-packages: true
docker-images: true
swap-storage: true
- name: Maximize Disk Space (Aggressive)
run: |
echo "Available space before cleanup:"
df -h
# Remove unnecessary packages and files
sudo apt-get remove -y '^aspnetcore-.*' '^dotnet-.*' '^llvm-.*' '^mongodb-.*' '^mysql-.*' '^postgresql-.*'
sudo apt-get autoremove -y
sudo apt-get autoclean
# Remove large directories
sudo rm -rf /usr/share/dotnet
sudo rm -rf /usr/local/lib/android
sudo rm -rf /opt/ghc
sudo rm -rf /opt/hostedtoolcache/CodeQL
sudo rm -rf /usr/local/share/boost
sudo rm -rf /usr/local/graalvm/
sudo rm -rf /usr/local/share/chromium
sudo rm -rf /usr/local/lib/node_modules
# Clean Docker completely
docker system prune -af --volumes
echo "Available space after cleanup:"
df -h
- name: Checkout
uses: actions/checkout@v4
- name: Install Pack CLI
uses: buildpacks/github-actions/setup-pack@v5.9.4
- name: Configure Docker for Large Images
run: |
sudo systemctl stop docker
echo '{"storage-driver": "overlay2", "max-concurrent-downloads": 1, "max-concurrent-uploads": 1, "log-driver": "none"}' | sudo tee /etc/docker/daemon.json
sudo systemctl start docker
docker system prune -af --volumes
- name: Restore Docker images from the cache
uses: actions/cache/restore@v4
with:
fail-on-cache-miss: true
key: ${{ github.run_id }}-cuda-images-${{ matrix.arch }}
path: images.tar.zst
env:
SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1
- name: Load Docker images into the Docker daemon
run: |
zstd -dc --long=31 images.tar.zst | docker load
rm -rf images.tar.zst
- name: Build Application Image
run: |
IMAGE_NAME_LOWER=$(echo "${{ env.IMAGE_NAME }}" | tr '[:upper:]' '[:lower:]')
pack build ${{ env.REGISTRY }}/${IMAGE_NAME_LOWER}:${{ github.sha }}_linux-${{ matrix.arch }} \
--builder cuda-builder:latest \
--trust-builder \
--pull-policy never \
--platform linux/${{ matrix.arch }}
- name: Export Application Image
run: |
IMAGE_NAME_LOWER=$(echo "${{ env.IMAGE_NAME }}" | tr '[:upper:]' '[:lower:]')
docker save ${{ env.REGISTRY }}/${IMAGE_NAME_LOWER}:${{ github.sha }}_linux-${{ matrix.arch }} | \
zstd -T0 --long=31 -o app-image.tar.zst
- name: Save Application Image to cache
uses: actions/cache/save@v4
with:
key: ${{ github.run_id }}-app-image-${{ matrix.arch }}
path: app-image.tar.zst
push_application_image:
runs-on: ubuntu-24.04
if: success() && github.ref == 'refs/heads/main'
needs: build_application_image
strategy:
fail-fast: false
matrix:
arch: ["amd64", "arm64"]
steps:
- name: Free Disk Space (Ubuntu)
uses: jlumbroso/free-disk-space@main
with:
# this might remove tools that are actually needed,
# if set to "true" but frees about 6 GB
tool-cache: true
# all of these default to true, but feel free to set to
# "false" if necessary for your workflow
android: true
dotnet: true
haskell: true
large-packages: true
docker-images: true
swap-storage: true
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Restore Application Image from cache
uses: actions/cache/restore@v4
with:
fail-on-cache-miss: true
key: ${{ github.run_id }}-app-image-${{ matrix.arch }}
path: app-image.tar.zst
- name: Load and Push Application Image
run: |
zstd -dc --long=31 app-image.tar.zst | docker load
IMAGE_NAME_LOWER=$(echo "${{ env.IMAGE_NAME }}" | tr '[:upper:]' '[:lower:]')
docker push ${{ env.REGISTRY }}/${IMAGE_NAME_LOWER}:${{ github.sha }}_linux-${{ matrix.arch }}
create_manifest:
runs-on: ubuntu-24.04
needs: push_application_image
if: success() && github.ref == 'refs/heads/main'
steps:
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Create and push manifest lists
run: |
# Create manifest for commit SHA
IMAGE_NAME_LOWER=$(echo "${{ env.IMAGE_NAME }}" | tr '[:upper:]' '[:lower:]')
docker manifest create ${{ env.REGISTRY }}/${IMAGE_NAME_LOWER}:${{ github.sha }} \
${{ env.REGISTRY }}/${IMAGE_NAME_LOWER}:${{ github.sha }}_linux-amd64 \
${{ env.REGISTRY }}/${IMAGE_NAME_LOWER}:${{ github.sha }}_linux-arm64
docker manifest push ${{ env.REGISTRY }}/${IMAGE_NAME_LOWER}:${{ github.sha }}
# Create manifest for latest tag
docker manifest create ${{ env.REGISTRY }}/${IMAGE_NAME_LOWER}:latest \
${{ env.REGISTRY }}/${IMAGE_NAME_LOWER}:${{ github.sha }}_linux-amd64 \
${{ env.REGISTRY }}/${IMAGE_NAME_LOWER}:${{ github.sha }}_linux-arm64
docker manifest push ${{ env.REGISTRY }}/${IMAGE_NAME_LOWER}:latest