要使用 GitHub Actions 自动打包 Docker 镜像并上传到 Docker Hub,可按以下步骤操作,通过配置工作流文件实现自动化流程:
Docker Hub 账号
确保拥有 Docker Hub 账号,并创建一个仓库(如 username/your-image-name)。
GitHub 仓库
将项目代码推送到 GitHub 仓库,确保代码中包含 Dockerfile(用于构建镜像)。
配置 Docker Hub 凭据 在 GitHub 仓库的 Settings → Secrets and variables → Actions → New repository secret 中添加两个密钥:
DOCKER_HUB_USERNAME:Docker Hub 用户名DOCKER_HUB_ACCESS_TOKEN:Docker Hub 访问令牌(在 Docker Hub 账号设置 中生成,需勾选 write 权限)在 GitHub 仓库中创建工作流配置文件,路径为:
.github/workflows/docker-build-push.yml
文件内容如下(可根据需求调整):
yamlname: Build and Push Docker Image
# 触发条件:当推送到 main 分支或创建标签时执行
on:
  push:
    branches: [ "main" ]
    tags: [ "v*.*.*" ]  # 匹配类似 v1.0.0 的标签
jobs:
  build-and-push:
    runs-on: ubuntu-latest  # 使用 Ubuntu 环境
    steps:
      # 步骤 1:拉取 GitHub 仓库代码
      - name: Checkout code
        uses: actions/checkout@v4
      # 步骤 2:设置 Docker 构建环境
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
      # 步骤 3:登录 Docker Hub
      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_HUB_USERNAME }}
          password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
      # 步骤 4:提取镜像标签(支持分支和标签触发)
      - name: Extract metadata (tags, labels)
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ${{ secrets.DOCKER_HUB_USERNAME }}/your-image-name  # 替换为你的 Docker Hub 仓库名
          tags: |
            type=ref,event=branch  # 分支触发时,标签为分支名(如 main)
            type=semver,pattern={{version}}  # 标签触发时,标签为版本号(如 v1.0.0 → 1.0.0)
            type=semver,pattern={{major}}.{{minor}}  # 标签触发时,额外添加主版本标签(如 1.0)
      # 步骤 5:构建并推送 Docker 镜像
      - name: Build and push Docker image
        uses: docker/build-push-action@v5
        with:
          context: .  # Dockerfile 所在目录(当前目录)
          push: true  # 推送镜像到 Docker Hub
          tags: ${{ steps.meta.outputs.tags }}  # 使用步骤 4 生成的标签
          labels: ${{ steps.meta.outputs.labels }}  # 附加元数据标签
触发条件(on )
示例中配置了推送到 main 分支或创建 v*.*.* 格式的标签时触发工作流,可根据需求修改(如添加 pull_request 触发)。
镜像标签(tags)
通过 docker/metadata-action 自动生成标签:
main 分支时,标签为 main(方便测试环境使用)。v1.0.0 时,生成标签 1.0.0 和 1.0(方便生产环境指定版本)。构建上下文(context )
默认为当前目录(.),若 Dockerfile 在子目录(如 ./docker),需修改为 context: ./docker 并通过 file: ./docker/Dockerfile 指定路径。
将配置文件提交到 GitHub 仓库的 main 分支。
触发工作流:
main 分支,工作流会自动运行并推送 main 标签的镜像。git tag v1.0.0 && git push origin v1.0.0),工作流会推送 1.0.0 和 1.0 标签的镜像。在 GitHub 仓库的 Actions 标签页中查看工作流运行状态,成功后可在 Docker Hub 仓库中看到推送的镜像。
例如,项目根目录下有个docker-composr.yml文件,其作用是从子目录里分别构建两个镜像siyuan044/timelesstales-backend和siyuan044/timelesstales-frontend
ymlversion: '3.8'
services:
  backend:
    build: ./package/server
    # 用环境变量 ${TAG} 动态指定版本(默认 fallback 到 v0.1.0)
    image: siyuan044/timelesstales-backend:${TAG:-v0.1.0}
    restart: always
    expose: [ "8000" ]
    networks: [ app-network ]
    volumes: [ "./package/server/data:/app/data" ]
  frontend:
    build: ./package/website
    image: siyuan044/timelesstales-frontend:${TAG:-v0.1.0}
    restart: always
    ports: [ "8081:80" ]
    depends_on: [ backend ]
    networks: [ app-network ]
networks:
  app-network:
    driver: bridge
此时可以使用 docker compose build命令构建镜像(注意部署docker-compose build)
yml      # 构建镜像(基于基础标签)
      - name: Build images with docker compose
        run: |
          TAG=${{ env.BASE_TAG }} docker compose build
当创建新的 Tag 时(如 v1.0.1),希望同时将 latest 标签指向该最新版本的镜像,可以在推送时额外添加 latest 标签。以下是具体实现方案,确保每次发布新 Tag 时,latest 会自动更新为该版本。
v1.0.1),除了推送 1.0.1 标签的镜像,额外推送 latest 标签的镜像。main),仅推送分支标签(不影响 latest,避免开发版本覆盖正式版)。更新 .github/workflows/docker-compose-build-push.yml,重点调整 镜像标签生成 和 推送逻辑:
ymlname: Build and Push Multi Docker Images with Compose
on:
  push:
    branches: [ "main" ]
    tags: [ "v*.*.*" ]
jobs:
  build-and-push:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
      - name: Set up Docker
        uses: docker/setup-buildx-action@v3
      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_HUB_USERNAME }}
          password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
      # 步骤:生成基础标签和额外标签(如 latest)
      - name: Determine image tags
        id: set-tags
        run: |
          # 基础标签(分支名或 Tag 版本)
          if [[ $GITHUB_REF == refs/tags/* ]]; then
            BASE_TAG=${GITHUB_REF#refs/tags/v}  # 如 v1.0.1 → 1.0.1
            EXTRA_TAGS="latest"  # Tag 触发时,额外添加 latest 标签
          else
            BASE_TAG=${GITHUB_REF#refs/heads/}  # 如 main 分支 → main
            EXTRA_TAGS=""  # 分支触发时,不添加 latest
          fi
          # 组合所有标签(用逗号分隔,供后续推送)
          ALL_TAGS="$BASE_TAG"
          if [ -n "$EXTRA_TAGS" ]; then
            ALL_TAGS="$BASE_TAG,$EXTRA_TAGS"
          fi
          # 输出环境变量(后端和前端镜像名相同,仅标签变化)
          echo "BASE_TAG=$BASE_TAG" >> $GITHUB_ENV
          echo "ALL_TAGS=$ALL_TAGS" >> $GITHUB_ENV
      # 构建镜像(基于基础标签)
      - name: Build images with docker compose
        run: |
          TAG=${{ env.BASE_TAG }} docker compose build
      # 推送镜像(包含所有标签:基础标签 + latest(若有))
      - name: Push backend images
        run: |
          # 拆分标签并逐个推送(或用 docker tag 批量处理)
          IFS=',' read -ra TAGS <<< "${{ env.ALL_TAGS }}"
          for TAG in "${TAGS[@]}"; do
            # 先给镜像打多标签,再推送
            docker tag ${{ secrets.DOCKER_HUB_USERNAME }}/timelesstales-backend:${{ env.BASE_TAG }} ${{ secrets.DOCKER_HUB_USERNAME }}/timelesstales-backend:$TAG
            docker push ${{ secrets.DOCKER_HUB_USERNAME }}/timelesstales-backend:$TAG
          done
      - name: Push frontend images
        run: |
          IFS=',' read -ra TAGS <<< "${{ env.ALL_TAGS }}"
          for TAG in "${TAGS[@]}"; do
            docker tag ${{ secrets.DOCKER_HUB_USERNAME }}/timelesstales-frontend:${{ env.BASE_TAG }} ${{ secrets.DOCKER_HUB_USERNAME }}/timelesstales-frontend:$TAG
            docker push ${{ secrets.DOCKER_HUB_USERNAME }}/timelesstales-frontend:$TAG
          done
本文作者:司小远
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!