一 本文目标

记录如何通过 Github Action 实现 SpringBoot 我的项目的自动化公布。其中 SpringBoot 我的项目通过 Docker 进行治理。

二 Github Action 须要的次要步骤

  1. 设置 Java 环境并通过 Maven 进行我的项目构建
  2. 构建 Docker 镜像并推送到公有镜像仓库
  3. 登录近程服务器,拉取镜像并重启服务

三 设置 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 创立公有镜像仓库如下:

  1. 详见我的项目,比方抉择我的项目名叫 docker-image
  2. 在我的项目中创立 “制品仓库”,制品类型抉择 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,最根本规定如下

EventRefDocker tags
pushrefs/heads/mainmain
pushrefs/heads/releases/v1releases-v1
push tagrefs/tags/v1.2.3v1.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# pulldocker 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 }}

这里留神几点:

  1. 应用 ssh key 登录近程服务器,次要是 key 不是 password;
  2. 倡议间接通过 命令行工具 把所有 key 文件内容复制到剪贴板,而后间接复制到 Github repo 的 secrets 中(如果手动复制,记得把正文也放进去):
# mac 下操作pbcopy < you_key_file
  1. 重启服务前要把旧的 Docker container 删掉。

六 残缺 Github Actions YAML 文件

name: GHA CI# Controls when the workflow will runon:  # 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 paralleljobs:  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 }}