Última atividade 1 month ago

使用 GitHub Action 构建 Docker 镜像

Dockerfile Bruto
1# 构建阶段
2FROM rust:1.85-trixie AS builder
3
4# Set working directory
5WORKDIR /app
6COPY . .
7
8# 编译应用
9# 使用 --release 模式进行优化
10RUN cargo build --release
11
12# 运行阶段
13FROM gcr.io/distroless/cc-debian12:nonroot
14
15# Set working directory
16WORKDIR /app
17
18# 从构建阶段复制编译好的二进制文件
19# 请根据实际项目名称修改 'app'
20COPY --from=builder /app/target/release/app /app/app
21
22# Expose port
23EXPOSE 8080
24
25# 设置运行时的入口点
26ENTRYPOINT ["/app/app"]
27
README.md Bruto
  • 使用项目提供的 Docker 镜像

    版本: latest, dev(GHCR only), <TAG>

    Registry Image
    Docker Hub jetsung/rclone-backup
    GitHub Container Registry ghcr.io/jetsung/rclone-backup
    Tencent Cloud Container Registry(SG) sgccr.ccs.tencentyun.com/jetsung/rclone-backup
    Aliyun Container Registry(GZ) registry.cn-guangzhou.aliyuncs.com/jetsung/rclone-backup
docker-bake.hcl Bruto
1## https://docs.docker.com/build/bake/
2## https://docs.docker.com/reference/cli/docker/buildx/bake/#set
3## https://github.com/crazy-max/buildx#remote-with-local
4## https://github.com/docker/metadata-action
5
6variable "VERSION" {
7 default = "latest"
8}
9
10## Special target: https://github.com/docker/metadata-action#bake-definition
11target "docker-metadata-action" {}
12
13target "_image" {
14 inherits = ["docker-metadata-action"]
15}
16
17target "_common" {
18 context = "."
19 dockerfile = "docker/Dockerfile"
20 platforms = ["linux/amd64"]
21 args = {
22 VERSION = "${VERSION}"
23 }
24}
25
26target "default" {
27 inherits = ["_common"]
28 tags = [
29 "app:local",
30 ]
31}
32
33group "dev" {
34 targets = ["dev"]
35}
36
37target "dev" {
38 inherits = ["_common", "_image"]
39}
40
41group "release" {
42 targets = ["release"]
43}
44
45target "release" {
46 inherits = ["_common", "_image"]
47 platforms = ["linux/amd64","linux/arm64"]
48}
docker-dev.yml Bruto
1name: Docker-Dev
2
3on:
4 push:
5 branches:
6 - dev*
7 paths:
8 - "docker/Dockerfile"
9 - ".github/workflows/docker-dev.yml"
10
11env:
12 GHCR_SLUG: ghcr.io/${{ github.repository }}
13
14permissions:
15 contents: read
16 packages: write
17
18jobs:
19 build:
20 strategy:
21 matrix:
22 include:
23 - arch: amd64
24 runner: ubuntu-24.04
25 tag: dev-amd64
26 - arch: arm64
27 runner: ubuntu-24.04-arm
28 tag: dev-arm64
29 runs-on: ${{ matrix.runner }}
30 outputs:
31 package_name: ${{ steps.get_package_name.outputs.package_name }}
32 steps:
33 - name: Checkout Source Code
34 uses: actions/checkout@v6
35
36 - name: Set package name
37 id: get_package_name
38 run: |
39 PACKAGE_NAME="$(basename ${{ github.repository }})"
40 echo "package_name=$PACKAGE_NAME" >> $GITHUB_ENV
41 echo "package_name=$PACKAGE_NAME" >> $GITHUB_OUTPUT
42
43 - name: Login to GitHub Container Registry (ghcr.io)
44 uses: docker/login-action@v4
45 with:
46 registry: ghcr.io
47 username: ${{ github.actor }}
48 password: ${{ secrets.GITHUB_TOKEN }}
49
50 # - name: Docker meta
51 # id: meta
52 # uses: docker/metadata-action@v6
53 # with:
54 # images: ${{ env.GHCR_SLUG }}
55 # labels: |
56 # org.opencontainers.image.title=${{ env.package_name }}
57 # org.opencontainers.image.vendor=Jetsung Chan
58 # [email protected]
59 # org.opencontainers.image.url=https://i.jetsung.com
60 # tags: ${{ matrix.tag }}
61
62 # - name: Set up Docker Buildx
63 # uses: docker/setup-buildx-action@v4
64
65 # - name: Build (without push)
66 # uses: docker/bake-action@v7
67 # with:
68 # files: |
69 # ./docker/docker-bake.hcl
70 # cwd://${{ steps.meta.outputs.bake-file }}
71 # targets: ${{ matrix.tag }}
72 # push: ${{ github.event_name != 'pull_request' }}
73
74 - name: Build and push
75 uses: docker/build-push-action@v7
76 with:
77 context: .
78 file: ./docker/Dockerfile
79 platforms: linux/${{ matrix.arch }}
80 push: ${{ github.event_name != 'pull_request' }}
81 tags: ${{ env.GHCR_SLUG }}:${{ matrix.tag }}
82
83 manifest:
84 needs: build
85 runs-on: ubuntu-24.04
86 steps:
87 - name: Checkout code
88 uses: actions/checkout@v6
89
90 - name: Log in to GHCR
91 uses: docker/login-action@v4
92 with:
93 registry: ghcr.io
94 username: ${{ github.actor }}
95 password: ${{ secrets.GITHUB_TOKEN }}
96
97 - name: Create and push multi-arch manifest
98 run: |
99 docker manifest create ${{ env.GHCR_SLUG }}:dev \
100 --amend ${{ env.GHCR_SLUG }}:dev-amd64 \
101 --amend ${{ env.GHCR_SLUG }}:dev-arm64
102 docker manifest push ${{ env.GHCR_SLUG }}:dev
103 shell: bash
104
105 - uses: actions/delete-package-versions@v5
106 continue-on-error: true
107 with:
108 package-name: ${{ needs.build.outputs.package_name }}
109 package-type: 'container'
110 min-versions-to-keep: 2
111 delete-only-untagged-versions: 'true'
112
docker-release.yml Bruto
1name: Docker-Release
2
3on:
4 push:
5 tags:
6 - "*"
7 # release:
8 # types: [created]
9 # branches:
10 # - 'main'
11 workflow_dispatch:
12 inputs:
13 version:
14 description: 'Version tag'
15 required: false
16 default: ''
17
18env:
19 branch: latest
20 image_org: jetsung
21 acr_registry: registry.cn-guangzhou.aliyuncs.com
22 hcr_registry: swr.ap-southeast-3.myhuaweicloud.com
23 tcr_registry: sgccr.ccs.tencentyun.com
24 package_name: app
25
26permissions:
27 contents: read
28 packages: write
29
30jobs:
31 build:
32 runs-on: ubuntu-24.04
33 outputs:
34 tag: ${{ steps.get_version.outputs.version }}
35 package_name: ${{ env.package_name }}
36 steps:
37 - name: Checkout Source Code
38 uses: actions/checkout@v6
39 with:
40 ref: 'main'
41
42 - name: Get version
43 id: get_version
44 run: |
45 if [[ "${{ github.event_name }}" == "push" && "${{ github.ref_type }}" == "tag" ]]; then
46 version=${{ github.ref_name }}
47 elif [[ "${{ github.event_name }}" == "workflow_dispatch" && -n "${{ github.event.inputs.version }}" ]]; then
48 version=${{ github.event.inputs.version }}
49 else
50 version=latest-$(date +%Y%m%d)
51 fi
52 echo "version=${version#v}" >> $GITHUB_OUTPUT
53
54 - name: Set up QEMU
55 uses: docker/setup-qemu-action@v4
56
57 - name: Set up Docker Buildx
58 uses: docker/setup-buildx-action@v4
59
60 - name: Docker meta
61 id: meta
62 uses: docker/metadata-action@v6
63 with:
64 images: ${{ env.package_name }}
65 labels: |
66 org.opencontainers.image.title=${{ env.package_name }}
67 org.opencontainers.image.vendor=Jetsung Chan
68 tags: |
69 type=raw,value=latest
70
71 - name: Build with Bake
72 uses: docker/bake-action@v7
73 with:
74 files: |
75 ./docker/docker-bake.hcl
76 cwd://${{ steps.meta.outputs.bake-file }}
77 targets: release
78 push: false
79 provenance: false
80 set: |
81 *.attest=type=provenance,disabled=true
82 *.attest=type=sbom,disabled=true
83 *.output=type=oci,dest=./image.tar
84 release.args.VERSION=${{ steps.get_version.outputs.version }}
85
86 # - name: Build image and create OCI artifact
87 # uses: docker/build-push-action@v7
88 # with:
89 # context: .
90 # platforms: linux/amd64,linux/arm64
91 # push: false
92 # provenance: false
93 # build-args: |
94 # VERSION=${{ steps.get_version.outputs.version }}
95 # outputs: type=oci,dest=./image.tar
96
97 - name: Upload image as artifact
98 uses: actions/upload-artifact@v7
99 with:
100 name: docker-image
101 path: ./image.tar
102 retention-days: 1
103
104 sync-to-docker:
105 needs: build
106 runs-on: ubuntu-24.04
107 continue-on-error: true
108 steps:
109 - name: Check Docker Hub credentials
110 id: check_dockerhub
111 run: |
112 if [ -z "${{ secrets.DOCKERHUB_USERNAME }}" ] || [ -z "${{ secrets.DOCKERHUB_TOKEN }}" ]; then
113 echo "Docker Hub credentials not configured, skipping..."
114 echo "skip=true" >> $GITHUB_OUTPUT
115 else
116 echo "skip=false" >> $GITHUB_OUTPUT
117 fi
118 - name: Install Skopeo
119 if: steps.check_dockerhub.outputs.skip != 'true'
120 uses: jetsung/install-skopeo@v1
121 - name: Check Skopeo
122 if: steps.check_dockerhub.outputs.skip != 'true'
123 run: |
124 skopeo --version
125 - name: Login to Docker Hub
126 if: steps.check_dockerhub.outputs.skip != 'true'
127 uses: docker/login-action@v4
128 with:
129 username: ${{ secrets.DOCKERHUB_USERNAME }}
130 password: ${{ secrets.DOCKERHUB_TOKEN }}
131 - name: Download image artifact
132 if: steps.check_dockerhub.outputs.skip != 'true'
133 uses: actions/download-artifact@v8
134 with:
135 name: docker-image
136 path: .
137 - name: Sync to Docker Hub
138 if: steps.check_dockerhub.outputs.skip != 'true'
139 env:
140 SRC_IMAGE: oci-archive:./image.tar
141 DEST_REPO: ${{ env.image_org }}/${{ env.package_name }}
142 DEST_TAG: ${{ needs.build.outputs.tag }}
143 run: |
144 skopeo copy --all $SRC_IMAGE docker://$DEST_REPO:$DEST_TAG
145 skopeo copy --all $SRC_IMAGE docker://$DEST_REPO:latest
146
147 sync-to-ghcr:
148 needs: build
149 runs-on: ubuntu-24.04
150 steps:
151 - name: Install Skopeo
152 uses: jetsung/install-skopeo@v1
153 - name: Check Skopeo
154 run: |
155 skopeo --version
156 - name: Login to GitHub Container Registry (ghcr.io)
157 uses: docker/login-action@v4
158 with:
159 registry: ghcr.io
160 username: ${{ github.actor }}
161 password: ${{ secrets.GITHUB_TOKEN }}
162 - name: Download image artifact
163 uses: actions/download-artifact@v8
164 with:
165 name: docker-image
166 path: .
167 - name: Sync to GitHub Container Registry (ghcr.io)
168 env:
169 SRC_IMAGE: oci-archive:./image.tar
170 DEST_REPO: ghcr.io/${{ github.repository_owner }}/${{ env.package_name }}
171 DEST_TAG: ${{ needs.build.outputs.tag }}
172 run: |
173 skopeo copy --all $SRC_IMAGE docker://$DEST_REPO:$DEST_TAG
174 skopeo copy --all $SRC_IMAGE docker://$DEST_REPO:latest
175 - uses: actions/delete-package-versions@v5
176 continue-on-error: true
177 with:
178 package-name: ${{ env.package_name }}
179 package-type: 'container'
180 min-versions-to-keep: 2
181 delete-only-untagged-versions: 'true'
182
183 sync-to-aliyun:
184 needs: build
185 runs-on: ubuntu-24.04
186 continue-on-error: true
187 steps:
188 - name: Check Aliyun credentials
189 id: check_aliyun
190 run: |
191 if [ -z "${{ secrets.ALIYUN_USERNAME }}" ] || [ -z "${{ secrets.ALIYUN_TOKEN }}" ]; then
192 echo "Aliyun credentials not configured, skipping..."
193 echo "skip=true" >> $GITHUB_OUTPUT
194 else
195 echo "skip=false" >> $GITHUB_OUTPUT
196 fi
197 - name: Install Skopeo
198 if: steps.check_aliyun.outputs.skip != 'true'
199 uses: jetsung/install-skopeo@v1
200 - name: Check Skopeo
201 if: steps.check_aliyun.outputs.skip != 'true'
202 run: |
203 skopeo --version
204 - name: Login to Aliyun
205 if: steps.check_aliyun.outputs.skip != 'true'
206 uses: docker/login-action@v4
207 with:
208 registry: ${{ env.acr_registry }}
209 username: ${{ secrets.ALIYUN_USERNAME }}
210 password: ${{ secrets.ALIYUN_TOKEN }}
211 - name: Download image artifact
212 if: steps.check_aliyun.outputs.skip != 'true'
213 uses: actions/download-artifact@v8
214 with:
215 name: docker-image
216 path: .
217 - name: Sync to Aliyun
218 if: steps.check_aliyun.outputs.skip != 'true'
219 env:
220 SRC_IMAGE: oci-archive:./image.tar
221 DEST_REPO: ${{ env.acr_registry }}/${{ env.image_org }}/${{ env.package_name }}
222 DEST_TAG: ${{ needs.build.outputs.tag }}
223 run: |
224 skopeo copy --all $SRC_IMAGE docker://$DEST_REPO:$DEST_TAG
225 skopeo copy --all $SRC_IMAGE docker://$DEST_REPO:latest
226
227 sync-to-tencent:
228 needs: build
229 runs-on: ubuntu-24.04
230 continue-on-error: true
231 steps:
232 - name: Check Tencent credentials
233 id: check_tencent
234 run: |
235 if [ -z "${{ secrets.TENCENT_USERNAME }}" ] || [ -z "${{ secrets.TENCENT_TOKEN }}" ]; then
236 echo "Tencent credentials not configured, skipping..."
237 echo "skip=true" >> $GITHUB_OUTPUT
238 else
239 echo "skip=false" >> $GITHUB_OUTPUT
240 fi
241 - name: Install Skopeo
242 if: steps.check_tencent.outputs.skip != 'true'
243 uses: jetsung/install-skopeo@v1
244 - name: Check Skopeo
245 if: steps.check_tencent.outputs.skip != 'true'
246 run: |
247 skopeo --version
248 - name: Login to Tencent
249 if: steps.check_tencent.outputs.skip != 'true'
250 uses: docker/login-action@v4
251 with:
252 registry: ${{ env.tcr_registry }}
253 username: ${{ secrets.TENCENT_USERNAME }}
254 password: ${{ secrets.TENCENT_TOKEN }}
255 - name: Download image artifact
256 if: steps.check_tencent.outputs.skip != 'true'
257 uses: actions/download-artifact@v8
258 with:
259 name: docker-image
260 path: .
261 - name: Sync to Tencent
262 if: steps.check_tencent.outputs.skip != 'true'
263 env:
264 SRC_IMAGE: oci-archive:./image.tar
265 DEST_REPO: ${{ env.tcr_registry }}/${{ env.image_org }}/${{ env.package_name }}
266 DEST_TAG: ${{ needs.build.outputs.tag }}
267 run: |
268 skopeo copy --all $SRC_IMAGE docker://$DEST_REPO:$DEST_TAG
269 skopeo copy --all $SRC_IMAGE docker://$DEST_REPO:latest
270
271