1- # .github/workflows/docker-compose-ci.yml
2- name : Build & Push (Compose/Bake)
1+ name : docker-compose-ci
32
43on :
54 push :
6- branches : [ "main", "master" ]
7- # enable when you want release builds from tags
8- # push:
9- # tags: [ "v*" ]
5+ branches : [ master ]
6+ tags : [ 'v*.*.*' ] # v1.2.3 -> release images
7+ pull_request :
8+ branches : [ master ]
9+
10+ permissions :
11+ contents : read
12+ packages : write # needed for GHCR
13+ id-token : write
14+
15+ concurrency :
16+ group : docker-compose-ci-${{ github.ref }}
17+ cancel-in-progress : true
18+
19+ env :
20+ # Project namespace for your image path: ghcr.io/<owner>/<REPO_SLUG>/<service>
21+ REPO_SLUG : centralized-logging
22+ # Optional: set to your Docker Hub namespace (lowercase). Leave empty to skip mirroring.
23+ DOCKERHUB_NAMESPACE : " "
24+ # Multi-arch
25+ PLATFORMS : linux/amd64,linux/arm64
1026
1127jobs :
12- build :
28+ build-and-push :
1329 runs-on : ubuntu-latest
1430
1531 steps :
@@ -18,36 +34,119 @@ jobs:
1834 with :
1935 fetch-depth : 0
2036
21- - name : Setup Docker Buildx
37+ - name : Set up QEMU
38+ uses : docker/setup-qemu-action@v3
39+
40+ - name : Set up Docker Buildx
2241 uses : docker/setup-buildx-action@v3
2342
24- - name : Login to Docker Hub
25- uses : docker/login-action@v3
43+ # --- Compute tags per service (three separate metadata steps) ---
44+ - name : Meta (userapi)
45+ id : meta_user
46+ uses : docker/metadata-action@v5
2647 with :
27- username : ${{ secrets.DOCKERHUB_USERNAME }}
28- password : ${{ secrets.DOCKERHUB_TOKEN }}
48+ images : ghcr.io/${{ github.repository_owner }}/${{ env.REPO_SLUG }}/userapi
49+ tags : |
50+ type=raw,value=edge,enable=${{ github.event_name != 'pull_request' }}
51+ type=raw,value=latest,enable=${{ github.ref == 'refs/heads/master' }}
52+ type=semver,pattern={{version}},enable=${{ startsWith(github.ref, 'refs/tags/v') }}
53+ type=semver,pattern={{major}}.{{minor}},enable=${{ startsWith(github.ref, 'refs/tags/v') }}
54+
55+ - name : Meta (api)
56+ id : meta_api
57+ uses : docker/metadata-action@v5
58+ with :
59+ images : ghcr.io/${{ github.repository_owner }}/${{ env.REPO_SLUG }}/api
60+ tags : |
61+ type=raw,value=edge,enable=${{ github.event_name != 'pull_request' }}
62+ type=raw,value=latest,enable=${{ github.ref == 'refs/heads/master' }}
63+ type=semver,pattern={{version}},enable=${{ startsWith(github.ref, 'refs/tags/v') }}
64+ type=semver,pattern={{major}}.{{minor}},enable=${{ startsWith(github.ref, 'refs/tags/v') }}
65+
66+ - name : Meta (web)
67+ id : meta_web
68+ uses : docker/metadata-action@v5
69+ with :
70+ images : ghcr.io/${{ github.repository_owner }}/${{ env.REPO_SLUG }}/web
71+ tags : |
72+ type=raw,value=edge,enable=${{ github.event_name != 'pull_request' }}
73+ type=raw,value=latest,enable=${{ github.ref == 'refs/heads/master' }}
74+ type=semver,pattern={{version}},enable=${{ startsWith(github.ref, 'refs/tags/v') }}
75+ type=semver,pattern={{major}}.{{minor}},enable=${{ startsWith(github.ref, 'refs/tags/v') }}
2976
3077 - name : Login to GHCR
78+ if : ${{ github.event_name != 'pull_request' }}
3179 uses : docker/login-action@v3
3280 with :
3381 registry : ghcr.io
34- username : ${{ github.actor }}
82+ username : ${{ github.repository_owner }}
3583 password : ${{ secrets.GITHUB_TOKEN }}
3684
37- # Optional: quick sanity check that compose is at repo root
38- - name : Show tree
85+ - name : Login to Docker Hub (optional)
86+ if : ${{ github.event_name != 'pull_request' && env.DOCKERHUB_NAMESPACE != '' && secrets.DOCKERHUB_USERNAME != '' && secrets.DOCKERHUB_TOKEN != '' }}
87+ uses : docker/login-action@v3
88+ with :
89+ username : ${{ secrets.DOCKERHUB_USERNAME }}
90+ password : ${{ secrets.DOCKERHUB_TOKEN }}
91+
92+ # Build cache (local dir cache)
93+ - name : Restore build cache
94+ uses : actions/cache@v4
95+ with :
96+ path : /tmp/.buildx-cache
97+ key : ${{ runner.os }}-buildx-${{ github.sha }}
98+ restore-keys : |
99+ ${{ runner.os }}-buildx-
100+
101+ - name : Bake & Push (multi-arch)
102+ uses : docker/bake-action@v5
103+ with :
104+ files : ./docker-bake.hcl
105+ push : ${{ github.event_name != 'pull_request' }}
106+ set : |
107+ # Platforms & cache
108+ *.platform=${{ env.PLATFORMS }}
109+ *.cache-from=type=local,src=/tmp/.buildx-cache
110+ *.cache-to=type=local,dest=/tmp/.buildx-cache-new,mode=max
111+ # Labels/injection
112+ *.labels.org.opencontainers.image.revision=${{ github.sha }}
113+ # Bake variables (must match variable names in docker-bake.hcl)
114+ OWNER=${{ github.repository_owner }}
115+ REPO_SLUG=${{ env.REPO_SLUG }}
116+ # If you customized REGISTRY_GHCR in the bake file, you could set it here too:
117+ # REGISTRY_GHCR=ghcr.io
118+ # Service-specific tags
119+ userapi.tags=${{ steps.meta_user.outputs.tags }}
120+ api.tags=${{ steps.meta_api.outputs.tags }}
121+ web.tags=${{ steps.meta_web.outputs.tags }}
122+
123+ - name : Save build cache
124+ if : always()
125+ run : |
126+ rm -rf /tmp/.buildx-cache
127+ mv /tmp/.buildx-cache-new /tmp/.buildx-cache
128+
129+ - name : Mirror to Docker Hub (optional)
130+ if : ${{ github.event_name != 'pull_request' && env.DOCKERHUB_NAMESPACE != '' && secrets.DOCKERHUB_USERNAME != '' && secrets.DOCKERHUB_TOKEN != '' }}
39131 run : |
40- pwd
41- ls -la
42- test -f docker-compose.yml && echo "compose found" || (echo "compose missing" && exit 1)
43-
44- - name : Build & Push with Bake (compose)
45- uses : docker/bake-action@v4
46- with :
47- files : |
48- docker-compose.yml
49- push : true
50- # You can override or add tags/labels per-target with `set:` if needed
51- # set: |
52- # *.labels=org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
53- # *.tags=ghcr.io/hasanjaved-developer/centralized-logging/{{.target}}:edge
132+ set -euo pipefail
133+ mapfile -t USER_TAGS <<< "${{ steps.meta_user.outputs.tags }}"
134+ mapfile -t API_TAGS <<< "${{ steps.meta_api.outputs.tags }}"
135+ mapfile -t WEB_TAGS <<< "${{ steps.meta_web.outputs.tags }}"
136+
137+ mirror() {
138+ local svc="$1"; shift
139+ for t in "$@"; do
140+ tg="$(basename "$t")"
141+ ghcr="ghcr.io/${{ github.repository_owner }}/${{ env.REPO_SLUG }}/${svc}:${tg}"
142+ hub="${{ env.DOCKERHUB_NAMESPACE }}/${{ env.REPO_SLUG }}-${svc}:${tg}"
143+ echo "Mirroring $ghcr -> $hub"
144+ docker pull "$ghcr"
145+ docker tag "$ghcr" "$hub"
146+ docker push "$hub"
147+ done
148+ }
149+
150+ mirror userapi "${USER_TAGS[@]}"
151+ mirror api "${API_TAGS[@]}"
152+ mirror web "${WEB_TAGS[@]}"
0 commit comments