Skip to content

Commit dc54add

Browse files
Hat Daoclaude
andcommitted
Fix multi-platform buildx error in GitHub Actions
- Fixed "docker exporter does not support manifest lists" error - Multi-platform builds now use --output type=image instead of --load - Single platform builds continue to use --load for local Docker daemon - CI workflow now builds for single platform to enable testing - Added separate workflow for testing multi-arch builds - Updated tests and documentation to reflect the behavior differences The issue was that --load only works for single platform builds since the local Docker daemon can only store images for one architecture. 🤖 Generated with Claude Code Co-Authored-By: Claude <[email protected]>
1 parent 9cfe64d commit dc54add

File tree

7 files changed

+79
-12
lines changed

7 files changed

+79
-12
lines changed

.github/workflows/dockerimage.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ jobs:
2424
2525
- name: Build multi-architecture images
2626
run: |
27-
# Build for both amd64 and arm64
28-
# Note: --no-push flag is used instead of --push=False
29-
invoke buildx latest --no-push
27+
# For CI testing, build only for the current platform (amd64)
28+
# This allows us to use --load and test the image
29+
invoke buildx latest --no-push --platforms="linux/amd64"
3030
3131
- name: Test the built image
3232
run: |
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
name: Test Multi-Architecture Build
2+
3+
on:
4+
pull_request:
5+
paths:
6+
- 'Dockerfile'
7+
- 'tasks.py'
8+
- '.github/workflows/test-multiarch.yml'
9+
workflow_dispatch:
10+
11+
jobs:
12+
test-multiarch-build:
13+
runs-on: ubuntu-latest
14+
strategy:
15+
matrix:
16+
version: ['latest', '7.2.5', '7.0.15']
17+
steps:
18+
- uses: actions/checkout@v4
19+
20+
- name: Set up QEMU
21+
uses: docker/setup-qemu-action@v3
22+
23+
- name: Set up Docker Buildx
24+
uses: docker/setup-buildx-action@v3
25+
26+
- name: Install Python dependencies
27+
run: |
28+
python -m pip install --upgrade pip
29+
pip install invoke requests
30+
31+
- name: Test multi-architecture build (without push)
32+
run: |
33+
# Test building for both platforms
34+
# This validates that the build works for ARM64
35+
invoke buildx ${{ matrix.version }} --no-push
36+
37+
- name: Build and test single platform
38+
run: |
39+
# Build for current platform only so we can test it
40+
invoke buildx ${{ matrix.version }} --no-push --platforms="linux/amd64"
41+
42+
# Test the image
43+
docker run --rm grokzen/redis-cluster:${{ matrix.version }} redis-server --version

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -242,17 +242,17 @@ To build multi-architecture images locally, you need Docker Buildx (included in
242242
# Build and push to Docker Hub (default behavior)
243243
invoke buildx 7.2.5
244244

245-
# Build without pushing (for local testing)
245+
# Build without pushing (for validation only - images won't be loaded locally)
246246
invoke buildx 7.2.5 --no-push
247247

248-
# Build for specific platforms only
249-
invoke buildx 7.2.5 --platforms="linux/amd64"
248+
# Build for current platform only (will be loaded to local Docker)
249+
invoke buildx 7.2.5 --no-push --platforms="linux/amd64"
250250

251251
# Build all versions for multi-arch
252252
invoke buildx all
253253

254-
# Build without pushing for a specific platform
255-
invoke buildx 7.2.5 --no-push --platforms="linux/arm64"
254+
# Build and load for local testing (single platform only)
255+
invoke buildx 7.2.5 --no-push --platforms="linux/$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')"
256256

257257
#### Using docker buildx directly
258258

__pycache__/tasks.cpython-312.pyc

8.31 KB
Binary file not shown.
11.3 KB
Binary file not shown.

tasks.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,20 @@ def _docker_buildx(config):
169169
Internal multiprocess method to run docker buildx command
170170
"""
171171
c, version, platforms, push = config
172-
action = "--push" if push else "--load"
172+
173+
if push:
174+
action = "--push"
175+
else:
176+
# For local builds, we need to handle single vs multi-platform differently
177+
platform_list = platforms.split(',')
178+
if len(platform_list) == 1:
179+
# Single platform: can use --load
180+
action = "--load"
181+
else:
182+
# Multi-platform: use --output type=docker,dest=-
183+
# This outputs to stdout which we'll discard, but allows the build to complete
184+
action = "--output type=image"
185+
173186
print(f" -- Starting docker buildx for version : {version} on platforms: {platforms} with action: {action}")
174187
build_command = f"docker buildx build --platform={platforms} --build-arg redis_version={version} -t grokzen/redis-cluster:{version} {action} ."
175188
c.run(build_command)

test_tasks.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,13 +85,24 @@ def test_docker_buildx_push_true(self):
8585
expected_cmd = "docker buildx build --platform=linux/amd64,linux/arm64 --build-arg redis_version=7.2.5 -t grokzen/redis-cluster:7.2.5 --push ."
8686
self.mock_context.run.assert_called_with(expected_cmd)
8787

88-
def test_docker_buildx_push_false(self):
89-
"""Test _docker_buildx with push=False"""
88+
def test_docker_buildx_push_false_multiplatform(self):
89+
"""Test _docker_buildx with push=False for multi-platform"""
9090
config = [self.mock_context, "7.2.5", "linux/amd64,linux/arm64", False]
9191

9292
tasks._docker_buildx(config)
9393

94-
expected_cmd = "docker buildx build --platform=linux/amd64,linux/arm64 --build-arg redis_version=7.2.5 -t grokzen/redis-cluster:7.2.5 --load ."
94+
# Multi-platform builds use --output type=image instead of --load
95+
expected_cmd = "docker buildx build --platform=linux/amd64,linux/arm64 --build-arg redis_version=7.2.5 -t grokzen/redis-cluster:7.2.5 --output type=image ."
96+
self.mock_context.run.assert_called_with(expected_cmd)
97+
98+
def test_docker_buildx_push_false_single_platform(self):
99+
"""Test _docker_buildx with push=False for single platform"""
100+
config = [self.mock_context, "7.2.5", "linux/amd64", False]
101+
102+
tasks._docker_buildx(config)
103+
104+
# Single platform builds can use --load
105+
expected_cmd = "docker buildx build --platform=linux/amd64 --build-arg redis_version=7.2.5 -t grokzen/redis-cluster:7.2.5 --load ."
95106
self.mock_context.run.assert_called_with(expected_cmd)
96107

97108
@patch('tasks.Pool')

0 commit comments

Comments
 (0)