东东's Blog

GoReleaser 自动发布 Go 镜像到 DockerHub & GitHub Release

差不多两年前学习记录过《使用 Github Action 自动构建 Release 版本》,也研究过《使用 Docker 构建多架构镜像》,手动推镜像到 DockerHub,其实一直还差最后一公里 —— 提交代码到 Github 自动构建 Release 二进制成品,并构建镜像推送到 DockerHub 仓库。

而这就是 Goreleaser 所擅长的,本文记录了相关配置和使用方式。

本地安装 Goreleaser#

brew install goreleaser

Go Releaser 配置#

在项目根目录执行初始化,生成 .goreleaser.yaml 配置文件

goreleaser init

按需修改,我的示例配置如下

version: 2

project_name: passkey-demo

before:
  hooks:
    - go mod tidy

builds:
  - id: server
    main: .
    binary: passkey-demo
    env:
      - CGO_ENABLED=0
    goos:
      - linux
      - darwin
    goarch:
      - amd64
      - arm64
    ldflags:
      - -s -w
      - -X main.version={{ .Version }}
      - -X main.commit={{ .Commit }}

archives:
  - id: default
    formats: [tar.gz]
    name_template: >-
      {{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}

checksum:
  name_template: checksums.txt

changelog:
  use: github
  sort: asc
  filters:
    exclude:
      - "^docs:"
      - "^test:"
      - "^chore:"

release:
  draft: true
  prerelease: auto
  footer: |
    ---
    Released by GoReleaser.

dockers_v2:
  - id: server
    ids:
      - server
    dockerfile: Dockerfile
    platforms:
      - linux/amd64
      - linux/arm64
    images:
      - "{{ .Env.DOCKERHUB_USERNAME }}/passkey-demo"
    tags:
      - "{{ .Version }}"
      - latest

注意需要在 GitHub Actions secrets 中配置 DOCKERHUB_USERNAME(以及后文的 DOCKERHUB_TOKEN),YAML 中通过 {{ .Env.DOCKERHUB_USERNAME }} 读取

Github Action 配置#

创建/修改 .github/workflows/release.yml 文件,内容如下:

name: Release

on:
  push:
    tags:
      - 'v*'

permissions:
  contents: write

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
        with:
          fetch-depth: 0

      - uses: actions/setup-go@v6
        with:
          go-version: '1.25'
          check-latest: true

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

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

      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Run GoReleaser
        uses: goreleaser/goreleaser-action@v6
        with:
          version: latest
          args: release --clean
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}

以上配置的 secrets.GITHUB_TOKEN 无需手动配置,Docker 的两个环境变量需要配置。

获取 Docker User Access Token

点击右上角头像,点击 “Account Settings” - “Settings” 下的 “Personal access tokens”,创建一个 “Read & Write” 权限的 Token

02.webp

生成的 Token 只展示一次,复制下来使用,即 secrets.DOCKERHUB_TOKEN

在 Github 上配置 Secrets

点击 Github 仓库的 “Settings”,侧边栏找到 “Secrets and variables”,我这里添加的是 Repository secrets 类型

03.webp

Dockerfile 配置参考#

放到项目根目录

FROM alpine:3.23

RUN apk add --no-cache ca-certificates

WORKDIR /app

# 使用构建参数获取目标平台(GoReleaser dockers_v2)
ARG TARGETPLATFORM

# GoReleaser 将二进制文件放在 <os>/<arch>/ 目录下,即 TARGETPLATFORM
COPY ${TARGETPLATFORM}/passkey-demo /app/passkey-demo

EXPOSE 8080

ENTRYPOINT ["/app/passkey-demo"]

本地测试构建#

注意替换 DOCKERHUB_USERNAME 为你的用户名

DOCKERHUB_USERNAME=your-username goreleaser release --snapshot --clean

04.webp

查看构建的镜像

docker images | grep passkey-demo

已构建出镜像

05.webp

如果想进一步运行测试镜像,可以运行:

docker run --rm -p 8080:8080 kissbug8720/passkey-demo:latest

推送标签触发构建#

git tag v0.0.12

git push origin v0.0.12

在仓库的 Action 可以看到构建任务。

06.webp

构建完成后,在 Github 仓库的 releases 可以看到一个 Draft 类型的发布,点击编辑,可修改描述,二进制成品也可以编辑,发布后即对外部可见。

Github Release

07.webp

Docker Hub 镜像

访问:https://hub.docker.com/r/kissbug8720/passkey-demo/tags

08.webp

可以看到 0.0.12 标签后 latest 标签的镜像。

最后#

从「手动编译难以维护的脚本」到「封装良好的现代化发布方案」,Golang 项目非常推荐使用 Goreleaser 进行发布。