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 ]
109
11- build :
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
26+
27+ jobs :
1228 build-and-push :
1329 runs-on : ubuntu-latest
1430
15- env :
16- # Your Docker Hub namespace (must be lowercase)
17- DOCKERHUB_NS : ${{ secrets.DOCKERHUB_USERNAME }}
18-
1931 steps :
2032 - name : Checkout
2133 uses : actions/checkout@v4
2234 with :
2335 fetch-depth : 0
24- - name : Setup Docker Buildx
36+
37+ - name : Set up QEMU
38+ uses : docker/setup-qemu-action@v3
39+
2540 - name : Set up Docker Buildx
2641 uses : docker/setup-buildx-action@v3
27- - name : Login to Docker Hub
28- uses : docker/login-action@v3
42+
43+ # --- Compute tags per service (three separate metadata steps) ---
44+ - name : Meta (userapi)
45+ id : meta_user
2946 uses : docker/metadata-action@v5
30- username : ${{ secrets.DOCKERHUB_USERNAME }}
31- password : ${{ secrets.DOCKERHUB_TOKEN }}
47+ with :
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') }}
3275 type=semver,pattern={{major}}.{{minor}},enable=${{ startsWith(github.ref, 'refs/tags/v') }}
3376
77+ - name : Login to GHCR
3478 if : ${{ github.event_name != 'pull_request' }}
3579 uses : docker/login-action@v3
3680 with :
37- username : ${{ github.actor }}
81+ registry : ghcr.io
3882 username : ${{ github.repository_owner }}
3983 password : ${{ secrets.GITHUB_TOKEN }}
4084
41- # Optional: quick sanity check that compose is at repo root
42- - 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()
43125 run : |
44- pwd
45- ls -la
46- test -f docker-compose.yml && echo "compose found" || (echo "compose missing" && exit 1)
47-
48- - name : Build & Push with Bake (compose)
49- uses : docker/bake-action@v4
50- with :
51- files : |
52- docker-compose.yml
53- push : true
54- # You can override or add tags/labels per-target with `set:` if needed
55- # set: |
56- # *.labels=org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
57- # *.tags=ghcr.io/hasanjaved-developer/centralized-logging/{{.target}}:edge
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 != '' }}
131+ run : |
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