Skip to content

Commit 31c409a

Browse files
authored
Create Docker multi-platform build workflow
Add GitHub Actions workflow for Docker multi-platform builds, including steps for building, pushing, and managing images for both Docker Hub and GitHub Container Registry.
1 parent e492c35 commit 31c409a

1 file changed

Lines changed: 302 additions & 0 deletions

File tree

.github/workflows/docker.yml

Lines changed: 302 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,302 @@
1+
name: Docker Multi Platform Builds
2+
3+
on:
4+
workflow_dispatch:
5+
push:
6+
branches:
7+
- 'main'
8+
tags:
9+
- 'v*.*.*'
10+
pull_request:
11+
branches:
12+
- 'main'
13+
14+
env:
15+
DOCKERHUB_IMAGE: ${{ 'oceanprotocol/ocean-contracts' }}
16+
GHCR_IMAGE: ${{ 'ghcr.io/oceanprotocol/ocean-contracts' }}
17+
18+
jobs:
19+
build:
20+
runs-on: ubuntu-latest
21+
if: ${{ github.actor != 'dependabot[bot]' }}
22+
strategy:
23+
fail-fast: false
24+
matrix:
25+
# we keep this just in case we need to change
26+
platform: ${{ github.event_name == 'pull_request' && fromJSON('["linux/amd64"]') || fromJSON('["linux/amd64"]') }}
27+
steps:
28+
- name: Prepare
29+
run: |
30+
platform=${{ matrix.platform }}
31+
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
32+
- name: Checkout
33+
uses: actions/checkout@v6
34+
- name: Set up QEMU
35+
uses: docker/setup-qemu-action@v3
36+
with:
37+
platforms: ${{ matrix.platform }}
38+
#image: tonistiigi/binfmt:qemu-v8.0.4
39+
- name: Set up Docker Buildx
40+
id: buildx
41+
uses: docker/setup-buildx-action@v3
42+
with:
43+
platforms: ${{ matrix.platform }}
44+
- name: Login to Docker Hub
45+
id: dockerhub_login
46+
env:
47+
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_PUSH_USERNAME }}
48+
DOCKERHUB_TOKEN: ${{ secrets.DOCKER_PUSH_TOKEN }}
49+
if: env.DOCKERHUB_USERNAME != '' && env.DOCKERHUB_TOKEN != ''
50+
uses: docker/login-action@v3
51+
with:
52+
username: ${{ secrets.DOCKERHUB_PUSH_USERNAME }}
53+
password: ${{ secrets.DOCKER_PUSH_TOKEN }}
54+
- name: Login to GitHub Container Registry
55+
id: ghcr_login
56+
env:
57+
GHCR_PUSH_TOKEN: ${{ secrets.GHCR_PUSH_TOKEN }}
58+
if: env.GHCR_PUSH_TOKEN != ''
59+
uses: docker/login-action@v3
60+
with:
61+
registry: ghcr.io
62+
username: ${{ github.repository_owner }}
63+
password: ${{ secrets.GHCR_PUSH_TOKEN }}
64+
- name: Set Docker metadata
65+
id: ocean_node_meta
66+
uses: docker/metadata-action@v5
67+
with:
68+
images: |
69+
${{ env.DOCKERHUB_IMAGE }}
70+
${{ env.GHCR_IMAGE }}
71+
# generate Docker tags based on the following events/attributes
72+
tags: |
73+
type=ref,event=branch
74+
type=semver,pattern={{version}}
75+
type=ref,event=pr
76+
# type=semver,pattern={{major}}.{{minor}}
77+
# type=semver,pattern={{major}}
78+
# type=sha
79+
- name: Build and push to Docker Hub
80+
if: steps.dockerhub_login.outcome == 'success'
81+
id: build_dockerhub
82+
uses: docker/build-push-action@v5
83+
with:
84+
builder: ${{ steps.buildx.outputs.name }}
85+
context: .
86+
platforms: ${{ matrix.platform }}
87+
push: true
88+
# tags: ${{ steps.ocean_node_meta.outputs.tags }}
89+
labels: ${{ steps.ocean_node_meta.outputs.labels }}
90+
outputs: type=image,name=${{ env.DOCKERHUB_IMAGE }},push-by-digest=true,name-canonical=true,push=true
91+
- name: Build and push to GHCR
92+
if: steps.ghcr_login.outcome == 'success'
93+
id: build_ghcr
94+
uses: docker/build-push-action@v5
95+
with:
96+
builder: ${{ steps.buildx.outputs.name }}
97+
context: .
98+
platforms: ${{ matrix.platform }}
99+
push: true
100+
labels: ${{ steps.ocean_node_meta.outputs.labels }}
101+
outputs: type=image,name=${{ env.GHCR_IMAGE }},push-by-digest=true,name-canonical=true,push=true
102+
- name: Export digests
103+
run: |
104+
mkdir -p /tmp/digests
105+
if [ -n "${{ steps.build_dockerhub.outputs.digest }}" ]; then
106+
dockerhub_digest="${{ steps.build_dockerhub.outputs.digest }}"
107+
touch "/tmp/digests/dockerhub-${dockerhub_digest#sha256:}"
108+
fi
109+
if [ -n "${{ steps.build_ghcr.outputs.digest }}" ]; then
110+
ghcr_digest="${{ steps.build_ghcr.outputs.digest }}"
111+
touch "/tmp/digests/ghcr-${ghcr_digest#sha256:}"
112+
fi
113+
- name: Upload digest
114+
uses: actions/upload-artifact@v4
115+
with:
116+
name: digests-${{ env.PLATFORM_PAIR }}
117+
path: /tmp/digests/*
118+
if-no-files-found: error
119+
retention-days: 1
120+
121+
build-arm:
122+
runs-on: ubuntu-24.04-arm
123+
if: ${{ github.actor != 'dependabot[bot]' }}
124+
strategy:
125+
fail-fast: false
126+
matrix:
127+
# we keep this just in case we need to change
128+
platform: ${{ github.event_name == 'pull_request' && fromJSON('["linux/arm64"]') || fromJSON('["linux/arm64"]') }}
129+
steps:
130+
- name: Prepare
131+
run: |
132+
platform=${{ matrix.platform }}
133+
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
134+
- name: Checkout
135+
uses: actions/checkout@v6
136+
- name: Set up QEMU
137+
uses: docker/setup-qemu-action@v3
138+
with:
139+
platforms: ${{ matrix.platform }}
140+
#image: tonistiigi/binfmt:qemu-v8.0.4
141+
- name: Set up Docker Buildx
142+
id: buildx
143+
uses: docker/setup-buildx-action@v3
144+
with:
145+
platforms: ${{ matrix.platform }}
146+
- name: Login to Docker Hub
147+
id: dockerhub_login
148+
env:
149+
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_PUSH_USERNAME }}
150+
DOCKERHUB_TOKEN: ${{ secrets.DOCKER_PUSH_TOKEN }}
151+
if: env.DOCKERHUB_USERNAME != '' && env.DOCKERHUB_TOKEN != ''
152+
uses: docker/login-action@v3
153+
with:
154+
username: ${{ secrets.DOCKERHUB_PUSH_USERNAME }}
155+
password: ${{ secrets.DOCKER_PUSH_TOKEN }}
156+
- name: Login to GitHub Container Registry
157+
id: ghcr_login
158+
env:
159+
GHCR_PUSH_TOKEN: ${{ secrets.GHCR_PUSH_TOKEN }}
160+
if: env.GHCR_PUSH_TOKEN != ''
161+
uses: docker/login-action@v3
162+
with:
163+
registry: ghcr.io
164+
username: ${{ github.repository_owner }}
165+
password: ${{ secrets.GHCR_PUSH_TOKEN }}
166+
- name: Set Docker metadata
167+
id: ocean_node_meta
168+
uses: docker/metadata-action@v5
169+
with:
170+
images: |
171+
${{ env.DOCKERHUB_IMAGE }}
172+
${{ env.GHCR_IMAGE }}
173+
# generate Docker tags based on the following events/attributes
174+
tags: |
175+
type=ref,event=branch
176+
type=semver,pattern={{version}}
177+
type=ref,event=pr
178+
# type=semver,pattern={{major}}.{{minor}}
179+
# type=semver,pattern={{major}}
180+
# type=sha
181+
- name: Build and push to Docker Hub
182+
if: steps.dockerhub_login.outcome == 'success'
183+
id: build_dockerhub
184+
uses: docker/build-push-action@v5
185+
with:
186+
builder: ${{ steps.buildx.outputs.name }}
187+
context: .
188+
platforms: ${{ matrix.platform }}
189+
push: true
190+
# tags: ${{ steps.ocean_node_meta.outputs.tags }}
191+
labels: ${{ steps.ocean_node_meta.outputs.labels }}
192+
outputs: type=image,name=${{ env.DOCKERHUB_IMAGE }},push-by-digest=true,name-canonical=true,push=true
193+
- name: Build and push to GHCR
194+
if: steps.ghcr_login.outcome == 'success'
195+
id: build_ghcr
196+
uses: docker/build-push-action@v5
197+
with:
198+
builder: ${{ steps.buildx.outputs.name }}
199+
context: .
200+
platforms: ${{ matrix.platform }}
201+
push: true
202+
labels: ${{ steps.ocean_node_meta.outputs.labels }}
203+
outputs: type=image,name=${{ env.GHCR_IMAGE }},push-by-digest=true,name-canonical=true,push=true
204+
- name: Export digests
205+
run: |
206+
mkdir -p /tmp/digests
207+
if [ -n "${{ steps.build_dockerhub.outputs.digest }}" ]; then
208+
dockerhub_digest="${{ steps.build_dockerhub.outputs.digest }}"
209+
touch "/tmp/digests/dockerhub-arm64-${dockerhub_digest#sha256:}"
210+
fi
211+
if [ -n "${{ steps.build_ghcr.outputs.digest }}" ]; then
212+
ghcr_digest="${{ steps.build_ghcr.outputs.digest }}"
213+
touch "/tmp/digests/ghcr-arm64-${ghcr_digest#sha256:}"
214+
fi
215+
- name: Upload digest
216+
uses: actions/upload-artifact@v4
217+
with:
218+
name: digests-${{ env.PLATFORM_PAIR }}
219+
path: /tmp/digests/*
220+
if-no-files-found: error
221+
retention-days: 1
222+
223+
merge:
224+
runs-on: ubuntu-latest
225+
if: ${{ github.actor != 'dependabot[bot]' }}
226+
needs:
227+
- build
228+
- build-arm
229+
steps:
230+
- name: Download digests
231+
uses: actions/download-artifact@v4
232+
with:
233+
path: /tmp/digests
234+
pattern: digests-*
235+
merge-multiple: true
236+
- name: Set up Docker Buildx
237+
uses: docker/setup-buildx-action@v3
238+
- name: Set Docker metadata
239+
id: ocean_node_meta
240+
uses: docker/metadata-action@v5
241+
with:
242+
images: |
243+
${{ env.DOCKERHUB_IMAGE }}
244+
${{ env.GHCR_IMAGE }}
245+
# generate Docker tags based on the following events/attributes
246+
tags: |
247+
type=ref,event=branch
248+
type=semver,pattern={{version}}
249+
type=ref,event=pr
250+
# type=semver,pattern={{major}}.{{minor}}
251+
# type=semver,pattern={{major}}
252+
# type=sha
253+
- name: Login to Docker Hub
254+
id: dockerhub_login
255+
env:
256+
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_PUSH_USERNAME }}
257+
DOCKERHUB_TOKEN: ${{ secrets.DOCKER_PUSH_TOKEN }}
258+
if: env.DOCKERHUB_USERNAME != '' && env.DOCKERHUB_TOKEN != ''
259+
uses: docker/login-action@v3
260+
with:
261+
username: ${{ secrets.DOCKERHUB_PUSH_USERNAME }}
262+
password: ${{ secrets.DOCKER_PUSH_TOKEN }}
263+
- name: Login to GitHub Container Registry
264+
id: ghcr_login
265+
env:
266+
GHCR_PUSH_TOKEN: ${{ secrets.GHCR_PUSH_TOKEN }}
267+
if: env.GHCR_PUSH_TOKEN != ''
268+
uses: docker/login-action@v3
269+
with:
270+
registry: ghcr.io
271+
username: ${{ github.repository_owner }}
272+
password: ${{ secrets.GHCR_PUSH_TOKEN }}
273+
- name: Create manifest list and push to Docker Hub
274+
if: steps.dockerhub_login.outcome == 'success'
275+
working-directory: /tmp/digests
276+
env:
277+
DOCKERHUB_IMAGE: ${{ env.DOCKERHUB_IMAGE }}
278+
run: |
279+
if ls dockerhub-* 1> /dev/null 2>&1; then
280+
TAGS=$(echo "${{ steps.ocean_node_meta.outputs.tags }}" | grep -E "^${DOCKERHUB_IMAGE}" | sed 's|^|-t |' | tr '\n' ' ')
281+
# Strip dockerhub-arm64- and dockerhub- so digest is always just the sha256 hex
282+
DIGESTS=$(ls dockerhub-* | sed -e "s|dockerhub-arm64-|${DOCKERHUB_IMAGE}@sha256:|" -e "s|dockerhub-|${DOCKERHUB_IMAGE}@sha256:|" | tr '\n' ' ')
283+
docker buildx imagetools create $TAGS $DIGESTS
284+
fi
285+
- name: Create manifest list and push to GHCR
286+
if: steps.ghcr_login.outcome == 'success'
287+
working-directory: /tmp/digests
288+
env:
289+
GHCR_IMAGE: ${{ env.GHCR_IMAGE }}
290+
run: |
291+
TAGS=$(echo "${{ steps.ocean_node_meta.outputs.tags }}" | grep -E "^${GHCR_IMAGE}" | sed 's|^|-t |' | tr '\n' ' ')
292+
# Strip ghcr-arm64- and ghcr- so digest is always just the sha256 hex
293+
DIGESTS=$(ls ghcr-* | sed -e "s|ghcr-arm64-|${GHCR_IMAGE}@sha256:|" -e "s|ghcr-|${GHCR_IMAGE}@sha256:|" | tr '\n' ' ')
294+
docker buildx imagetools create $TAGS $DIGESTS
295+
- name: Inspect Docker Hub image
296+
if: steps.dockerhub_login.outcome == 'success'
297+
run: |
298+
docker buildx imagetools inspect ${{ env.DOCKERHUB_IMAGE }}:${{ steps.ocean_node_meta.outputs.version }}
299+
- name: Inspect GHCR image
300+
if: steps.ghcr_login.outcome == 'success'
301+
run: |
302+
docker buildx imagetools inspect ${{ env.GHCR_IMAGE }}:${{ steps.ocean_node_meta.outputs.version }}

0 commit comments

Comments
 (0)