Overview
The repository provides scripts and workflows to:
- Build AlmaLinux Container Images (Docker Images)
- Test these images
- Push them into different registries, the Client Library:
- Extract root filesystem (RootFS) from default and minimal images
- Publish the images to the Docker Official Library.
These Container Images can be used with all OCI complaint container runtime environments such as Docker, Podman and Kubernetes as well as serve as drop-in replacements for CentOS images as they reach End of Life.
Requirements/Prerequisites
Personal, Organization or Enterprise account on GitHub is the only requirement. Please read more about accounts on GitHub.
The idea
The project utilizes GitHub Actions to provide public, transparent and fast workflows that are easy to understand, use and modify.
There are two workflows on GitHub Actions designed to achieve the idea:
- Build, test, push all types of container images into the Client Library, and extract RootFS from
defaultandminimalimages. The workflow can be initiated manually, or runs as scheduled action. - Use these RootFS to request Docker to create images for the Official Library.
You can read more about how the workflows work in the section below.
The AlmaLinux Client Library includes the following registries/organizations:
- Docker.io/almalinux (Sponsored OSS)
- Quay.io/almalinuxorg
- Ghcr.io/AlmaLinux
The AlmaLinux Official Library is maintained by Docker.
Containerfiles
Each image pushed to the Client Library is built from a corresponding Containerfile that is a unique file for each AlmaLinux release and configuration type: base, default, init, micro, minimal.
These files match Dockerfile standard and contain commands and instructions on how to install AlmaLinux's whole root filesystem in them.
Images for the Docker Official Library are built using other Dockerfiles that are also designed for each AlmaLinux release but only default and minimal types:
- 8 default and minimal per platform;
- 9 default and minimal per platform;
- Kitten default and minimal per platform.
These Dockerfiles are to build images from scratch using platform's corresponding RootFS.
What Container Images are built
AlmaLinux releases
Container images are built for AlmaLinux OS 8, 9, Kitten and 10. The Major version of the release must be set for the Build, Test and Push workflow. The Minor version is automatically set by the workflow as the latest.
Publish Images workflow pushes build requests to the Docker for all AlmaLinux releases: 8, 9 and Kitten. AlmaLinux OS 10 Docker build requests are pushed as soon as the version is released.
Image configuration types
AlmaLinux container images types match Red Hat Universal Base Image:
basedefault(the image is also available via the Docker Official Library)initmicrominimal(the image is also available via the Docker Official Library)
Additionally, there is another container image type:
toolbox
Supported platforms/architectures
Build, Test and Push workflow builds container images of the following platforms simultaneously with docker buildx. They result in the following machine hardware names (uname -m):
| docker platform | hardware name |
|---|---|
| linux/386 | x86_64 |
| linux/amd64 | x86_64 |
| linux/amd64/v2 | x86_64 (v2) |
| linux/ppc64le | ppc64le |
| linux/s390x | s390x |
| linux/arm64 | aarch64 |
| linux/riscv64 | riscv64 |
linux/amd64/v2 are for AlmaLinux Kitten and 10 releases.
linux/riscv64 are for AlmaLinux Kitten.
linux/386 are for AlmaLinux 8 and 9 releases.
To get packages arch, the rpm -qf --queryformat '%{ARCH}' /etc/almalinux-release command may be used (except for the micro image, where uname -m is used instead).
❗ Please, note, linux/amd64/v2 and linux/386 images are pushed to the Docker's Client Library only, but not to the Official Library .
The containerd image store store for Docker Engine together with buildx are used to build and push multiple platforms at once.
Repositories
The following repositories are created on all registries (Docker.io/almalinux, Quay.io/almalinuxorg, Ghcr.io/AlmaLinux) for all supported images types:
/almalinux- Quay.io/almalinuxorg only. Is built from thedefaultimage./8-base/9-base/10-base/10-kitten-base/8-init/9-init/10-init/10-kitten-init/8-micro/9-micro/10-micro/10-kitten-micro/8-minimal/9-minimal/10-minimal/10-kitten-minimal/8-toolbox/9-toolbox/10-toolbox/10-kitten-toolbox
They are the Client Library.
Tags
The following tags are created under each repository (AlmaLinux 9.3 example as of 24 Nov 2023):
| tag | example |
|---|---|
| latest | latest |
| MAJOR | 9 |
| MAJOR.MINOR | 9.3 |
| MAJOR.MINOR-DATE_STAMP | 9.3-20231124 |
The /almalinux repository includes the latest tag for AlmaLinux release 9.x only.
container-images repository structure
Directories structure
- Branch 'main'
.
├── .github
│ └── workflows
│ ├── build-test-push.yml
│ └── publish-docker-library.yml
├── Containerfiles
│ ├── 10
│ │ ├── Containerfile.base
│ │ ├── Containerfile.default
│ │ ├── Containerfile.init
│ │ ├── Containerfile.micro
│ │ ├── Containerfile.minimal
│ │ └── Containerfile.toolbox
│ ├── 10-kitten
│ │ ├── Containerfile.base
│ │ ├── Containerfile.default
│ │ ├── Containerfile.init
│ │ ├── Containerfile.micro
│ │ ├── Containerfile.minimal
│ │ └── Containerfile.toolbox
│ ├── 8
│ │ ├── Containerfile.base
│ │ ├── Containerfile.default
│ │ ├── Containerfile.init
│ │ ├── Containerfile.micro
│ │ ├── Containerfile.minimal
│ │ └── Containerfile.toolbox
│ └── 9
│ ├── Containerfile.base
│ ├── Containerfile.default
│ ├── Containerfile.init
│ ├── Containerfile.micro
│ ├── Containerfile.minimal
│ └── Containerfile.toolbox
├── LICENSE
└── README.md- Branch for AlmaLinux release '8'
.
├── docker-library-definition.tmpl
│
├── default
│ ├── 386
│ │ ├── Dockerfile
│ │ └── almalinux-8-default-386.tar.gz
│ ├── amd64
│ │ ├── Dockerfile
│ │ └── almalinux-8-default-amd64.tar.gz
│ ├── arm64
│ │ ├── Dockerfile
│ │ └── almalinux-8-default-arm64.tar.gz
│ ├── ppc64le
│ │ ├── Dockerfile
│ │ └── almalinux-8-default-ppc64le.tar.gz
│ └── s390x
│ ├── Dockerfile
│ └── almalinux-8-default-s390x.tar.gz
└── minimal
├── 386
│ ├── Dockerfile
│ └── almalinux-8-minimal-386.tar.gz
├── amd64
│ ├── Dockerfile
│ └── almalinux-8-minimal-amd64.tar.gz
├── arm64
│ ├── Dockerfile
│ └── almalinux-8-minimal-arm64.tar.gz
├── ppc64le
│ ├── Dockerfile
│ └── almalinux-8-minimal-ppc64le.tar.gz
└── s390x
├── Dockerfile
└── almalinux-8-minimal-s390x.tar.gz- Branch for AlmaLinux release '9'
.
├── docker-library-definition.tmpl
│
├── default
│ ├── 386
│ │ ├── Dockerfile
│ │ └── almalinux-9-default-386.tar.gz
│ ├── amd64
│ │ ├── Dockerfile
│ │ └── almalinux-9-default-amd64.tar.gz
│ ├── arm64
│ │ ├── Dockerfile
│ │ └── almalinux-9-default-arm64.tar.gz
│ ├── ppc64le
│ │ ├── Dockerfile
│ │ └── almalinux-9-default-ppc64le.tar.gz
│ └── s390x
│ ├── Dockerfile
│ └── almalinux-9-default-s390x.tar.gz
└── minimal
├── 386
│ ├── Dockerfile
│ └── almalinux-9-minimal-386.tar.gz
├── amd64
│ ├── Dockerfile
│ └── almalinux-9-minimal-amd64.tar.gz
├── arm64
│ ├── Dockerfile
│ └── almalinux-9-minimal-arm64.tar.gz
├── ppc64le
│ ├── Dockerfile
│ └── almalinux-9-minimal-ppc64le.tar.gz
└── s390x
├── Dockerfile
└── almalinux-9-minimal-s390x.tar.gz- Branch for AlmaLinux release '10'
.
├── docker-library-definition.tmpl
├── default
│ ├── amd64
│ │ ├── Dockerfile
│ │ └── almalinux-10-default-amd64.tar.gz
│ ├── amd64_v2
│ │ ├── Dockerfile
│ │ └── almalinux-10-default-amd64_v2.tar.gz
│ ├── arm64
│ │ ├── Dockerfile
│ │ └── almalinux-10-default-arm64.tar.gz
│ ├── ppc64le
│ │ ├── Dockerfile
│ │ └── almalinux-10-default-ppc64le.tar.gz
│ └── s390x
│ ├── Dockerfile
│ └── almalinux-10-default-s390x.tar.gz
└── minimal
├── amd64
│ ├── Dockerfile
│ └── almalinux-10-minimal-amd64.tar.gz
├── amd64_v2
│ ├── Dockerfile
│ └── almalinux-10-minimal-amd64_v2.tar.gz
├── arm64
│ ├── Dockerfile
│ └── almalinux-10-minimal-arm64.tar.gz
├── ppc64le
│ ├── Dockerfile
│ └── almalinux-10-minimal-ppc64le.tar.gz
└── s390x
├── Dockerfile
└── almalinux-10-minimal-s390x.tar.gz- Branch for AlmaLinux Kitten
.
├── docker-library-definition.tmpl
├── default
│ ├── amd64
│ │ ├── Dockerfile
│ │ └── almalinux-10-kitten-default-amd64.tar.gz
│ ├── amd64_v2
│ │ ├── Dockerfile
│ │ └── almalinux-10-kitten-default-amd64_v2.tar.gz
│ ├── arm64
│ │ ├── Dockerfile
│ │ └── almalinux-10-kitten-default-arm64.tar.gz
│ ├── ppc64le
│ │ ├── Dockerfile
│ │ └── almalinux-10-kitten-default-ppc64le.tar.gz
│ ├── riscv64
│ │ ├── Dockerfile
│ │ └── almalinux-10-kitten-default-riscv64.tar.gz
│ └── s390x
│ ├── Dockerfile
│ └── almalinux-10-kitten-default-s390x.tar.gz
└── minimal
├── amd64
│ ├── Dockerfile
│ └── almalinux-10-kitten-minimal-amd64.tar.gz
├── amd64_v2
│ ├── Dockerfile
│ └── almalinux-10-kitten-minimal-amd64_v2.tar.gz
├── arm64
│ ├── Dockerfile
│ └── almalinux-10-kitten-minimal-arm64.tar.gz
├── ppc64le
│ ├── Dockerfile
│ └── almalinux-10-kitten-minimal-ppc64le.tar.gz
├── riscv64
│ ├── Dockerfile
│ └── almalinux-10-kitten-minimal-riscv64.tar.gz
└── s390x
├── Dockerfile
└── almalinux-10-kitten-minimal-s390x.tar.gzWorkflow *.yml files
The .github/workflows/build-test-push.yml workflow is used to Build, Test and Push images to the Client Library, and extract RootFS:
name: Build, test and push to the Client Library on: workflow_dispatch: inputs: production: description: | 'Push to production registries' 'not checked - to testing' required: true type: boolean default: true ...
The
.github/workflows/publish-docker-library.yml workflow is used to Publish Images to the Docker Official Library:
name: Publish images to the Docker Library on: workflow_dispatch: inputs: pr: description: 'Publish to Docker Official Library' required: true type: boolean default: true ...
Both workflows are triggered manually by the workflow_dispatch event of GitHub Actions.
Sourced Containerfiles
This Containerfiles/9/Containerfile.minimal file is a Containerfile example for AlmaLinux release 9 and minimal type used to build container image for the Client Library:
ARG SYSBASE=almalinux:9 FROM ${SYSBASE} as system-build RUN mkdir /mnt/sys-root; \ dnf install -y \ --installroot /mnt/sys-root \ --releasever 9 \ --setopt install_weak_deps=false \ --nodocs \ almalinux-release \ bash \ ... FROM scratch COPY --from=system-build /mnt/sys-root/ / CMD ["/bin/bash"]
This minimal/amd64/Dockerfile file is a Dockerfile example for AlmaLinux release 9 minimal type and amd64 (x86_64) platform used to build container image for the Docker Official Library:
# Tags: minimal, 9-minimal, 9.3-minimal, 9.3-minimal-20231124 FROM scratch ADD almalinux-9-minimal-amd64.tar.xz / CMD ["/bin/bash"]
Template file for Docker Library Definition
The Docker Official Library uses Definition File to request building of official images. Changing the file triggers a new image(s) building on the Docker side. The docker-library-definition.tmpl template is used to generate the Definition file:
Tags: {{ .tags }} GitFetch: refs/heads/{{ .version_major }} GitCommit: {{ .commit_hash }} amd64-Directory: {{ .image_type }}/amd64/ arm64v8-Directory: {{ .image_type }}/arm64/ ppc64le-Directory: {{ .image_type }}/ppc64le/ s390x-Directory: {{ .image_type }}/s390x/ Architectures: amd64, arm64v8, ppc64le, s390x
❗ Please, note, linux/amd64/v2 and linux/386 images are pushed to the Docker's Client Library only, but not to the Official Library .
How to contribute/help and customize workflow(s)
Fork GitHub repositories
Fork the following repositories:
- container-images, you will need the
main,8,9,10and10-kittenbranches. - docker-library
Read more about GitHub forks here.
❗ Please, note, that you won't be able to create a Pull Request to this repository as only AlmaLinux organization members have access to do it.
Set Action's secrets
To set secrets needed for this repository, go to your GitHub account Settings -> expand Secrets and variables (located under the Security section) -> select Actions. Read more about Github Secrets in Actions.
The following Repository secrets are required. Set them with your personal data.
For production Client Library please define secrets, only for registries you are using
| Secret name | Description |
|---|---|
DOCKERHUB_USERNAME |
docker.io user |
DOCKERHUB_TOKEN |
docker.io token |
QUAY_IO_USERNAME |
quay.io user |
QUAY_IO_CLI_PASSWORD |
quay.io CLI password |
GIT_HUB_USERNAME |
GitHub user |
GIT_HUB_TOKEN |
GitHub token |
The same secrets with TEST_ prefix in secret names (like TEST_DOCKERHUB_USERNAME) should be set for corresponded registries if testing Client Library (testing mode).
On how to create tokens/CLI passwords please read:
- Manage Quay.io Access Tokens
- Create and manage access tokens on Docker
- Managing your personal access tokens on GitHub.
When creating a new personal access token on GitHub, please, select:
- write:packages scope, to allow packages uploading to GitHub Package Registry;
- admin:org scope, to allow Pull Request creation to docker-library.
To work with Mattermost
| Secret name | Description |
|---|---|
MATTERMOST_WEBHOOK_URL |
Webhook URL for your Mattermost |
Set Action's variables
To work with Mattermost
| Variable name | Description |
|---|---|
MATTERMOST_CHANNEL |
Mattermost channel name |
Change registries list
On needed registries create your own accounts in case you don't have any as you won't be able to use AlmaLinux accounts.
According to your list of needed registries and knowing your user names edit the .github/workflows/build-test-push.yml workflow file (branch master) and set list for both production and testing Client Library:
registries_production: 'docker.io/<user_name>, quay.io/<user_name>, ghcr.io/<user_name>' registries_testing: 'docker.io/<user_name>, quay.io/<user_name>, ghcr.io/<user_name>'
<user_name> - is your user name on the specific registry.
Separate the registries with commas. At least one registry in each list is required.
Change platforms list
If you don't need to build images for all platforms, you can edit the list of platforms to meet your needs in the .github/workflows/build-test-push.yml workflow file (branch master):
platforms: 'linux/amd64, linux/ppc64le, linux/s390x, linux/arm64'
Separate the platforms with commas. At least one platform in the list is required.
Change image types list
Edit the .github/workflows/build-test-push.yml workflow file (branch master) to change type of images which are built:
- (workflow dispatch) add/modify/delete input for specific type name of image:
type_<type_name>: description: '<type_name>' required: true type: boolean
- (workflow dispatch) add/modify/delete the image type for the build matrix:
workflow_dispatch) ... echo "image_types_matrix=$(jq -c <<< '[${{ format('"{0}"', ( inputs.type_default && '<type_name>' ) ) }}]')" >> $GITHUB_OUTPUT
- (scheduled workflow) add/modify/delete from the list. Separate types with comma. Enclose each type into
":
env: ... image_types: '"<type_name>", "<type_name>"'
Where <type_name> is the name of your image type.
Default are: base, default, init, micro, minimal, toolbox
To bump AlmaLinux release (Major number)
If a new AlmaLinux major release is available, edit the .github/workflows/build-test-push.yml workflow file (branch master), to set this major version:
- (workflow dispatch)
inputs.version_majorlike:
version_major: description: 'AlmaLinux major version' required: true default: '<version_latest>' type: choice options: - <version_latest> - 9 - 8
- (scheduled workflow)
env.versions_list. Separate types with comma. Enclose each version into":
env: ... versions_list: '"8", "9", "<version_latest>"'
env.version_latestlike:
version_latest: <version_latest>
Where <version_latest> is an AlmaLinux version major version, for example 10.
To bump AlmaLinux release (Minor number)
If a new AlmaLinux minor release is available, edit the .github/workflows/build-test-push.yml workflow file (branch master) to set it. To do so, you need the "DeployPrepare AlmaLinux Minor version number" step:
case ${{ inputs.version_major }} in 8) version_minor="<8_minor>" ;; 9) version_minor="<9_minor>" ;; 10) version_minor="<10_minor>" ;;
Where <8_minor>, <9_minor>, <10_minor> are AlmaLinux's corresponding minor versions.
For example Minors are 10, 4 or 1 for new 8.10, 9.4 or 10.1 versions respectively.
To change scheduled time
The workflow is designed to run every day at 04:00 UTC. To change, edit the .github/workflows/build-test-push.yml workflow file (branch master) and set the time in Unix cron format, like:
schedule: # run every day at 04:00 UTC - cron: '00 04 * * *'
Restrictions
❗ Only AlmaLinux organization members have access to create Pull Requests and publish container images into the Docker Official Library.
❗ Build, test and push to the Client Library workflow will work only for your Client Library, but not for AlmaLinux-owned ones.
Workflows jobs and steps
Build, test and push to the Client Library
Tree illustration of the workflow Jobs and Steps for AlmaLinux 9 minimal image:
Build, test and push to the Client Library
│
├── Set matrix, prepare variables
│ ├── Set up job
│ ├── Set matrix, prepare variables
│ └── Complete job
│
├── Deploy 9 minimal images
│ ├── Set up job
│ ├── Prepare AlmaLinux Minor version number
│ ├── Check update
│ ├── Set platforms and registries
│ ├── Generate list of Docker images to use as base name for tags
│ ├── Enable containerd image store on Docker Engine
│ ├── Checkout _container-images, branch 'main'
│ ├── Checkout _container-images, branch '9', path '9'
│ ├── Set up QEMU
│ ├── Set up Docker Buildx
│ ├── Login to Docker.io
│ ├── Login to Quay.io
│ ├── Login to Ghcr.io
│ ├── Generate tags and prepare metadata to build and push
│ ├── Build images
│ ├── Test images
│ ├── Push images to Client Library
│ ├── Generate Docker Hub README
│ ├── Update Docker Hub repository description
│ ├── Prepare Mattermost message
│ ├── Upload Mattermost message artifacts
│ ├── Extract RootFS (default and minimal only)
│ ├── Change date stamp in Dockerfile (default and minimal only)
│ ├── Commit and push minimal/*/* Dockerfile and RootFS (branch 9)"
│ ├── Post Push images to Client Library
│ ├── Post Build images
│ ├── Post Login to Ghcr.io
│ ├── Post Set up Docker Buildx
│ ├── Post Checkout _container-images, branch '9', path '9'
│ ├── Post Checkout _container-images, branch 'main'
│ └── Complete job
│
├── Mattermost notification (9)
│ ├── Download Mattermost message artifacts
│ ├── Create Mattermost message
│ └── Send notification to Mattermost
│
└── Optimize size of repository, branch '9'
├── Set up job
├── Checkout almalinux/container-images, branch '9', path '9'
├── Optimize size of branch the '9'
├── Commit and push almalinux/container-images, branch '9'
└── Complete job
Inputs for workflow dispatch
The workflow inputs are:
-
production- boolean 'Push to production registries' with the default valuetrue(checked). Container images are pushed into the production Client Library: Docker.io/almalinux, Quay.io/almalinuxorg and Ghcr.io/AlmaLinux. Otherwise, images are pushed into the testing Client Library: Quay.io/almalinuxautobot -
notify_mattermost- boolean 'Send notification to Mattermost' with the default valuefalse(not checked). Determines whether to send notification to channelvars.MATTERMOST_CHANNELusingsecrets.MATTERMOST_WEBHOOK_URL -
Checklist of image types: base, default, init, micro, minimal, toolbox. At least one should be checked.
-
version_major- dropdown 'AlmaLinux major version' with the default value9. This is a major number of AlmaLinux version to build images for.
Environment variables which affect all jobs
-
version_latest- AlmaLinux version for which thelatesttag is set. Now is set to9 -
platforms- comma separated list of platforms -
registries_production- comma separated list of production Client Library to push images -
registries_testing- comma separated list of testing Client Library to push images
Job: Set matrix, prepare variables
Step: Set matrix, prepare variables
The step sets:
-
matrix for the 'Deploy version_major image_types images' job based on image types from
type_*inputs for workflow dispatch, or predefined viaimage_typesenvironment variable for scheduled workflow -
matrix based on version_major from
version_majorinput for workflow dispatch, or predefined versions viaversions_listenvironment variable for scheduled workflow -
production- environment variable value based on corresponded inputtrueorfalsefor workflow dispatch, or with defaultfalsevalue for scheduled workflow -
notify_mattermost- environment variable value based on corresponded inputtrueorfalsefor workflow dispatch, or with defaulttruevalue for scheduled workflow -
date_time_stamp- in format %Y%m%d%H%M%S, used for Mattermost notifications -
date_stamp- in format YYYYMMDD, used in image tags -
time_stamp- in format %H:%M:%S, used in commit messages
Job: Deploy version_major image_types images
Job proceeds to input version_major and iterates with selected image_types using matrix. Multiple jobs run simultaneously for each image type.
Step: Prepare AlmaLinux Minor version number
The step sets AlmaLinux version_minor according to set on inputs version_major.
Step: Check update
The step runs:
dnf check-update --secseverity=Important
Based on its exit code (please read more at Check-Update Command), determines if there any packages' Important updates are available, and for scheduled workflow continue or not with image(s) building.
Exit codes:
0 - no updates
100 - updates available
125 - tag/platform not found
127 - command not found
255 - workflow_dispatch run
In dispatch mode, image(s) are built regardless of the presence of Important updates.
The command runs inside podman container pulling the most recent quay.io/almalinuxorg/almalinux:${version_major} image.
Step: Set platforms and registries
-
Extends
platformslist withlinux/riscv64andlinux/amd64/v2if Kitten -
Extends
platformslist withlinux/amd64/v2if AlmaLinux 10 -
Extends
platformslist withlinux/386if AlmaLinux 8 or 9 -
Set
registriesintoregistries_productionif production Client Library, and intoregistries_testingif scheduled workflow or testing Client Library.
Step: Generate list of Docker images to use as base name for tags
Generates env.IMAGE_NAMES for each registry including image type like: docker.io/***/8-minimal quay.io/***/8-minimal
Step: Enable containerd image store on Docker Engine
Modifies the /etc/docker/daemon.json as:
"features": { "containerd-snapshotter": true }
Restarts the docker service to get a new image store working.
The successful switch is printed in the docker info:
[[driver-type io.containerd.snapshotter.v1]]Step: Checkout container-images, branch 'main'
Checkouts container-images into branch 'main'. The repository directory is located at /home/runner/work/container-images/container-images. Please note, the only last commit is checked out.
The actions/checkout@v4 is used.
Step: Checkout container-images, branch '${version_major}', path '${version_major}'
Checkouts container-images into branch '${version_major}'. The repository directory is located at /home/runner/work/container-images/${version_major}.
The actions/checkout@v4 is used.
Step: Set up QEMU
Installs QEMU static binaries. The docker/setup-qemu-action@v3 is used. The QEMU static binaries are required to build different platforms within one machine.
Step: Set up Docker Buildx
Sets up Docker Buildx. It uses docker/setup-buildx-action@v3
Step: Login to Docker.io
The docker/login-action@v3 is used. The following secrets are used:
production mode:
- DOCKERHUB_USERNAME
- DOCKERHUB_TOKEN
testing mode:
- TEST_DOCKERHUB_USERNAME
- TEST_DOCKERHUB_TOKEN
Step: Login to Quay.io
The docker/login-action@v3 is used. The following secrets are used:
production mode:
- QUAY_IO_USERNAME
- QUAY_IO_CLI_PASSWORD
testing mode:
- TEST_QUAY_IO_USERNAME
- TEST_QUAY_IO_CLI_PASSWORD
Step: Login to Ghcr.io
The docker/login-action@v3 is used. The following secrets are used:
production mode:
- GIT_HUB_USERNAME
- GIT_HUB_TOKEN
testing mode:
- TEST_GIT_HUB_USERNAME
- TEST_GIT_HUB_TOKEN
Step: Generate tags and prepare metadata to build and push
The docker/metadata-action@v5 is used to generate tags, labels and annotations for images. Here is an example of AlmaLinux 8 minimal image's tags:
"tags": [ "docker.io/***/8-minimal:latest", "docker.io/***/8-minimal:8", "docker.io/***/8-minimal:8.9", "docker.io/***/8-minimal:8.9-20240319", "quay.io/***/8-minimal:latest", "quay.io/***/8-minimal:8", "quay.io/***/8-minimal:8.9", "quay.io/***/8-minimal:8.9-20240319", ],
Step: Build images
The docker/build-push-action@v5 is used to build images. This step builds the images from corresponding Containerfile, for specified env.platforms and uses tags from the previous step. After the successful building, the images are loaded into docker, but not pushed yet as they need to be tested first. AlmaLinux 8 minimal images buildx looks like this:
/usr/bin/docker buildx build --file ./Containerfile.minimal ... \ --platform linux/386,linux/amd64,linux/ppc64le,linux/s390x,linux/arm64 \ --provenance false ... \ --tag docker.io/***/8-minimal:latest --tag docker.io/***/8-minimal:8 --tag docker.io/***/8-minimal:8.9 --tag docker.io/***/8-minimal:8.9-20240319 --tag quay.io/***/8-minimal:latest --tag quay.io/***/8-minimal:8 --tag quay.io/***/8-minimal:8.9 --tag quay.io/***/8-minimal:8.9-20240319 \ --load \ --metadata-file /home/runner/work/_temp/docker-actions-toolkit-*/metadata-file \ https://github.com/***/container-images.git#270a6d3fd433cfa6c3e1fff5896a92d1ae2896be:Containerfiles/8
provenance: false is to disable the Provenance attestations as Quay.io registry doesn't support such kind of images data.
Step: Test images
Every image is tested for each platform by verifying the release string and architecture. The container outputs the content of /etc/almalinux-release and the detected architecture, which is then piped to grep on the host side (to avoid dependency on grep inside the container, e.g. for micro images):
docker run --platform=${platform} ${digest} /bin/bash -c " \ echo \"\$(cat /etc/almalinux-release) \$(${arch_query})\"" | \ grep -E "${release_string}.*${expected_arch}"
For micro images, the architecture is queried via uname -m; for all other types, rpm -qf --queryformat '%{ARCH}' /etc/almalinux-release is used.
Step: Push images to Client Library
The docker/build-push-action@v5 is used. This step pushes built images into Client Library. The options are the same as for Build images step.
Step: Generate Docker Hub README
❗ Skip this step if the image type is 'default' or Docker Hub is not in the registries list.
Generates a dockerhub-readme.md file with current supported tags, supported architectures, and a description of the image type. The tags are extracted from the metadata generated by the Generate tags step, filtered for docker.io entries only.
Step: Update Docker Hub repository description
❗ Skip this step if the image type is 'default' or Docker Hub is not in the registries list.
Uses peter-evans/dockerhub-description@v4 to push the generated README to the Docker Hub repository (e.g. almalinux/9-minimal). This keeps the "Supported tags" and other information on Docker Hub in sync with the actual pushed tags. The following secrets are used:
- DOCKERHUB_USERNAME
- DOCKERHUB_TOKEN
Step: Prepare Mattermost message
Creates two files-artifacts to generate messages to Mattermost (AlmaLinux 9 example):
9_mattermost.md, includes the header of the message with AlmaLinux release, build stamp and platforms list9_${{ matrix.image_types }}_mattermost.mdincludes tags list for specificimage_types
Step: Upload Mattermost message artifacts
Stores files created on the previous step, as workflow artifacts. The actions/upload-artifact is used.
Step: Extract RootFS (default and minimal only)
❗ Skip this step if the image type is not 'default' or 'minimal'.
The step is to extract RootFS from existing image's blobs:
- uses
docker saveto produce a tarred repository and save it to the "tar file". Unpack the "tar file" to get blobs. - Prepares the "temporary Dockerfile" to build image based on RootFS.
FROM scratch ADD rootfs.tar.gz / CMD ["/bin/bash"]
- Loops blobs to find all zipped files that are RootFS for a particular architecture.
- with
docker build, builds an image from the "temporary Dockerfile". - with
docker run, runs the image and queryalmalinux-releasepackage's architecture. - Maps found architecture to the corresponding platform.
- Copes the "taken RootFS" into corresponded .tar.xz (like
almalinux-9-default-amd64.tar.xz)
Step: Change date stamp in Dockerfile (default and minimal only)
❗ Skip this step if the image type is not 'default' or 'minimal'.
The step changes (# Tags with date stamp) in corresponded ${images_type}/${platform}/Docker file for AlmaLinux release 8 an release 9, which Docker will use to build images for the Official Library. An example is for AlmaLinux 9 minimal amd64 minimal/amd64/dockerfile file:
# Tags: 8-minimal, 8.9-minimal, 8.9-minimal-20240319
FROM scratch
ADD almalinux-9-minimal-amd64.tar.xz /
CMD ["/bin/bash"]
The change indicates that a new default and/or minimal container image was pushed to the Client Library and should be requested to be built by Docker. The change will later be committed to the corresponded branch: 8, 9, 10 or 10-kitten.
It will try to pull recent changes (before push) with
--rebase --autostash
Step: Commit and push ${image_types }// Dockerfile and RootFS (branch ${version_major })"
❗ Skip this step if the image type is not 'default' or 'minimal'.
❗ The step is skipped if 'Push to production registries' is not checked (inputs.production set to false.)
Uses EndBug/add-and-commit@v9 to commit and push Dockerfile and RootFS, which were changed and extracted on the previous steps.
The commit message is:
AlmaLinux ${version_major}-${images_type} image build as of ${date_stamp} (with ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}).It includes the AlmaLinux version major, image type, build date, and reference to this GitHub Action.
Job: Mattermost notification
Step: Download Mattermost message artifacts
Downloads all artifacts, generated by the Upload Mattermost message artifacts step of build-test-push job.
The actions/download-artifact is used.
Step: Create Mattermost message
The step sets MATTERMOST_TEXT environment variable from two files-artifacts (AlmaLinux 9 example):
- first occurrence of
mattermost-message-9-*/9_mattermost.mdfile, with heading for the message, and platforms list - all
mattermost-message-9-*/9_*_mattermost.mdfiles, with tags list for each image type
Step: Send notification to Mattermost
The mattermost/action-mattermost-notify@master is used.
Runs only if notify_mattermost input is true (checked) or on scheduled workflow.
Runs with:
MATTERMOST_WEBHOOK_URLworkflow secretMATTERMOST_CHANNELworkflow variableMATTERMOST_USERNAMEset via predefinedgithub.triggering_actorvariableTEXTset viaMATTERMOST_TEXTenvironment variable generated on the previous step
Example of message in a channel about AlmaLinux 9.5, micro image build:
AlmaLinux OS 9.5 Container Image, build 20250411091645, generated by the GitHub Action
Platforms:
linux/386, linux/amd64, linux/ppc64le, linux/s390x, linux/arm64
:almalinux: micro
quay.io/almalinuxorg/9-micro:latest
quay.io/almalinuxorg/9-micro:9
quay.io/almalinuxorg/9-micro:9.5
quay.io/almalinuxorg/9-micro:9.5-20250411
Job: Optimize size of repository, branch '${version_major}'
❗ Skip the job if the image type is not 'default' or 'minimal', or 'Push to production registries' is not checked (inputs.production set to false.)
Step: Checkout almalinux/container-images, branch '${version_major}', path '${version_major}'
The actions/checkout@v4 checkouts container-images into branch '${version_major}'. The repository directory is located at /home/runner/work/container-images/container-images and its subdirectory is named '${version_major}'. All commits for the branch are checkout with fetch-depth: 0.
Step: Optimize size of branch the '${version_major}'
This step is written in bash and is designed to:
- preserves 'default' and 'minimal' folders with Dockerfiles and RootFSs into
../tmp-${date_stamp}folder - checkouts into new local 'tmp' branch
- removes local ${version_major} branch
- checkouts into orphan ${version_major} branch
- restores 'default' and 'minimal' folders into the orphan branch placeholder
Step: Commit and push almalinux/container-images, branch '${version_major}'
Uses EndBug/add-and-commit@v9 to commit and push Dockerfiles and RootFSs which were prepared on previous step. The following options are used to push:
--force- to rewrite history--set-upstream origin ${version_major}- to set upstream branch (as new one is orphan)
Publish images to the Docker Library
Tree illustration of the workflow Jobs and Steps for AlmaLinux 9 minimal image:
Publish images to the Docker Library
│
├── 10-kitten default definition preparing
.
.
.
├── 10-kitten minimal definition preparing
.
.
├── 8 default definition preparing
.
.
.
├── 8 minimal definition preparing
.
.
.
├── 9 default definition preparing
.
.
.
├── 9 minimal definition preparing
│ ├── Set up job
│ ├── Checkout container-images, branch '9'
│ ├── Checkout official-images, branch 'master'
│ ├── Get need data for the definition
│ ├── Render the definition
│ ├── Upload the definition for 9 minimal
│ ├── Post Checkout official-images, branch 'master'
│ ├── Post Checkout container-images, branch '9'
│ └── Complete job
│
└── Create Pull Request with the new definition file
├── Set up job
├── Checkout official-images, branch 'master'
├── Sync official-images with docker-library/official-images, branch 'master'
├── Download all definitions
├── Create head of official-images/library/almalinux
├── Merge definitions into official-images/library/almalinux
├── Prepare date stamp
├── Prepare time stamp
├── Commit and push official-images/library/almalinux
├── Create Pull Request for official-images/library/almalinux
├── Post Checkout official-images, branch 'master'
└── Complete job
Inputs
The workflow inputs are:
-
pr- boolean 'Publish to the Docker Official Library' with the default valuetrue(checked). The input indicates whether to create a Pull Request to Docker with AlmaLinux Definition File. -
draft- boolean 'Draft Pull Request' with the default valuefalse(not checked). The input indicates whether the Pull Request is draft or it is ready to review.
Job: version_major image_types definition preparing
Job iterates (using matrix) with AlmaLinux all version_major, and image_types (default and minimal). Multiple jobs run simultaneously for each of the versions and each of the image types.
Step: Checkout container-images, branch '${version_major}'
The actions/checkout@v4 checkouts container-images into branch '${version_major}'. The repository directory is located at /home/runner/work/container-images/container-images. All commits for the branch are checkout with fetch-depth: 0.
Step: Checkout official-images, branch 'master'
The actions/checkout@v4 checkouts container-images into branch 'master'. The repository directory is located at /home/runner/work/container-images/official-images.
That's your fork of docker-library/official-images repository.
Step: Get need data for the definition
The step is written in bash. It reads the # Tags: string and the commit hash of Containerfiles/${{ matrix.version_major }}/Containerfile.image_types file changed by the Build, test and push workflow. env.tags and env.last_commit are exported. These data will be used to generate part of Definition File.
Step: Render the definition
The chuhlomin/render-template@v1 generates from the docker-library-definition.tmpl using data (env.tags, env.last_commit, matrix.version_major and matrix.image_types) file official-images/library/almalinux.version_major.image_types. The file is a part of Docker Library Definition File.
Step: Upload the definition for version_major image_types
The step uses actions/upload-artifact@v4 to store an artifact generated in the previous step official-images/library/almalinux.version_major.image_types. The artifact is named against version_major and image_type, following the pattern: definition-${version_major}.${image_types}.
Artifacts are used to transfer files between different jobs of the same workflow. The artifact is a zip archive of the file without file-path included.
It is also possible to download artifacts via GitHub Action's web interface.
Job: Create Pull Request with the new definition file
The job is skipped if the 'Publish to Docker Official Library' isn't checked (
inputs.prset intofalse)
Step: Checkout official-images, branch 'master'
The actions/checkout@v4 checkouts container-images into branch 'master'. The repository directory is located at /home/runner/work/container-images/official-images.
That's your fork of docker-library/official-images repository.
Step: Sync official-images with upstream
The step is written in bash. It uses GitHub CLI to sync the docker-library-official-images with the official-images upstream repository.
Step: Download all definitions
Uses actions/download-artifact@v4 to download multiple (merge-multiple: true) artifacts with generated definitions. The files are saved into the official-images/library/ directory.
Step: Create head of official-images/library/almalinux
Creates heading for the Docker Definition File.
Step: Merge definitions into official-images/library/almalinux
The step is written in bash. It appends the official-images/library/almalinux Definition File with downloaded on the previous step definitions official-images/library/almalinux.version_major.image_types.
Step: Prepare date stamp
Generates date_stamp in the YYYYMMDD format. It is used in the commit message and pull request title.
Step: Prepare time stamp
Generates time_stamp in the HH:MM:SS format. It is used in the commit message and pull request title.
Step: Commit and push official-images/library/almalinux
Uses EndBug/add-and-commit@v9 to commit and push the generated Definition File.
The commit message is:
AlmaLinux auto-update - ${{ env.date_stamp }} ${{ env.time_stamp }}.It will try to pull recent changes (before push) with
--rebase --autostash
Step: Create Pull Request for official-images/library/almalinux
The step is written in bash. It uses Github CLI to create a Pull Request for the official-images/library/almalinux Definition File from your fork and to docker-library/official-images repository.
The Pull Request will be drafted if the draft input is checked. When ready, mark the request as ready for review.