要使用 GitHub Actions 自动打包 Docker 镜像并上传到 Docker Hub,可按以下步骤操作,通过配置工作流文件实现自动化流程:
步骤 1:准备工作
-
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权限)
步骤 2:创建 GitHub Actions 工作流文件
在 GitHub 仓库中创建工作流配置文件,路径为:
.github/workflows/docker-build-push.yml
文件内容如下(可根据需求调整):
name: 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指定路径。
步骤 3:测试工作流
-
将配置文件提交到 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-compose构建
例如,项目根目录下有个docker-composr.yml文件,其作用是从子目录里分别构建两个镜像siyuan044/timelesstales-backend和siyuan044/timelesstales-frontend
version: '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)
# 构建镜像(基于基础标签)
- name: Build images with docker compose
run: |
TAG=${{ env.BASE_TAG }} docker compose build
补充:自动更新latest标签
当创建新的 Tag 时(如 v1.0.1),希望同时将 latest 标签指向该最新版本的镜像,可以在推送时额外添加 latest 标签。以下是具体实现方案,确保每次发布新 Tag 时,latest 会自动更新为该版本。
核心思路
- 当工作流由 Tag 触发 时(如
v1.0.1),除了推送1.0.1标签的镜像,额外推送latest标签的镜像。 - 当由 分支触发 时(如
main),仅推送分支标签(不影响latest,避免开发版本覆盖正式版)。
修改工作流配置
更新 .github/workflows/docker-compose-build-push.yml,重点调整 镜像标签生成 和 推送逻辑:
name: 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
841

被折叠的 条评论
为什么被折叠?



