a purpose of this paper
Document how to automate the publishing of SpringBoot projects through Github Actions. The SpringBoot project is managed through Docker.
Two main steps required by Github Action
- Set up the Java environment and build the project via Maven
- Build a Docker image and push to a private registry
- Log in to the remote server, pull the image and restart the service
Three Set up the Java environment and build the project through Maven
Here we use JDK 11 and set up the maven cache to speed up the build time. Where -DskipTests=true
means skip tests when building. You can delete this parameter if you need to test.
- 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
4 Build a Docker image and push it to a private image repository
The main problem to be solved here is how to choose a Docker private image. The choices are as follows
name | advantage | shortcoming |
---|---|---|
Github Package | Free, highly integrated with Github, easy to configure | The cloud server in mainland my country is too slow to connect to Github |
Docker Official | Docker official, trustworthy, the connection speed of the mainland cloud server is OK | Only supports one private image repository, more money is required |
Coding.net | The mainland cloud server has a fast connection speed and is free of charge. It has been accepted by Tencent, and the service should not be interrupted. | Configuration is slightly complicated but acceptable |
My final choice is Coding.net, but if the cloud server allows it, I'll choose Github Package.
4.1 Coding.net private mirror repository
4.1.1 Create a private image repository through Coding.net as follows:
- See the project for details, for example, select the project named docker-image
- Create a "product warehouse" in the project, select docker for the product type, then name it, set the permissions (can be default) and it's OK
Create an artifact | Set product information |
---|---|
4.1.2 Push and pull Docker images:
There are generally two ways: the command line or the CICD tool. However, you need to log in to an account with project operation permissions first.
Log in
Click the operation guide:
Get the login token:
docker login \
-u random-user-name \
-p random-passworkd \
coding-username-docker.pkg.coding.net
Note here that although random username and password are generated, they are indeed valid for a long time, so they can be placed in the secrets of Gihub repo for Github Action to use.
push/pull image
Push:
docker push \
coding-username-docker.pkg.coding.net/docker-image/test-service/<PACKAGE>:<VERSION>
Before pushing, make sure you already have this coding-username-docker.pkg.coding.net/docker-image/test-service/<PACKAGE>:<VERSION>
this tag, if you don't have it, tag it.
docker tag \
<LOCAL_IMAGE_TAG> coding-username-docker.pkg.coding.net/docker-image/test-service/<PACKAGE>:<VERSION>
Pull:
docker pull \
coding-username-docker.pkg.coding.net/docker-image/test-service/<PACKAGE>:<VERSION>
4.1.3 Setting up Coding.net private mirror repository in Github Action
# 登录
- 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 setting rules can refer to docker/metadata-action , the most basic rules are as follows
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 |
Note here that if it is Push Github tag
, then two Docker tags (Perfect!) will be generated by default.
If we want to trigger GHA after push tag, we need to add it in workflow
on:
push:
tags: # tags 更新时触发 workflow
- 'v*'
4.2 Github Package Private Image Repository
First of all, Github Package is not necessarily a Docker image. You can go to the official website to learn more. Here we only introduce the use of Github package with Github's Container registry to create a private Docker image repository.
For the complete steps, please refer to Container registry . The process is similar to Coding.net: after login, push and pull.
4.2.1 Log in to Container registry
It is recommended to use GITHUB_TOKEN, set in Settings/Developer settings/Personal access tokens
:
Remember to save the Token here, otherwise you won't be able to find it later.
After obtaining the Token, log in to the 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 mirroring
# push
$ docker push ghcr.io/OWNER/IMAGE_NAME:TAG
# pull
docker pull ghcr.io/OWNER/IMAGE_NAME:TAG
4.2.3 Settings in GHA
You can directly use the github
own variable, such as github.actor
as the username. The overlapping parts with coding.net will not be repeated.
- 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 }}
5. Log in to the remote server, pull the image and restart the service
The appleboy/ssh-action is used here, which can directly configure the script that needs to be executed after logging in to the remote server in 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 }}
A few things to note here:
- Use ssh key to log in to the remote server, mainly
key
notpassword
; - It is recommended to copy all the key file contents to the clipboard directly through the command line tool, and then directly copy them to the secrets of the Github repo (if you copy manually, remember to put the comments as well):
# mac 下操作
pbcopy < you_key_file
- Delete the old Docker container before restarting the service.
Six complete Github Actions YAML files
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 }}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。