Skip to content

Commit 4694e65

Browse files
authored
Add helper image for RHEL (#74)
The change creates a helper image based on RHEL UBI. The Docker image adds back a RHEL repo that contains the packages we need to build and sign an .rpm installer for `rippled`. As credentials are needed to add the repo, which will not be available in forks, this helper image will therefore allow external contributors to modify our RHEL image without needing access to the credentials.
1 parent c00f7ca commit 4694e65

File tree

3 files changed

+279
-0
lines changed

3 files changed

+279
-0
lines changed

.github/workflows/rhel-ubi.yml

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
name: RHEL UBI
2+
3+
on:
4+
pull_request:
5+
paths:
6+
- .github/workflows/rhel-ubi.yml
7+
- docker/rhel-ubi/Dockerfile
8+
push:
9+
branches:
10+
- main
11+
paths:
12+
- .github/workflows/rhel-ubi.yml
13+
- docker/rhel-ubi/Dockerfile
14+
workflow_dispatch:
15+
16+
concurrency:
17+
group: ${{ github.workflow }}-${{ github.ref }}
18+
cancel-in-progress: true
19+
20+
defaults:
21+
run:
22+
shell: bash
23+
24+
env:
25+
PUSH: ${{ github.event_name == 'push' }}
26+
CONTAINER_REGISTRY: ghcr.io
27+
BUILDKIT_PROGRESS: plain
28+
29+
jobs:
30+
# Build the Docker image for the Red Hat Enterprise Linux image based on their
31+
# free Universal Binary Image, which contains a subset of feature. We modify
32+
# this image by adding back a package repository that contains dependencies we
33+
# need.
34+
# Note, the `os` part of matrix must be kept in sync with the `merge` job below
35+
build:
36+
strategy:
37+
matrix:
38+
architecture:
39+
- platform: linux/amd64
40+
runner: ubuntu-24.04
41+
name: x86_64
42+
- platform: linux/arm64
43+
runner: ubuntu-24.04-arm
44+
name: aarch64
45+
os:
46+
- release: 8
47+
- release: 9
48+
- release: 10
49+
runs-on: ${{ matrix.architecture.runner }}
50+
permissions:
51+
packages: write
52+
steps:
53+
- name: Checkout repository
54+
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
55+
- name: Set up Docker Buildx
56+
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
57+
- name: Login to GitHub Registry
58+
if: ${{ github.event_name == 'push' }}
59+
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
60+
with:
61+
registry: ${{ env.CONTAINER_REGISTRY }}
62+
username: ${{ github.repository_owner }}
63+
password: ${{ secrets.GITHUB_TOKEN }}
64+
- name: Prepare environment
65+
run: |
66+
# Convert the repository name to lowercase as the organization name is
67+
# uppercase, which is not permitted by the Docker registry. It's 2025 and GitHub
68+
# still does not provide convenient action expression syntax for lowercase.
69+
GITHUB_REPO=${{ github.repository }}
70+
CONTAINER_REPO=${GITHUB_REPO@L}
71+
echo "CONTAINER_REPOSITORY=${CONTAINER_REPO}/rhel-${{ matrix.os.release }}" >> $GITHUB_ENV
72+
echo "CONTAINER_IMAGE=${CONTAINER_REGISTRY}/${CONTAINER_REPO}/rhel-${{ matrix.os.release }}" >> $GITHUB_ENV
73+
PLATFORM=${{ matrix.architecture.platform }}
74+
echo "PLATFORM_PAIR=${PLATFORM//\//-}" >> $GITHUB_ENV
75+
- name: Prepare container metadata
76+
id: meta
77+
uses: docker/metadata-action@c1e51972afc2121e065aed6d45c65596fe445f3f # v5.8.0
78+
env:
79+
DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,manifest-descriptor
80+
with:
81+
images: ${{ env.CONTAINER_IMAGE }}
82+
tags: |
83+
type=raw,value=ubi
84+
type=sha,prefix=ubi-sha-
85+
labels: |
86+
org.opencontainers.image.authors=For inquiries, please use https://${{ github.repository }}/issues
87+
org.opencontainers.image.documentation=https://${{ github.repository }}
88+
org.opencontainers.image.vendor=XRPLF
89+
org.opencontainers.image.title=${{ env.CONTAINER_REPOSITORY }}
90+
- name: Build and push the Docker image
91+
id: build
92+
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
93+
with:
94+
build-args: |
95+
BUILDKIT_DOCKERFILE_CHECK=skip=InvalidDefaultArgInFrom
96+
BUILDKIT_INLINE_CACHE=1
97+
RHEL_ARCH=${{ matrix.architecture.name }}
98+
RHEL_VERSION=${{ matrix.os.release }}
99+
context: .
100+
file: docker/rhel-ubi/Dockerfile
101+
outputs: type=image,name=${{ env.CONTAINER_IMAGE }},push-by-digest=true,name-canonical=true,push=${{ env.PUSH }}
102+
platforms: ${{ matrix.architecture.platform }}
103+
provenance: mode=max
104+
push: ${{ env.PUSH }}
105+
sbom: true
106+
secrets: |
107+
"RHEL_KEY=${{ secrets.RHEL_KEY }}"
108+
"RHEL_ORG=${{ secrets.RHEL_ORG }}"
109+
labels: ${{ steps.meta.outputs.labels }}
110+
- name: Export digest
111+
if: ${{ env.PUSH }}
112+
run: |
113+
mkdir -p /tmp/digests
114+
DIGEST="${{ steps.build.outputs.digest }}"
115+
touch "/tmp/digests/${DIGEST#sha256:}"
116+
- name: Upload digest
117+
if: ${{ env.PUSH }}
118+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
119+
with:
120+
name: digests-${{ matrix.os.release }}-${{ env.PLATFORM_PAIR }}
121+
path: /tmp/digests/*
122+
if-no-files-found: error
123+
retention-days: 1
124+
125+
merge:
126+
if: ${{ github.event_name == 'push' }}
127+
strategy:
128+
matrix:
129+
os:
130+
- release: 8
131+
- release: 9
132+
- release: 10
133+
runs-on: ubuntu-24.04
134+
needs:
135+
- build
136+
permissions:
137+
packages: write
138+
steps:
139+
- name: Checkout repository
140+
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
141+
- name: Download digests
142+
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
143+
with:
144+
path: /tmp/digests
145+
pattern: digests-${{ matrix.os.release }}-*
146+
merge-multiple: true
147+
- name: Set up Docker Buildx
148+
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
149+
- name: Login to GitHub Registry
150+
if: ${{ github.event_name == 'push' }}
151+
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
152+
with:
153+
registry: ${{ env.CONTAINER_REGISTRY }}
154+
username: ${{ github.repository_owner }}
155+
password: ${{ secrets.GITHUB_TOKEN }}
156+
- name: Prepare environment
157+
run: |
158+
GITHUB_REPO=${{ github.repository }}
159+
CONTAINER_REPO=${GITHUB_REPO@L}
160+
echo "CONTAINER_IMAGE=${CONTAINER_REGISTRY}/${CONTAINER_REPO}/rhel-${{ matrix.os.release }}" >> $GITHUB_ENV
161+
- name: Prepare container metadata
162+
id: meta
163+
uses: docker/metadata-action@c1e51972afc2121e065aed6d45c65596fe445f3f # v5.8.0
164+
env:
165+
DOCKER_METADATA_ANNOTATIONS_LEVELS: index
166+
with:
167+
images: ${{ env.CONTAINER_IMAGE }}
168+
tags: |
169+
type=raw,value=ubi
170+
type=sha,prefix=ubi-sha-
171+
- name: Create manifest list and push
172+
working-directory: /tmp/digests
173+
run: |
174+
eval "docker buildx imagetools create \
175+
$(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
176+
$(jq -cr '.annotations | map("--annotation \"" + . + "\"") | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
177+
$(printf '${{ env.CONTAINER_IMAGE }}@sha256:%s ' *)"
178+
- name: Inspect image
179+
run: |
180+
docker buildx imagetools inspect ${{ env.CONTAINER_IMAGE }}:${{ steps.meta.outputs.version }}

docker/rhel-ubi/Dockerfile

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
ARG RHEL_VERSION
2+
FROM registry.access.redhat.com/ubi${RHEL_VERSION}/ubi:latest AS ubi
3+
4+
# This is not inherited from the base image.
5+
ARG RHEL_VERSION
6+
# The RHEL architecture should be either 'x86_64' or 'aarch64'.
7+
ARG RHEL_ARCH
8+
9+
# Enable the repository containing packages we need that are missing from the
10+
# UBI image.
11+
RUN --mount=type=secret,id=RHEL_KEY,env=RHEL_KEY \
12+
--mount=type=secret,id=RHEL_ORG,env=RHEL_ORG \
13+
subscription-manager register --activationkey="${RHEL_KEY}" --org="${RHEL_ORG}" && \
14+
subscription-manager repos --enable=rhel-${RHEL_VERSION}-for-${RHEL_ARCH}-appstream-rpms

docker/rhel-ubi/README.md

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
## RHEL-UBI: A helper Docker image for RHEL
2+
3+
We are providing a helper Docker image for building `rippled` on Red Hat
4+
Enterprise Linux (RHEL) systems. The image is based on the Universal Base Image
5+
(UBI) provided by Red Hat, which is freely available to everyone. However, they
6+
contain a subset of RHEL content, and for our purposes some content is missing.
7+
8+
The helper Docker image adds back a RHEL repo that contains the packages we need
9+
to build and sign an .rpm installer for `rippled`. As credentials are needed to
10+
add the repo, which will not be available in forks, this helper image will
11+
therefore allow external contributors to modify our RHEL image without needing
12+
access to the credentials.
13+
14+
### Obtaining Red Hat credentials
15+
16+
To be able to add the RHEL repo to the UBI image, an activation key is needed,
17+
which can be obtained free of charge. First you need to register for a Developer
18+
account [here](https://developers.redhat.com), and then you can create an activation key
19+
[here](https://console.redhat.com/insights/connector/activation-keys). On that
20+
same page you will find your organization ID.
21+
22+
### Building the Docker image
23+
24+
In order to build an image, run the commands below from the root directory of
25+
the repository.
26+
27+
```shell
28+
export RHEL_KEY=<value-of-rhel-key>
29+
export RHEL_ORG=<value-of-rhel-org>
30+
RHEL_ARCH=<x86_64 or aarch64>
31+
RHEL_VERSION=8
32+
CONTAINER_IMAGE=ghcr.io/xrplf/ci/rhel-${RHEL_VERSION}:ubi
33+
34+
docker buildx build . \
35+
--file docker/rhel-ubi/Dockerfile \
36+
--build-arg BUILDKIT_DOCKERFILE_CHECK=skip=InvalidDefaultArgInFrom \
37+
--build-arg BUILDKIT_INLINE_CACHE=1 \
38+
--secret id=RHEL_KEY,env=RHEL_KEY \
39+
--secret id=RHEL_ORG,env=RHEL_ORG \
40+
--build-arg RHEL_ARCH=${RHEL_ARCH} \
41+
--build-arg RHEL_VERSION=${RHEL_VERSION} \
42+
--tag ${CONTAINER_IMAGE}
43+
```
44+
45+
### Pushing the Docker image
46+
47+
#### Logging into the GitHub registry
48+
49+
To be able to push a Docker image to the GitHub registry, a personal access
50+
token is needed, see instructions [here](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry#authenticating-with-a-personal-access-token-classic).
51+
In summary, if you do not have a suitable personal access token, generate one
52+
[here](https://github.com/settings/tokens/new?scopes=write:packages).
53+
54+
```shell
55+
GITHUB_USER=<your-github-username>
56+
GITHUB_TOKEN=<your-github-personal-access-token>
57+
echo ${GITHUB_TOKEN} | docker login ghcr.io -u "${GITHUB_USER}" --password-stdin
58+
```
59+
60+
#### Pushing to the GitHub registry
61+
62+
To push the image to the GitHub registry, you can do so with the following
63+
command, whereby we append your username to not overwrite existing images:
64+
65+
```shell
66+
docker tag ${CONTAINER_IMAGE} ${CONTAINER_IMAGE}-${GITHUB_USER}
67+
docker push ${CONTAINER_IMAGE}-${GITHUB_USER}
68+
```
69+
70+
However, there should be no need to push the RHEL UBI image manually, as it is
71+
only used as a base image for other images in this repository.
72+
73+
Note, if you or the CI pipeline are pushing an image for the first time, it will
74+
be private by default. You will need to go to the
75+
[packages page](https://github.com/orgs/XRPLF/packages), select the relevant
76+
package, then "Package settings", and after clicking the "Change visibility"
77+
button make it "Public". In addition, on that same page, under "Manage Actions
78+
access" click the "Add repository" button, select the `ci` repository, and grant
79+
it "Admin" access.
80+
81+
#### Note on macOS
82+
83+
If you are using macOS and wish to push an image to the GitHub registry for use
84+
in GitHub Actions, you will need to append `--platform linux/amd64` to the
85+
`docker buildx build` commands above.

0 commit comments

Comments
 (0)