IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    简明 Docker + GitHub Actions 自动化部署教程

    NX の 博客发表于 2024-03-22 14:50:45
    love 0

    我之前其实写过一些 cicd 的教程,但是写的太烂了,这篇算重构

    直入正题,我会用我的一个 gin-rush-template 来做为 demo 演示

    你可以模仿下面的过程为自己的项目实现自动化部署

    我的 demo 的其实写的很烂的,但是你只需要知道它有三个特点,无需关注其他细节:

    1. 会从 config/config.yaml 读取配置文件
    2. 需要连接 MySQL 依赖
    3. 能提供一个 /ping 接口

    我们先做到让它在本地跑起来,首先 clone 下来,然后跟随下面的操作

    1
    2
    3
    4
    5
    6
    7
    8
    # 复制一份配置文件
    cp config/config.example.yaml config/config.yaml

    # 运行 MySQL 依赖
    docker-compose -f docker-compose-env.yml up -d

    # 运行 Go 程序
    go run main.go

    如果没有报错,并且 curl 能正常提供服务,那么就没有问题了

    1
    2
    curl http://127.0.0.1:8080/ping
    {"message":"pong"}

    image-2024032273050526 PM

    或者你可以在浏览器中手动访问 http://127.0.0.1:8080/ping


    体验手动部署

    安装 Docker

    接下来将体验手动编译并部署 Docker Image 到服务器,我以本地 OrbStack 提供的 Debian12 arm64 虚拟机为例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    nx@debian:~$ screenfetch
    _,met$$$$$gg. nx@debian
    ,g$$$$$$$$$$$$$$$P. OS: Debian
    ,g$$P"" """Y$$.". Kernel: aarch64 Linux 6.5.13-orbstack-00122-g57b8027e2387
    ,$$P' `$$$. Uptime: 3h 56m
    ',$$P ,ggs. `$$b: Packages: 275
    `d$$' ,$P"' . $$$ Shell: bash 5.2.15
    $$P d$' , $$P Disk: 442G / 1.4T (32%)
    $$: $$. - ,d$$' CPU: Apple - @ 8x 2GHz
    $$\; Y$b._ _,d$P' RAM: 979MiB / 5250MiB
    Y$$. `.`"Y$$$$P"'
    `$$b "-.__
    `Y$$
    `Y$$.
    `$$b.
    `Y$$b.
    `"Y$b._
    `""""

    请注意,本教程全程使用 arm64 架构(或称 aarch64 架构),而一般情况下云服务商提供的服务器为 amd64 架构(或称 x64 或 x86_64 架构)

    服务器一般仅能运行当前的架构的 Docker Image,如果你的本地架构与目标架构不相同,则需要使用 bulidx 进行交叉编译,这并不在本文的讨论过程中

    或者你可以跳过实践「手动部署」部分,而记得在后文编写 GitHub Actions 时记得选择与目标匹配的架构编译

    首先是在服务器安装 Docker 和 Docker Compose,这一点可以前往官方文档查看

    1
    2
    3
    4
    nx@debian:~$ docker -v
    Docker version 20.10.24+dfsg1, build 297e128
    nx@debian:~$ docker-compose -v
    Docker Compose version v2.25.0

    当然,你在本地也应当安装 Docker 和 Docker Compose,一般情况下 Docker Desktop 或者 OrbStack 会是很好的选择

    如果你从未听说过 Docker 与 Docker Compose,可以前往 Bilibili 或者 YouTube 学习

    编译 Docker Image

    接下来从项目根目录的 Dockerfile 编译 Docker Image

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    FROM golang:latest as go-build-stage

    ENV GOPROXY https://goproxy.cn,direct

    WORKDIR /go/src/app

    COPY . .

    RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .

    FROM scratch

    WORKDIR /app

    COPY --from=go-build-stage /go/src/app/main .

    CMD ["./main"]
    1
    docker build -t gin-rush-template:v1 .

    编译完成后检查得到的 Image

    1
    2
    3
    docker images
    REPOSITORY TAG IMAGE ID CREATED SIZE
    gin-rush-template v1 c21723202467 About a minute ago 21.1MB

    推送至 Docker Hub

    现在我们要将这个 Image 传递到服务器上,这里可以上传到某些镜像仓库中,或者导出为文件再在服务器上从文件导入

    这里我们直接上传到 Docker Hub(或者你可以使用一些云厂商的服务,这就需要查看对应的文档)

    假设你已经注册了 Docker Hub 的账号,请在终端使用 docker login 进行登陆

    在推送镜像之前,需要确保镜像被正确标记,以便符合 Docker Hub 的格式要求

    一般的格式为

    1
    <你的用户名>/<应用名>:<版本标签>

    而我们目前的镜像并没有用户名,所以需要使用 docker tag 重新命名

    1
    docker tag gin-rush-template:v1 yourusername/gin-rush-template:v1

    请将 yourusername 替换为你的 Docker Hub 用户名,比如我需要执行

    1
    docker tag gin-rush-template:v1 nxofficial/gin-rush-template:v1

    现在,我们得到了一个名为 nxofficial/gin-rush-template 的镜像,它与之前的镜像指向一个相同的 ID,说明它们其实是一样的

    1
    2
    3
    4
    docker images
    REPOSITORY TAG IMAGE ID CREATED SIZE
    gin-rush-template v1 c21723202467 14 minutes ago 21.1MB
    nxofficial/gin-rush-template v1 c21723202467 14 minutes ago 21.1MB

    下面,可以使用 docker push 推送镜像(如果被拒绝请先使用 docker login 进行登陆)

    1
    2
    3
    4
    5
    docker push nxofficial/gin-rush-template:v1
    The push refers to repository [docker.io/nxofficial/gin-rush-template]
    c84414e107f0: Pushed
    3b8bd6ab22a4: Pushed
    v1: digest: sha256:4d1b5f800ba3ec7022fc9dec77ec1e8fd9d2dc103825373ab2dec2c3b6015fb5 size: 734

    现在在 Docker Hub 上已经能找到我们推送的镜像

    image-2024032280040822 PM

    你可以看见,这个镜像是 arm64 架构

    拉取并运行镜像

    下面的任务就是在服务器上拉取并运行镜像

    首先找到 deploy 目录,其中的文件需要上传至服务器

    1
    2
    3
    4
    5
    6
    tree .
    .
    ├── config.yaml
    └── docker-compose.yaml

    1 directory, 2 files

    其中 congfig.yaml 是要映射进 Docker 容器的配置文件

    注意如何在 Docker 网络中访问某个容器提供的服务:直接使用服务名作为域名即可

    1
    2
    3
    Mysql:
    Host: "mysql" # 而不是 127.0.0.1
    Port: "3306"

    而 docker-compose.yaml 用于编排服务

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    version: '2.1' # 之所以不用3是因为3砍了好用的健康检查而逼你用没人用的 Docker Swarm

    networks:
    gin-rush-template-net:
    driver: bridge

    services:
    app:
    image: nxofficial/gin-rush-template:v1 # 这里后面被改成了 latest,但是先使用 v1 体验一下
    container_name: gin-rush-template-app
    volumes:
    - ./config.yaml:/app/config/config.yaml # 将配置文件映射进来
    ports:
    - "8080:8080"
    depends_on:
    mysql:
    condition: service_healthy
    networks:
    - gin-rush-template-net

    mysql:
    image: mysql:8.0
    container_name: gin-rush-template-mysql
    environment:
    MYSQL_ROOT_PASSWORD: 12345678
    MYSQL_DATABASE: gin-rush-template
    TZ: Asia/Shanghai
    healthcheck:
    # MySQL 就绪检测
    test: [ "CMD", "mysqladmin" ,"ping", "-h", "localhost" ]
    interval: 5s
    retries: 10
    privileged: true
    restart: always
    networks:
    - gin-rush-template-net

    之后运行即可,他会自动拉下来

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    $ sudo docker-compose up
    WARN[0000] /Users/nx/GolandProjects/gin-rush-template/deploy/docker-compose.yaml: `version` is obsolete
    [+] Running 2/0
    ✔ Container gin-rush-template-mysql Created 0.0s
    ✔ Container gin-rush-template-app Created 0.0s
    Attaching to gin-rush-template-app, gin-rush-template-mysql
    gin-rush-template-mysql | 2024-03-22 21:21:20+08:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.36-1.el8 started.
    gin-rush-template-mysql | 2024-03-22 21:21:20+08:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
    gin-rush-template-mysql | 2024-03-22 21:21:20+08:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.36-1.el8 started.
    gin-rush-template-mysql | '/var/lib/mysql/mysql.sock' -> '/var/run/mysqld/mysqld.sock'
    gin-rush-template-mysql | 2024-03-22T13:21:21.278083Z 0 [Warning] [MY-011068] [Server] The syntax '--skip-host-cache' is deprecated and will be removed in a future release. Please use SET GLOBAL host_cache_size=0 instead.
    gin-rush-template-mysql | 2024-03-22T13:21:21.279792Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.0.36) starting as process 1
    gin-rush-template-mysql | 2024-03-22T13:21:21.284859Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
    gin-rush-template-mysql | 2024-03-22T13:21:21.367493Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
    gin-rush-template-mysql | 2024-03-22T13:21:21.494743Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.
    gin-rush-template-mysql | 2024-03-22T13:21:21.494766Z 0 [System] [MY-013602] [Server] Channel mysql_main configured to support TLS. Encrypted connections are now supported for this channel.
    gin-rush-template-mysql | 2024-03-22T13:21:21.495550Z 0 [Warning] [MY-011810] [Server] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory.
    gin-rush-template-mysql | 2024-03-22T13:21:21.504335Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Bind-address: '::' port: 33060, socket: /var/run/mysqld/mysqlx.sock
    gin-rush-template-mysql | 2024-03-22T13:21:21.504354Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.36' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server - GPL.
    gin-rush-template-app |
    gin-rush-template-app | 2024/03/22 13:21:26 /go/src/app/internal/global/database/mysql.go:36
    gin-rush-template-app | [0.078ms] [rows:-] SELECT DATABASE()
    gin-rush-template-app |
    gin-rush-template-app | 2024/03/22 13:21:26 /go/src/app/internal/global/database/mysql.go:36
    gin-rush-template-app | [1.725ms] [rows:1] SELECT SCHEMA_NAME from Information_schema.SCHEMATA where SCHEMA_NAME LIKE 'gin-rush-template%' ORDER BY SCHEMA_NAME='gin-rush-template' DESC,SCHEMA_NAME limit 1
    gin-rush-template-app |
    gin-rush-template-app | 2024/03/22 13:21:26 /go/src/app/internal/global/database/mysql.go:36
    gin-rush-template-app | [0.887ms] [rows:-] SELECT count(*) FROM information_schema.tables WHERE table_schema = 'gin-rush-template' AND table_name = 'user' AND table_type = 'BASE TABLE'
    gin-rush-template-app |
    gin-rush-template-app | 2024/03/22 13:21:26 /go/src/app/internal/global/database/mysql.go:36
    gin-rush-template-app | [0.053ms] [rows:-] SELECT DATABASE()
    gin-rush-template-app |
    gin-rush-template-app | 2024/03/22 13:21:26 /go/src/app/internal/global/database/mysql.go:36
    gin-rush-template-app | [0.200ms] [rows:1] SELECT SCHEMA_NAME from Information_schema.SCHEMATA where SCHEMA_NAME LIKE 'gin-rush-template%' ORDER BY SCHEMA_NAME='gin-rush-template' DESC,SCHEMA_NAME limit 1
    gin-rush-template-app |
    gin-rush-template-app | 2024/03/22 13:21:26 /go/src/app/internal/global/database/mysql.go:36
    gin-rush-template-app | [1.952ms] [rows:-] SELECT * FROM `user` LIMIT 1
    gin-rush-template-app |
    gin-rush-template-app | 2024/03/22 13:21:26 /go/src/app/internal/global/database/mysql.go:36
    gin-rush-template-app | [0.816ms] [rows:-] SELECT column_name, column_default, is_nullable = 'YES', data_type, character_maximum_length, column_type, column_key, extra, column_comment, numeric_precision, numeric_scale , datetime_precision FROM information_schema.columns WHERE table_schema = 'gin-rush-template' AND table_name = 'user' ORDER BY ORDINAL_POSITION
    gin-rush-template-app |
    gin-rush-template-app | 2024/03/22 13:21:26 /go/src/app/internal/global/database/mysql.go:36
    gin-rush-template-app | [0.070ms] [rows:-] SELECT DATABASE()
    gin-rush-template-app |
    gin-rush-template-app | 2024/03/22 13:21:26 /go/src/app/internal/global/database/mysql.go:36
    gin-rush-template-app | [0.190ms] [rows:1] SELECT SCHEMA_NAME from Information_schema.SCHEMATA where SCHEMA_NAME LIKE 'gin-rush-template%' ORDER BY SCHEMA_NAME='gin-rush-template' DESC,SCHEMA_NAME limit 1
    gin-rush-template-app |
    gin-rush-template-app | 2024/03/22 13:21:26 /go/src/app/internal/global/database/mysql.go:36
    gin-rush-template-app | [0.534ms] [rows:-] SELECT count(*) FROM information_schema.statistics WHERE table_schema = 'gin-rush-template' AND table_name = 'user' AND index_name = 'idx_user_deleted_at'
    gin-rush-template-app |
    gin-rush-template-app | 2024/03/22 13:21:26 /go/src/app/internal/global/database/mysql.go:36
    gin-rush-template-app | [0.039ms] [rows:-] SELECT DATABASE()
    gin-rush-template-app |
    gin-rush-template-app | 2024/03/22 13:21:26 /go/src/app/internal/global/database/mysql.go:36
    gin-rush-template-app | [0.149ms] [rows:1] SELECT SCHEMA_NAME from Information_schema.SCHEMATA where SCHEMA_NAME LIKE 'gin-rush-template%' ORDER BY SCHEMA_NAME='gin-rush-template' DESC,SCHEMA_NAME limit 1
    gin-rush-template-app |
    gin-rush-template-app | 2024/03/22 13:21:26 /go/src/app/internal/global/database/mysql.go:36
    gin-rush-template-app | [0.309ms] [rows:-] SELECT count(*) FROM information_schema.statistics WHERE table_schema = 'gin-rush-template' AND table_name = 'user' AND index_name = 'idx_user_email'
    gin-rush-template-app | [GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
    gin-rush-template-app | - using env: export GIN_MODE=release
    gin-rush-template-app | - using code: gin.SetMode(gin.ReleaseMode)
    gin-rush-template-app |
    gin-rush-template-app | [GIN-debug] POST /login --> gin-rush-template/internal/module/user.Login (3 handlers)
    gin-rush-template-app | [GIN-debug] POST /register --> gin-rush-template/internal/module/user.Create (3 handlers)
    gin-rush-template-app | [GIN-debug] GET /ping --> gin-rush-template/internal/module/ping.(*ModulePing).InitRouter.func1 (3 handlers)
    gin-rush-template-app | [GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
    gin-rush-template-app | Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
    gin-rush-template-app | [GIN-debug] Listening and serving HTTP on 0.0.0.0:8080
    gin-rush-template-app | 2024/03/22 13:21:26 Init Module: User
    gin-rush-template-app | 2024/03/22 13:21:26 Init Module: Ping
    gin-rush-template-app | 2024/03/22 13:21:26 InitRouter: User
    gin-rush-template-app | 2024/03/22 13:21:26 InitRouter: Ping

    如果你的服务器位于国内,可能会遇到网络问题,但这不属于本文的内容

    测试运行

    在服务器上测试

    1
    2
    curl 127.0.0.1:8080/ping
    {"message":"pong"}

    在外部测试

    1
    2
    curl http://debian.orb.local:8080/ping
    {"message":"pong"}

    可见服务已经正常运行


    实现自动化部署

    为了实现自动化部署,我们需要有两个环节的自动化:

    1. 每次提交自动构建新镜像并推送至 Docker Hub
    2. 在 Docker Hub 每次收到新的更新时自动拉取并替换为新的 Image

    我们可以先实现第二个自动化

    自动拉取并替换

    我们可以先更改一下代码,突出与之前的不同

    1
    2
    3
    4
    5
    6
    7
    8
     func (p *ModulePing) InitRouter(r *gin.RouterGroup) {
    r.GET("/ping", func(c *gin.Context) {
    c.JSON(200, gin.H{
    "message": "pong",
    + "version": "v2",
    })
    })
    }

    为了监听更新,我们可以使用 Watchtower ,他能自动监听镜像的更新并进行替换

    1
    2
    3
    4
    5
    6
    7
    8
    9
    watchtower:
    image: containrrr/watchtower
    container_name: gin-rush-template-watchtower
    command: --interval 5
    volumes:
    - /var/run/docker.sock:/var/run/docker.sock # 需要将 Docker 的 sock 映射进去以控制 Docker
    restart: always
    networks:
    - gin-rush-template-net

    同时,为了始终拉取最新的版本,我们可以将 app 的预期版本设置为 latest

    1
    2
    - image: nxofficial/gin-rush-template:v1
    + image: nxofficial/gin-rush-template:latest

    然后在本地编译 Docker Image

    1
    2
    3
    4
    5
    # 构建镜像并添加多个标签
    docker build -t nxofficial/gin-rush-template:v2 -t nxofficial/gin-rush-template:latest .
    # 将两个标签都推送过去
    docker push nxofficial/gin-rush-template:latest
    docker push nxofficial/gin-rush-template:v2

    image-2024032295026637 PM

    但你可以看见 latest 和 v2 其实是一个版本,每次重复操作就可以保留每个版本的 Docker Image 并且将 latest 指向最新版本

    image-2024032295053683 PMimage-2024032295100261 PM

    现在,重新启动 docker-compose

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    nx@debian:/Users/nx/GolandProjects/gin-rush-template/deploy$ sudo docker-compose down
    WARN[0000] /Users/nx/GolandProjects/gin-rush-template/deploy/docker-compose.yaml: `version` is obsolete
    [+] Running 3/0
    ✔ Container gin-rush-template-app Removed 0.0s
    ✔ Container gin-rush-template-mysql Removed 0.0s
    ✔ Network deploy_gin-rush-template-net Removed 0.0s
    nx@debian:/Users/nx/GolandProjects/gin-rush-template/deploy$ sudo docker-compose up
    WARN[0000] /Users/nx/GolandProjects/gin-rush-template/deploy/docker-compose.yaml: `version` is obsolete
    [+] Running 7/7
    ✔ app 2 layers [⣿⣿] 0B/0B Pulled 32.2s
    ✔ 11af50565267 Already exists 0.0s
    ✔ 7eb7e9370331 Pull complete 25.0s
    ✔ watchtower 3 layers [⣿⣿⣿] 0B/0B Pulled 31.4s
    ✔ 57241801ebfd Pull complete 9.7s
    ✔ 3d4f475b92a2 Pull complete 9.4s
    ✔ b6a140e9726f Pull complete 21.0s
    [+] Running 4/3
    ✔ Network deploy_gin-rush-template-net Created 0.0s
    ✔ Container gin-rush-template-watchtower Created 0.1s
    ✔ Container gin-rush-template-mysql Created 0.1s
    ✔ Container gin-rush-template-app Created 0.0s

    看看,现在已经是 v2 了

    1
    2
    curl 127.0.0.1:8080/ping
    {"message":"pong","version":"v2"}

    这时,再把版本改成 v3 并重新上传

    1
    2
    3
    docker build -t nxofficial/gin-rush-template:v3 -t nxofficial/gin-rush-template:latest .
    docker push nxofficial/gin-rush-template:v3
    docker push nxofficial/gin-rush-template:latest

    发现 Watchtower 有响应了

    1
    2
    3
    4
    5
    6
    gin-rush-template-watchtower  | time="2024-03-22T13:57:01Z" level=info msg="Session done" Failed=0 Scanned=3 Updated=0 notify=no
    gin-rush-template-watchtower | time="2024-03-22T13:57:21Z" level=info msg="Found new nxofficial/gin-rush-template:latest image (e3283961517d)"
    gin-rush-template-watchtower | time="2024-03-22T13:57:36Z" level=info msg="Stopping /gin-rush-template-app (cbfe32e3ed41) with SIGTERM"
    gin-rush-template-app exited with code 2
    gin-rush-template-watchtower | time="2024-03-22T13:57:37Z" level=info msg="Creating /gin-rush-template-app"
    gin-rush-template-watchtower | time="2024-03-22T13:57:38Z" level=info msg="Session done" Failed=0 Scanned=3 Updated=1 notify=no

    测试,貌似完美

    1
    2
    curl 127.0.0.1:8080/ping
    {"message":"pong","version":"v3"}

    自动打包并上传

    接下来就要实现每次自动打包并上传的功能了,这一般可以使用 GitHub Actions

    在项目根目录下创建 .github/workflows/docker-publish.yaml

    我选择了使用 bulidx 实现交叉编译以支持多种架构

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    name: Build and Push Docker Image

    on:
    push:
    branches:
    - main # 指定触发事件的分支,这里是 main 分支

    jobs:
    build-and-push:
    runs-on: ubuntu-latest
    steps:
    - name: Check out the code
    uses: actions/checkout@v3

    - name: Set up QEMU
    uses: docker/setup-qemu-action@v3

    - name: Set up Docker Buildx
    uses: docker/setup-buildx-action@v3

    # 记得在 GitHub 仓库的 Secrets 中添加 DOCKER_USERNAME DOCKER_PASSWORD DOCKER_REPOSITORY 三个环境变量
    - name: Log in to Docker Hub
    uses: docker/login-action@v3
    with:
    username: ${{ secrets.DOCKER_USERNAME }}
    password: ${{ secrets.DOCKER_PASSWORD }}

    - name: Set short SHA
    id: shortsha
    run: echo "SHORT_SHA=$(echo ${{ github.sha }} | cut -c1-8)" >> $GITHUB_ENV

    - name: Build and push
    uses: docker/build-push-action@v5
    with:
    context: .
    file: ./Dockerfile
    push: true
    # 使用 commit hash 作为镜像 tag
    tags: |
    ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_REPOSITORY }}:latest
    ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_REPOSITORY }}:${{ env.SHORT_SHA }}
    platforms: linux/amd64,linux/arm64 # 为多个架构编译,如果你确定只需要其中一种,可以仅保留一种

    同时请前往 GitHub 上配置你的环境变量,这样运行时就可以读取

    image-20240322102120002 PM

    之后推送 commit,等待自动化编译完成

    image-20240322104728856 PM

    image-20240322104704203 PM

    实际上很多时候会使用 commit hash 作为 tag,我在这里也是这么处理的

    回到服务器,发现 Watchtower 的确拉取了最新的镜像

    1
    2
    curl 127.0.0.1:8080/ping
    {"message":"pong","version":"v4"}

    大功告成❤️



沪ICP备19023445号-2号
友情链接