Multi-arch images with Buildah

Buildah allows you to create container images without the need for a full container runtime. Buildah is an open-source Linux-based tool that can create Docker and Kubernetes-compatible images. In addition, Buildah can not only create working containers from scratch, but also from an existing Dockerfile. Finally, it can be easily integrated into scripts and build pipelines.

First steps

  1. Set up environment variables

    DEPLOY_USER

    Name of the account.

    DEPLOY_KEY_FILE

    Path to a private SSH key that is to be used for authentication against the server.

    DEPLOY_HOST

    Host name or IP address of the server to be deployed to.

  2. Setting up the CI/CD pipeline

    .gitlab-ci.yml
     1stages:
     2  - build
     3  - deploy
     4
     5build_docker:
     6  stage: build
     7  variables:
     8    DOCKER_STEM: $CI_REGISTRY_IMAGE
     9  image: quay.io/buildah/stable:v1.27
    10  script:
    11    - apk add --no-cache openssh
    12    - chmod 0600 "$DEPLOY_KEY_FILE"
    13    - ./build.sh
    14
    15deploy_app:
    16  stage: deploy
    17  image: alpine
    18  environment:
    19    name: app
    20    deployment_tier: staging
    21  when: manual
    22  script:
    23    - apk add --no-cache openssh
    24    - chmod 0600 "$DEPLOY_KEY"
    25    - ./deploy.sh
    
  3. Building the Docker container

    build.sh
    1# Registry login
    2echo "$CI_REGISTRY_PASSWORD" | buildah login -u "$CI_REGISTRY_USER" --password-stdin "$CI_REGISTRY"
    3
    4# Set docker tag
    5if [ "$CI_COMMIT_BRANCH" == main ]; then export DOCKER_TAG="latest"; else export DOCKER_TAG="${CI_COMMIT_TAG:-$CI_COMMIT_REF_SLUG}"; fi; export DOCKER_TAG_FULL="$DOCKER_STEM:$DOCKER_TAG"; echo "DOCKER_TAG_FULL=$DOCKER_TAG_FULL"
    6
    7# Build and push
    8buildah build --isolation chroot --storage-driver vfs --jobs 2 --platform linux/amd64,linux/arm/v7 --manifest "$DOCKER_TAG_FULL" && buildah --storage-driver vfs images && buildah manifest push --storage-driver vfs --format v2s2 --all "$DOCKER_TAG_FULL" "docker://$DOCKER_TAG_FULL"
    
    Line 2

    logs in to the GitLab Package Registry.

    Line 5

    identifies the images by their branch or tag names with the exception of main, which is labelled with latest.

    Line 8

    builds the images and deploys them with the VFS driver.

  4. Deploy

    deploy.sh
    1# Set docker tag
    2if [ "$CI_COMMIT_BRANCH" == main ]; then export DOCKER_TAG="latest"; else export DOCKER_TAG="${CI_COMMIT_TAG:-$CI_COMMIT_REF_SLUG}"; fi; export DOCKER_TAG_FULL="$DOCKER_STEM:$DOCKER_TAG"; echo "DOCKER_TAG_FULL=$DOCKER_TAG_FULL"
    3
    4echo "$CI_REGISTRY $DEPLOY_USER $DEPLOY_PASSWORD MYAPP $DOCKER_TAG" | ssh -o 'BatchMode yes' -o 'StrictHostKeyChecking accept-new' -i "$DEPLOY_KEY" root@$DEPLOY_HOST