一 本文目标
记录如何通过 Github Action 实现 SpringBoot 我的项目的自动化公布。其中 SpringBoot 我的项目通过 Docker 进行治理。
二 Github Action 须要的次要步骤
- 设置 Java 环境并通过 Maven 进行我的项目构建
- 构建 Docker 镜像并推送到公有镜像仓库
- 登录近程服务器,拉取镜像并重启服务
三 设置 Java 环境并通过 Maven 进行我的项目构建
这里应用 JDK 11 并设置 maven 缓存放慢构建工夫。其中 -DskipTests=true
示意构建时跳过测试。如果须要测试能够删掉这个参数。
- name: Set up JDK 11
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'temurin'
cache: maven
- name: Build with Maven
run: mvn -B -DskipTests=true package --file pom.xml
四 构建 Docker 镜像并推送到公有镜像仓库
这里次要解决的问题是怎么抉择 Docker 公有镜像,抉择有下
名称 | 长处 | 毛病 |
---|---|---|
Github Package | 收费,和 Github 高度集成,配置不便 | 我国大陆云服务器连贯 Github 太 TM 慢 |
Docker 官网 | Docker 官网,值得信赖,大陆云服务器连贯速度 OK | 只反对一个公有镜像仓库,多了要钱 |
Coding.net | 大陆云服务器连贯速度快,收费,被腾讯收了,服务应该不会中断 | 配置稍微简单但能够承受 |
我最终的抉择是 Coding.net,但如果云服务器容许,我会抉择 Github Package。
4.1 Coding.net 公有镜像仓库
4.1.1 通过 Coding.net 创立公有镜像仓库如下:
- 详见我的项目,比方抉择我的项目名叫 docker-image
- 在我的项目中创立“制品仓库”,制品类型抉择 docker,而后起名,设置权限(能够默认)就 OK
创立制品 | 设置制品信息 |
---|---|
4.1.2 推送、拉取 Docker 镜像:
个别通过两种路径:命令行或者 CICD 工具。不过哪种,都须要先登录到有我的项目操作权限的账号。
登录
点击操作指引:
获取登录令牌:
docker login \
-u random-user-name \
-p random-passworkd \
coding-username-docker.pkg.coding.net
这里留神,尽管生成的是随机 username 和 password,但的确长期有效,所以能够放在 Gihub repo 的 secrets 中供 Github Action 应用。
推送 / 拉取镜像
推送:
docker push \
coding-username-docker.pkg.coding.net/docker-image/test-service/<PACKAGE>:<VERSION>
推送前确保曾经有了这个 coding-username-docker.pkg.coding.net/docker-image/test-service/<PACKAGE>:<VERSION>
这个 tag,没有的话要打标签。
docker tag \
<LOCAL_IMAGE_TAG> coding-username-docker.pkg.coding.net/docker-image/test-service/<PACKAGE>:<VERSION>
拉取:
docker pull \
coding-username-docker.pkg.coding.net/docker-image/test-service/<PACKAGE>:<VERSION>
4.1.3 在 Github Action 中设置 Coding.net 公有镜像仓库
# 登录
- name: Log in to the Coding docker registry
uses: docker/login-action@v1
with:
registry: ${{env.REGISTRY}} # REGISTRY 为 GHA 环境变量
username: ${{secrets.CODING_USER}} # coding.net 的 random-user-name,设置在 GHA 的 secrets 中
password: ${{secrets.CODING_TOKEN}} # coding.net 的 random-password
# 设置 image 名称
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v3
with:
images: ${{env.IMAGE_NAME_TOTAL_NAME}}
# 推送
- name: Build and push Docker image
uses: docker/build-push-action@v2
with:
context: .
push: true
tags: ${{steps.meta.outputs.tags}}
labels: ${{steps.meta.outputs.labels}}
Docker tags 设置规定能够参考 docker/metadata-action,最根本规定如下
Event | Ref | Docker tags |
---|---|---|
push | refs/heads/main | main |
push | refs/heads/releases/v1 | releases-v1 |
push tag | refs/tags/v1.2.3 | v1.2.3, latest |
这里留神,如果是 Push Github tag
,那么会默认生成两个 Docker tag(Perfect!)。
如果咱们想要 push tag 后触发 GHA,须要在 workflow 中增加
on:
push:
tags: # tags 更新时触发 workflow
- 'v*'
4.2 Github Package 公有镜像仓库
首先 Github Package 不肯定是 Docker 镜像,能够去官网理解更多,这里只介绍利用 Github package 配合 Github 的 Container registry 创立公有 Docker 镜像仓库。
残缺步骤能够参考 Container registry,流程和 Coding.net 相似:登录后而后推送、拉取。
4.2.1 登录 Container registry
举荐应用 GITHUB_TOKEN,在 Settings/Developer settings/Personal access tokens
中设置:
这里要记得把 Token 保留下来,不然前面就找不到了。
获取 Token 后登录到 Contianer Registry
$ export CR_PAT=YOUR_TOKEN # 存储 token 到变量 CR_PAT 中
$ echo $CR_PAT | docker login ghcr.io -u USERNAME --password-stdin
> Login Succeeded
4.2.2 Push/Pull 镜像
# push
$ docker push ghcr.io/OWNER/IMAGE_NAME:TAG
# pull
docker pull ghcr.io/OWNER/IMAGE_NAME:TAG
4.2.3 GHA 中的设置
能够间接用 github
自身变量,比方 github.actor
作为 username。和 coding.net 重复部分不再赘述。
- name: Log in to the Container registry
uses: docker/login-action@v1
with:
registry: ${{env.REGISTRY}} # 为 ghcr.io
username: ${{github.actor}} # 能够间接读取以后 Github 触发事件的用户
password: ${{secrets.GITHUB_TOKEN}}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v3
with:
images: ${{env.REGISTRY}}/${{env.IMAGE_NAME}} # IMAGE_NAME 为 ${{github.repository}}
- name: Build and push Docker image
uses: docker/build-push-action@v2
with:
context: .
push: true
tags: ${{steps.meta.outputs.tags}}
labels: ${{steps.meta.outputs.labels}}
五 登录近程服务器,拉取镜像并重启服务
这里应用了 appleboy/ssh-action,它的有点事能够间接在 GHA workflow 中配置登录近程服务器后须要执行的脚本。
- name: executing remote ssh commands using password
uses: appleboy/ssh-action@master
with:
host: ${{secrets.REMOTE_HOST}}
username: ${{secrets.REMOTE_USER}}
# 通过 ssh key 登录
key: ${{secrets.REMOTE_ACCESS_TOKEN}}
script: |
docker login -u ${{secrets.CODING_USER}} -p ${{secrets.CODING_TOKEN}} ${{env.REGISTRY}}
docker pull ${{env.IMAGE_TOTAL_NAME}}:${{env.IMAGE_TAG}}
docker stop ${{env.CONTAINER_NAME}}
docker rm ${{env.CONTAINER_NAME}}
docker run -d \
--name ${{env.CONTAINER_NAME}} \
-p ${{secrets.EXPOSED_PORT}}:${{secrets.EXPOSED_PORT}} \
--link ${{secrets.DATABASE_CONTAINER_NAME}}:${{secrets.DATABASE_CONTAINER_NAME}} \
${{env.IMAGE_TOTAL_NAME}}:${{env.IMAGE_TAG}}
这里留神几点:
- 应用 ssh key 登录近程服务器,次要是
key
不是password
; - 倡议间接通过 命令行工具 把所有 key 文件内容复制到剪贴板,而后间接复制到 Github repo 的 secrets 中(如果手动复制,记得把正文也放进去):
# mac 下操作
pbcopy < you_key_file
- 重启服务前要把旧的 Docker container 删掉。
六 残缺 Github Actions YAML 文件
name: GHA CI
# Controls when the workflow will run
on:
# Triggers the workflow on push or pull request events but only for the main branch
push:
# branches: [main]
tags: # tags 更新时触发 workflow
- 'v*'
# pull_request:
# branches: [main]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
env:
IMAGE_TOTAL_NAME: ${{secrets.CODING_REGISTRY}}/docker-image/${{secrets.SERVICE_CONTAINER_NAME}}/${{secrets.SERVICE_CONTAINER_NAME}}
IMAGE_TAG: latest
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
# maven build
- name: Set up JDK 11
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'temurin'
cache: maven
- name: Build with Maven
run: mvn -B -DskipTests=true package --file pom.xml
# coding.net docker repo
- name: Log in to the Coding docker registry
uses: docker/login-action@v1
with:
registry: ${{secrets.CODING_REGISTRY}}
username: ${{secrets.CODING_USER}}
password: ${{secrets.CODING_TOKEN}}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v3
with:
images: ${{env.IMAGE_TOTAL_NAME}}
- name: Build and push Docker image
uses: docker/build-push-action@v2
with:
context: .
push: true
tags: ${{steps.meta.outputs.tags}}
labels: ${{steps.meta.outputs.labels}}
# pull new image and restart service
- name: executing remote ssh commands using password
uses: appleboy/ssh-action@master
with:
host: ${{secrets.REMOTE_HOST}}
username: ${{secrets.REMOTE_USER}}
key: ${{secrets.REMOTE_ACCESS_TOKEN}}
script: |
docker login -u ${{secrets.CODING_USER}} -p ${{secrets.CODING_TOKEN}} ${{secrets.CODING_REGISTRY}}
docker pull ${{env.IMAGE_TOTAL_NAME}}:${{env.IMAGE_TAG}}
docker stop ${{secrets.SERVICE_CONTAINER_NAME}}
docker rm ${{secrets.SERVICE_CONTAINER_NAME}}
docker run -d \
--name ${{secrets.SERVICE_CONTAINER_NAME}} \
-p ${{secrets.EXPOSED_PORT}}:${{secrets.EXPOSED_PORT}} \
--link ${{secrets.DATABASE_CONTAINER_NAME}}:${{secrets.DATABASE_CONTAINER_NAME}} \
${{env.IMAGE_TOTAL_NAME}}:${{env.IMAGE_TAG}}