From 7081ab905dc9c11d672065e2db27866f3518b4f5 Mon Sep 17 00:00:00 2001 From: sigmalko <188585048+sigmalko@users.noreply.github.com> Date: Tue, 29 Sep 2026 23:02:18 +0200 Subject: [PATCH 1/2] Add GitHub Actions workflow to publish runner image to GHCR --- .github/workflows/publish-image.yaml | 78 ++++++++++++++++++++++++++++ README.md | 29 +++++++++++ 2 files changed, 107 insertions(+) create mode 100644 .github/workflows/publish-image.yaml diff --git a/.github/workflows/publish-image.yaml b/.github/workflows/publish-image.yaml new file mode 100644 index 0000000..d41002d --- /dev/null +++ b/.github/workflows/publish-image.yaml @@ -0,0 +1,78 @@ +name: Build and publish runner image + +on: + push: + branches: [main] + tags: ['v*'] + pull_request: + branches: [main] + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: runner-image-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + +jobs: + image: + runs-on: ubuntu-latest + timeout-minutes: 30 + permissions: + contents: read + packages: write + steps: + - name: Check out source + uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 + with: + persist-credentials: false + + - name: Determine image name and publication policy + id: image + env: + REPOSITORY: ${{ github.repository }} + EVENT_NAME: ${{ github.event_name }} + REF: ${{ github.ref }} + run: | + echo "name=ghcr.io/${REPOSITORY,,}" >> "$GITHUB_OUTPUT" + if [[ "$EVENT_NAME" != "pull_request" && ( "$REF" == "refs/heads/main" || "$REF" == refs/tags/v* ) ]]; then + echo "publish=true" >> "$GITHUB_OUTPUT" + else + echo "publish=false" >> "$GITHUB_OUTPUT" + fi + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3 + + - name: Generate image tags and labels + id: metadata + uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5 + with: + images: ${{ steps.image.outputs.name }} + flavor: latest=false + tags: | + type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }} + type=ref,event=tag + type=ref,event=pr + type=sha,format=long + + - name: Log in to GitHub Container Registry + if: steps.image.outputs.publish == 'true' + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and optionally publish image + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6 + with: + context: . + file: ./Dockerfile + platforms: linux/amd64 + push: ${{ steps.image.outputs.publish == 'true' }} + tags: ${{ steps.metadata.outputs.tags }} + labels: ${{ steps.metadata.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/README.md b/README.md index 42af592..daa5764 100644 --- a/README.md +++ b/README.md @@ -108,6 +108,35 @@ the same time. `compose.common.yaml` is a shared settings file, not a standalone deployment file. The Windows and Linux setup examples above use local building; replace their startup commands with the published-image commands when desired. +## Publishing the image to GHCR + +The `Build and publish runner image` workflow builds the Dockerfile on +GitHub-hosted Linux runners, so it does not depend on this self-hosted runner +being available. It uses the Dockerfile defaults and publishes `linux/amd64` +images, suitable for x86-64 Linux hosts and Docker Desktop using Linux containers. +ARM64 publishing is not enabled by this workflow. + +- Pushes to `main` publish `latest` and `sha-` tags. +- Pushes of release tags such as `v1.0.0` publish that tag and a commit tag. +- Pull requests targeting `main` build the image without publishing or registry login. +- Manual runs from Actions → Build and publish runner image → Run workflow + publish only when run against `main` or a `v*` tag. Other branches only build. + +The registry path is derived from the GitHub repository name and converted to +lowercase. For this repository it is `ghcr.io/sigmalko/githab-runner-in-docker`. +Authentication uses the automatic `GITHUB_TOKEN` with `packages: write`; +no Personal Access Token or runner registration token is needed for publishing. +Runner credentials remain runtime configuration and are excluded from the build +context by `.dockerignore`. + +After the first publication, open the container package's **Package settings** +on GitHub and change its visibility to **Public** to allow anonymous pulls. +A public source repository does not automatically make a new GHCR package public. +Once published and public, use the ready-image Compose commands above. + +See [GitHub's Docker image publishing guide](https://docs.github.com/en/actions/tutorials/publish-packages/publish-docker-images) +and [Container Registry documentation](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry). + ## Where to get RUNNER_TOKEN The source of `RUNNER_TOKEN` is the **self-hosted runner setup page in the target From d1b71072d706237fb0f645157b5b7e2e5dba8b88 Mon Sep 17 00:00:00 2001 From: sigmalko <188585048+sigmalko@users.noreply.github.com> Date: Tue, 29 Sep 2026 23:03:29 +0200 Subject: [PATCH 2/2] Correct repository and container image name --- .env.example | 2 +- README.md | 8 ++++---- compose.image.yaml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.env.example b/.env.example index 8c8ea91..d478a80 100644 --- a/.env.example +++ b/.env.example @@ -3,6 +3,6 @@ RUNNER_TOKEN=PASTE_FRESH_REGISTRATION_TOKEN_HERE RUNNER_NAME=docker-runner-1 RUNNER_LABELS=docker,maven # Optional override for compose.image.yaml; defaults to this project's GHCR image. -# RUNNER_IMAGE=ghcr.io/sigmalko/githab-runner-in-docker:latest +# RUNNER_IMAGE=ghcr.io/sigmalko/github-runner-in-docker:latest # RUNNER_GROUP=Default # RUNNER_WORKDIR=/runner/_work diff --git a/README.md b/README.md index daa5764..2022cc0 100644 --- a/README.md +++ b/README.md @@ -78,12 +78,12 @@ and architecture arguments described in “Parameters”. `compose.image.yaml` defaults to this project's GitHub Container Registry image: ```dotenv -RUNNER_IMAGE=ghcr.io/sigmalko/githab-runner-in-docker:latest +RUNNER_IMAGE=ghcr.io/sigmalko/github-runner-in-docker:latest ``` You can optionally set `RUNNER_IMAGE` in `.env` to override the default with a version tag, digest, or another compatible image. The image is built from -[this repository](https://github.com/sigmalko/githab-runner-in-docker). +[this repository](https://github.com/sigmalko/github-runner-in-docker). This setting is independent of `RUNNER_URL`, which identifies the repository accepting jobs and must be supplied by the user. The default reference must be published in GHCR before it can be pulled. Private images require registry login. @@ -123,7 +123,7 @@ ARM64 publishing is not enabled by this workflow. publish only when run against `main` or a `v*` tag. Other branches only build. The registry path is derived from the GitHub repository name and converted to -lowercase. For this repository it is `ghcr.io/sigmalko/githab-runner-in-docker`. +lowercase. For this repository it is `ghcr.io/sigmalko/github-runner-in-docker`. Authentication uses the automatic `GITHUB_TOKEN` with `packages: write`; no Personal Access Token or runner registration token is needed for publishing. Runner credentials remain runtime configuration and are excluded from the build @@ -206,7 +206,7 @@ docker run -d --name github-runner --restart unless-stopped --env-file .env -v g | RUNNER_ARCH | Build argument | x64 or arm64 | | RUNNER_SHA256 | Build argument | SHA-256 for the selected version and architecture | | RUNNER_URL | Environment variable | Repository or organization URL | -| RUNNER_IMAGE | Compose interpolation variable | Optional override for compose.image.yaml; defaults to ghcr.io/sigmalko/githab-runner-in-docker:latest | +| RUNNER_IMAGE | Compose interpolation variable | Optional override for compose.image.yaml; defaults to ghcr.io/sigmalko/github-runner-in-docker:latest | | RUNNER_TOKEN | Environment variable | Runner registration token | | RUNNER_TOKEN_FILE | Environment variable | Alternative path to a mounted file containing the token | | RUNNER_NAME | Environment variable | Defaults to the container hostname | diff --git a/compose.image.yaml b/compose.image.yaml index 5d4b72e..e5de53b 100644 --- a/compose.image.yaml +++ b/compose.image.yaml @@ -3,6 +3,6 @@ services: extends: file: compose.common.yaml service: runner - image: ${RUNNER_IMAGE:-ghcr.io/sigmalko/githab-runner-in-docker:latest} + image: ${RUNNER_IMAGE:-ghcr.io/sigmalko/github-runner-in-docker:latest} volumes: runner-data: