本文以 SimCaptcha 项目为例。
.github/workflows/deploy-docker.yml
name: Docker Image CI/CD
on:
push:
branches: [ master ]
jobs:
# 构建并上传 Docker镜像
build:
runs-on: ubuntu-latest # 依赖的环境
steps:
- uses: actions/checkout@v2
- name: Build Image
run: |
docker build -t yiyungent/simcaptcha -f examples/EasyAspNetCoreService/Dockerfile .
docker build -t yiyungent/simcaptcha-client -f examples/AspNetCoreClient/Dockerfile .
- name: Login to Registry
run: docker login --username=${{ secrets.DOCKER_USERNAME }} --password ${{ secrets.DOCKER_PASSWORD }}
- name: Push Image
run: |
docker push yiyungent/simcaptcha
docker push yiyungent/simcaptcha-client
# Docker 自动部署
deploy-docker:
needs: [build]
name: Deploy Docker
runs-on: ubuntu-latest
steps:
- name: Deploy
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.HOST }} # 服务器ip
username: ${{ secrets.HOST_USERNAME }} # 服务器登录用户名
password: ${{ secrets.HOST_PASSWORD }} # 服务器登录密码
port: ${{ secrets.HOST_PORT }} # 服务器ssh端口
script: |
# 切换工作区
cd simcaptcha
# 下载 docker-compose.yml
wget -O docker-compose.yml https://raw.githubusercontent.com/yiyungent/SimCaptcha/master/docker-compose.yml
# 停止并删除旧 容器、网络、挂载点
#docker-compose down # TODO: docker-compose: command not found. 不知道为什么找不到 docker-compose,但直接连接服务器执行就可以
/usr/local/python3/bin/docker-compose down
# 删除旧镜像
docker rmi yiyungent/simcaptcha
docker rmi yiyungent/simcaptcha-client
# 登录镜像服务器
docker login --username=${{ secrets.DOCKER_USERNAME }} --password ${{ secrets.DOCKER_PASSWORD }}
# 创建并启动容器
#docker-compose up -d --build
/usr/local/python3/bin/docker-compose up -d --build
上面方法,每次 push 的均为
latest
,没有版本号,不便于记录
参考:
GitHub ghcr.io
Docker Hub
目标 我们想要让 拥有
tag
标记的成为一个release
正式版或者prerelease
, 这样的版本会被 push 到Docker Hub
,而没有 tag 的为开发版,但为了让少部分人能及时获取最新开发版,也 push 到Docker Hub
,如何区分? 正式版:v1.0.0
在这个v1.0.0
后又更新了些,但不足以发布新版本,但仍 push 到Docker Hub
, 于是由GitHub Actions
自动 push 到Docker Hub
标记为上次版本号-beta
,例如:v1.0.0-beta
, 意味:v1.0.0
后的最新开发版(介于v1.0.0
到 下一个正式版本之前)下面分为两种情况,有时我们的一个仓库可能需要发布不止一个包,于是如果直接使用
v1.0.0
这样的tag
会导致混乱,不知道这是哪一个包的版本,于是这里用包名-v1.0.0
, 例如PluginCore-v1.0.0
,来标记PluginCore
在v1.0.0
, 这时GitHub Actions
就需要去除PluginCore-
,再拿到v1.0.0
,用作push
到GitHub
Bug记录: 目前下方方案还有一个问题未解决: 那就是 获取上一次
release
的tag
,在一个仓库有多个包时,获取的release tag
,可能不是你所需要包的对应tag
,因此,为了防止混乱,-beta
是直接添加在获取到的上一次release tag
后,即release tag
没有做去除包名
,例如, 没有去除前面的PluginCore-
,而是直接用PluginCore-v1.0.0
UpyunAction-docker-push-beta.yml
name: Docker Image CI/CD - Beta - UpyunAction
on:
push:
branches: [ main ]
jobs:
# build and push
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Get latest release
id: last_release
uses: InsonusK/get-latest-release@v1.0.1
with:
myToken: ${{ github.token }}
exclude_types: "release, prerelease"
view_top: 1
- name: Set outputs
id: vars
run: |
# 修改为你要推送的 镜像名
echo ::set-output name=IMAGE_NAME::upyun-action
- name: Build Image
run: |
docker build -t ${{ secrets.DOCKER_USERNAME }}/${{ steps.vars.outputs.IMAGE_NAME }}:${{ steps.last_release.outputs.tag_name }}-beta -f src/UpyunAction/Dockerfile .
- name: Login to Registry - Docker Hub
run: docker login --username=${{ secrets.DOCKER_USERNAME }} --password ${{ secrets.DOCKER_PASSWORD }}
- name: Push Image - Docker
# push: last_release-beta
run: |
docker push ${{ secrets.DOCKER_USERNAME }}/${{ steps.vars.outputs.IMAGE_NAME }}:${{ steps.last_release.outputs.tag_name }}-beta
- name: Login to Registry - ghcr.io
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
- name: Push Image - ghcr.io
# push: last_release-beta
run: |
IMAGE_ID=ghcr.io/${{ github.repository_owner }}/${{ steps.vars.outputs.IMAGE_NAME }}
VERSION=${{ steps.last_release.outputs.tag_name }}-beta
echo IMAGE_ID=$IMAGE_ID
echo VERSION=$VERSION
docker tag ${{ secrets.DOCKER_USERNAME }}/${{ steps.vars.outputs.IMAGE_NAME }}:${{ steps.last_release.outputs.tag_name }}-beta $IMAGE_ID:$VERSION
docker push $IMAGE_ID:$VERSION
UpyunAction-docker-push-release.yml
name: Docker Image CI/CD - Release - UpyunAction
on:
# release:
# types: [published]
push:
tags:
- 'v*'
jobs:
# build and push
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set outputs
id: vars
run: |
#echo ::set-output name=RELEASE_VERSION::$(echo ${GITHUB_REF:10})
# 去掉前面的 refs/tags/
echo ::set-output name=RELEASE_VERSION::$(echo ${GITHUB_REF:10})
# 修改为你要推送的 镜像名
echo ::set-output name=IMAGE_NAME::upyun-action
- name: Build Image
run: |
docker build -t ${{ secrets.DOCKER_USERNAME }}/${{ steps.vars.outputs.IMAGE_NAME }}:${{ steps.vars.outputs.RELEASE_VERSION }} -f src/UpyunAction/Dockerfile .
- name: Login to Registry - Docker Hub
run: docker login --username=${{ secrets.DOCKER_USERNAME }} --password ${{ secrets.DOCKER_PASSWORD }}
- name: Push Image - Docker Hub
# push: RELEASE_VERSION, latest
run: |
docker push ${{ secrets.DOCKER_USERNAME }}/${{ steps.vars.outputs.IMAGE_NAME }}:${{ steps.vars.outputs.RELEASE_VERSION }}
docker tag ${{ secrets.DOCKER_USERNAME }}/${{ steps.vars.outputs.IMAGE_NAME }}:${{ steps.vars.outputs.RELEASE_VERSION }} ${{ secrets.DOCKER_USERNAME }}/${{ steps.vars.outputs.IMAGE_NAME }}:latest
docker push ${{ secrets.DOCKER_USERNAME }}/${{ steps.vars.outputs.IMAGE_NAME }}:latest
- name: Login to Registry - ghcr.io
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
- name: Push Image - ghcr.io
# push: RELEASE_VERSION, latest
run: |
IMAGE_ID=ghcr.io/${{ github.repository_owner }}/${{ steps.vars.outputs.IMAGE_NAME }}
VERSION=${{ steps.vars.outputs.RELEASE_VERSION }}
echo IMAGE_ID=$IMAGE_ID
echo VERSION=$VERSION
docker tag ${{ secrets.DOCKER_USERNAME }}/${{ steps.vars.outputs.IMAGE_NAME }}:latest $IMAGE_ID:$VERSION
docker push $IMAGE_ID:$VERSION
docker tag $IMAGE_ID:$VERSION $IMAGE_ID:latest
docker push $IMAGE_ID:latest
AspNetCore3_1-docker-push-beta.yml
name: Docker Image CI/CD - Beta - AspNetCore3_1
on:
push:
branches: [ main ]
jobs:
# build and push
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Get latest release
id: last_release
uses: InsonusK/get-latest-release@v1.0.1
with:
myToken: ${{ github.token }}
exclude_types: "release, prerelease"
view_top: 1
- name: Set outputs
id: vars
run: |
# 修改为你要推送的 镜像名
echo ::set-output name=IMAGE_NAME::plugincore-aspnetcore3-1
- name: Build Image
run: |
docker build -t ${{ secrets.DOCKER_USERNAME }}/${{ steps.vars.outputs.IMAGE_NAME }}:${{ steps.last_release.outputs.tag_name }}-beta -f examples/AspNetCore3_1/Dockerfile .
- name: Login to Registry - Docker Hub
run: docker login --username=${{ secrets.DOCKER_USERNAME }} --password ${{ secrets.DOCKER_PASSWORD }}
- name: Push Image - Docker
# push: last_release-beta
run: |
docker push ${{ secrets.DOCKER_USERNAME }}/${{ steps.vars.outputs.IMAGE_NAME }}:${{ steps.last_release.outputs.tag_name }}-beta
- name: Login to Registry - ghcr.io
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
- name: Push Image - ghcr.io
# push: last_release-beta
run: |
IMAGE_ID=ghcr.io/${{ github.repository_owner }}/${{ steps.vars.outputs.IMAGE_NAME }}
VERSION=${{ steps.last_release.outputs.tag_name }}-beta
echo IMAGE_ID=$IMAGE_ID
echo VERSION=$VERSION
docker tag ${{ secrets.DOCKER_USERNAME }}/${{ steps.vars.outputs.IMAGE_NAME }}:${{ steps.last_release.outputs.tag_name }}-beta $IMAGE_ID:$VERSION
docker push $IMAGE_ID:$VERSION
AspNetCore3_1-docker-push-release.yml
name: Docker Image CI/CD - Release - AspNetCore3_1
on:
# release:
# types: [published]
push:
tags:
- 'AspNetCore3_1-v*'
jobs:
# build and push
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set outputs
id: vars
run: |
#echo ::set-output name=RELEASE_VERSION::$(echo ${GITHUB_REF:10})
# 去掉前面的 refs/tags/AspNetCore3_1-
# 注意: 这里需要修改 24,
# 这个数字为 `refs/tags/AspNetCore3_1-` 这个字符串的长度, 即为 24=10+len(AspNetCore3_1-)
echo ::set-output name=RELEASE_VERSION::$(echo ${GITHUB_REF:24})
# 修改为你要推送的 镜像名
echo ::set-output name=IMAGE_NAME::plugincore-aspnetcore3-1
- name: Build Image
run: |
docker build -t ${{ secrets.DOCKER_USERNAME }}/${{ steps.vars.outputs.IMAGE_NAME }}:${{ steps.vars.outputs.RELEASE_VERSION }} -f examples/AspNetCore3_1/Dockerfile .
- name: Login to Registry - Docker Hub
run: docker login --username=${{ secrets.DOCKER_USERNAME }} --password ${{ secrets.DOCKER_PASSWORD }}
- name: Push Image - Docker Hub
# push: RELEASE_VERSION, latest
run: |
docker push ${{ secrets.DOCKER_USERNAME }}/${{ steps.vars.outputs.IMAGE_NAME }}:${{ steps.vars.outputs.RELEASE_VERSION }}
docker tag ${{ secrets.DOCKER_USERNAME }}/${{ steps.vars.outputs.IMAGE_NAME }}:${{ steps.vars.outputs.RELEASE_VERSION }} ${{ secrets.DOCKER_USERNAME }}/${{ steps.vars.outputs.IMAGE_NAME }}:latest
docker push ${{ secrets.DOCKER_USERNAME }}/${{ steps.vars.outputs.IMAGE_NAME }}:latest
- name: Login to Registry - ghcr.io
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
- name: Push Image - ghcr.io
# push: RELEASE_VERSION, latest
run: |
IMAGE_ID=ghcr.io/${{ github.repository_owner }}/${{ steps.vars.outputs.IMAGE_NAME }}
VERSION=${{ steps.vars.outputs.RELEASE_VERSION }}
echo IMAGE_ID=$IMAGE_ID
echo VERSION=$VERSION
docker tag ${{ secrets.DOCKER_USERNAME }}/${{ steps.vars.outputs.IMAGE_NAME }}:latest $IMAGE_ID:$VERSION
docker push $IMAGE_ID:$VERSION
docker tag $IMAGE_ID:$VERSION $IMAGE_ID:latest
docker push $IMAGE_ID:latest
当 docker-push-release.yml
触发运行时, docker-push-beta
并不会触发运行,(因此不用担心发布release时, 错误push两次)
因为 GitHub Actions
的触发条件互斥,
on:
push:
branches: [ main ]
上方并不意味着在所有 main
上的 push
都会触发,
因为有 同样的在有 tag: v*
时已经触发了,因此不会再触发 仅仅是 push
的条件
纠正,上诉说法有误 其实是因为
git push
与git push --tags
是两步,git push
触发一次,git push --tags
触发一次,git push --tags
仅仅是推送了tag
,而不是源代码,因此仅仅触发了GitHub Action 的 tag 触发器
, 而git push
,不会推送tag
,自然不会触发tag触发器
参考:
GitHub Container Registry 可免费用于公共镜像。 在 Beta 版期间,Container Registry 可免费用于私有镜像,并且作为 GitHub Packages 的一部分,在普遍可用时将遵循相同的定价模型。
PS: 以前是
GitHub Packages Docker Registry
,现在新的替换品是GitHub Container Registry
, 它们都属于GitHub Packages
Container registry 的域是 ghcr.io
。
注册表 | 示例 URL |
---|---|
GitHub Packages Docker Registry | docker.pkg.github.com/OWNER/REPOSITORY/IMAGE_NAME |
Container registry | ghcr.io/OWNER/IMAGE_NAME |
注意 对于
ghcr.io
而言,与Docker Hub
不同,无需提交latest
,latest
标签将始终指向最新提交的镜像, 因此,在使用GitHub Actions
自动构建时,无需push xxx:latest
, 而在Docker Hub
,latest
只是在你没有指定:tag
时默认即为latest
Docker Hub
ghcr.io
注意 测试了一下,发现好像又不一定
latest
始终指向最新,因此最好还是release
情况下,latest
和指定版本号 的docker image
都push
一次
docker-compose build
build Build or rebuild services
docker-compose build --pull
--pull Always attempt to pull a newer version of the image.
docker-compose pull
pull Pull service images
docker-compose up
up Create and start containers
其实直接一个up 就可以,如果没有build,则自动build,但是并不是每次都会build,如果已经存在镜像,则不build,如果要每次都build,则 up --build
docker-compose down
down Stop and remove containers, networks, images, and volumes
注意:虽然文档说是会删除镜像,但实际测试,使用 docker images
,依然会显示有镜像,不过,确实相关容器被停止并删除
docker-compose push
push Push service images
示例:
docker-compose -f docker-compose.Debug.yml up -d
参考:
添加用户 deploy-docker
adduser deploy-docker
补充:
在新建用户的同时添加到 docker组
adduser -g docker deploy-docker
为此用户设置密码
passwd deploy-docker
给已有用户增加组
usermod -G docker deploy-docker
或者
gpasswd -a username groupname
注意: 添加用户到某一个组 可以使用
usermod -G groupname username
这个命令可以添加一个用户到指定的组,但是以前添加的组就会清空掉。 所以想要添加一个用户到一个组,同时保留以前添加的组时,请使用gpasswd这个命令来添加操作用户
查看当前用户所在组
groups
查看指定用户所在组
groups username
查看有哪些组
cat /etc/group
查看有哪些用户
cat /etc/passwd
[deploy-docker@iZqnwheobg66nbZ simcaptcha]$ docker-compose up -d --build
Building with native build. Learn about native build in Compose here: https://docs.docker.com/go/compose-native-build/
Creating network "simcaptcha_simcaptcha-net" with driver "bridge"
ERROR: Failed to Setup IP tables: Unable to enable SKIP DNAT rule: (iptables failed: iptables --wait -t nat -I DOCKER -i br-f34f4bfebf69 -j RETURN: iptables: No chain/target/match by that name.
(exit status 1))
重启 Docker
service docker restart
感谢帮助!
本文作者: yiyun
本文链接: https://moeci.com/posts/分类-github/github-actions-docker/
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!