Publish a single multi-arch Docker image

Build amd64 and arm64 natively (no emulation), push each by
digest, then merge them into one multi-arch manifest so
`zedeus/nitter:latest` and `:<sha>` resolve to the right image
on any CPU. Replaces the separate `latest-arm64` tag, which is
no longer needed. Update the README notes accordingly.
This commit is contained in:
Zed
2026-06-07 01:02:47 +02:00
parent 40d17bf042
commit f629507537
2 changed files with 88 additions and 36 deletions
+87 -33
View File
@@ -7,55 +7,109 @@ on:
branches: branches:
- master - master
env:
IMAGE: zedeus/nitter
jobs: jobs:
tests: tests:
uses: ./.github/workflows/run-tests.yml uses: ./.github/workflows/run-tests.yml
secrets: inherit secrets: inherit
build-docker-amd64: # Build each architecture natively (no emulation) and push by digest only.
# The digests are stitched into a single multi-arch tag by the merge job.
build:
needs: [tests] needs: [tests]
strategy:
fail-fast: false
matrix:
include:
- runner: ubuntu-24.04
platform: linux/amd64
- runner: ubuntu-24.04-arm
platform: linux/arm64
runs-on: ${{ matrix.runner }}
steps:
- name: Prepare platform name
run: echo "PLATFORM_PAIR=${platform//\//-}" >> "$GITHUB_ENV"
env:
platform: ${{ matrix.platform }}
- uses: actions/checkout@v6
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
version: latest
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push by digest
id: build
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
platforms: ${{ matrix.platform }}
outputs: type=image,name=${{ env.IMAGE }},push-by-digest=true,name-canonical=true,push=true
# Attestations turn a single-platform push into a manifest index, which
# breaks push-by-digest + the imagetools merge below. Disable them.
provenance: false
sbom: false
- name: Export digest
run: |
mkdir -p "${{ runner.temp }}/digests"
digest="${{ steps.build.outputs.digest }}"
touch "${{ runner.temp }}/digests/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v4
with:
name: digests-${{ env.PLATFORM_PAIR }}
path: ${{ runner.temp }}/digests/*
if-no-files-found: error
retention-days: 1
# Combine the per-arch digests into one multi-arch manifest so that
# `docker pull zedeus/nitter:latest` serves the right image on any CPU.
merge:
needs: [build]
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
steps: steps:
- uses: actions/checkout@v6 - name: Download digests
- name: Set up Docker Buildx uses: actions/download-artifact@v4
id: buildx
uses: docker/setup-buildx-action@v3
with: with:
version: latest path: ${{ runner.temp }}/digests
- name: Login to DockerHub pattern: digests-*
uses: docker/login-action@v3 merge-multiple: true
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push AMD64 Docker image
uses: docker/build-push-action@v3
with:
context: .
file: ./Dockerfile
platforms: linux/amd64
push: true
tags: zedeus/nitter:latest,zedeus/nitter:${{ github.sha }}
build-docker-arm64:
needs: [tests]
runs-on: ubuntu-24.04-arm
steps:
- uses: actions/checkout@v6
- name: Set up Docker Buildx - name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v3
with: with:
version: latest version: latest
- name: Login to DockerHub - name: Login to DockerHub
uses: docker/login-action@v3 uses: docker/login-action@v3
with: with:
username: ${{ secrets.DOCKER_USERNAME }} username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }} password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push ARM64 Docker image
uses: docker/build-push-action@v3 - name: Create manifest list and push
with: working-directory: ${{ runner.temp }}/digests
context: . run: |
file: ./Dockerfile # latest-arm64 is a backward-compat alias of the (now multi-arch)
platforms: linux/arm64 # latest tag, for users still pinned to the old ARM64-only image.
push: true # word splitting is intentional: one image ref arg per digest file
tags: zedeus/nitter:latest-arm64,zedeus/nitter:${{ github.sha }}-arm64 # shellcheck disable=SC2046
docker buildx imagetools create \
-t ${{ env.IMAGE }}:latest \
-t ${{ env.IMAGE }}:latest-arm64 \
-t ${{ env.IMAGE }}:${{ github.sha }} \
$(printf '${{ env.IMAGE }}@sha256:%s ' *)
- name: Inspect image
run: docker buildx imagetools inspect ${{ env.IMAGE }}:${{ github.sha }}
+1 -3
View File
@@ -123,7 +123,7 @@ performance reasons.
Page for the Docker image: https://hub.docker.com/r/zedeus/nitter Page for the Docker image: https://hub.docker.com/r/zedeus/nitter
#### NOTE: For ARM64 support, please use the separate ARM64 docker image: [`zedeus/nitter:latest-arm64`](https://hub.docker.com/r/zedeus/nitter/tags). #### NOTE: The published image is multi-arch — `zedeus/nitter:latest` runs natively on both `amd64` and `arm64`.
To run Nitter with Docker, you'll need to install and run Redis separately To run Nitter with Docker, you'll need to install and run Redis separately
before you can run the container. See below for how to also run Redis using before you can run the container. See below for how to also run Redis using
@@ -147,8 +147,6 @@ docker build -t nitter:latest .
docker run -v $(pwd)/nitter.conf:/src/nitter.conf -d --network host nitter:latest docker run -v $(pwd)/nitter.conf:/src/nitter.conf -d --network host nitter:latest
``` ```
Note: For ARM64, use this Dockerfile: [`Dockerfile.arm64`](https://github.com/zedeus/nitter/blob/master/Dockerfile.arm64).
A prebuilt Docker image is provided as well: A prebuilt Docker image is provided as well:
```bash ```bash