需求背景
有个开源项目, 想发版到自己的服务器上的docker中, 自己服务器没那么多资源部署一套CI, 因此拟使用GitHub来处理. 感谢GitHub
其实主要难点在于如何让docker通过ssh连上自己的服务器, 这里写一下主要思路
本文主要内容: 将GitHub上的vite项目部署到自己买的云服务器, 其中云服务器环境为CentOS 7+Docker
主要思路
- 在自己电脑上生成公钥和私钥
- 将公钥上传到自己的服务器, 私钥放在GitHub Action, 用来登录
- 配置ssh支持root登录(因为我演示用的root账户, 否则可以不用配置)
- 将本机的known_hosts放到GitHub Action中, 避免每次手动信任
- 利用GitHub Action打包
- docker创建并使用远程context
- docker使用远程context执行构建
- docker使用远程context清理原有镜像, 并启动新的镜像
准备
为了避免终端不统一, 事先声明我使用得终端为: git bash, 管理员权限
Windows cmd可能有些命令不支持
示例服务器IP地址为:
12.34.56.78
, 账号为root
, 密码为A.bc1.23
-
生成SSH私钥和公钥, 并将公钥上传到自己的服务器
其中ly-chn是自己的备注, 最好写上, 不然会用你电脑的设备名称
然后会让你输入三个参数, 如果不了解, 最好什么都不填, 然后敲三下回车
如果你以前已经生成过而且正在用, 请填写第一个参数, 即密钥保存路径
密钥生成后会在指定目录下生成两个文件, 其中一个带
.pub
后缀, 为公钥, 不带则是私钥公钥可以泄露, 私钥不可以
$ ssh-keygen -C "ly-chn"
-
推送公钥到自己的服务器, 这里需要输入一下服务器的密码, 注意这里的用户名和你后面的用户名保持一致
$ ssh-copy-id -i ~/.ssh/id_rsa.pub root@12.34.56.78
-
测试
这里选择在自己远程服务器上执行docker system df 来查看一下docker磁盘占用
$ ssh root@12.34.56.78 "docker system df"
在GitHub项目中配置一些密钥
名词介绍:
github action secrets: 这里指github程序运行时的一些密钥, 官方翻译为
机密
, 虽然后写生硬, 但为了不引起歧义, 后文中也统一使用机密
一词
-
创建仓库机密的方式
-
创建环境机密的方式
先创建环境, 再创建机密, 后续演示使用环境机密
环境名称一般是
dev
/prod
等, 我用的是deploy to my tencent
-
要创建的几个机密:
示例中ssh端口为默认22, 如你端口不同, 可新加一个端口的机密
-
SSH_HOST
即服务器的IP地址
示例: 12.34.56.78
-
SSH_USERNAME
即服务器的ssh用户名
示例: root
-
SSH_PRIVATE_KEY
ssh私钥, 准备阶段第一步生成的私钥, 查看方式, 将此文件内容完整的复制即可
-
SSH_KNOWN_HOST
自己的服务器的公钥, 查看方式(需要你本机通过ssh连接过服务器才行, 建议使用命令行连接)
将此文件中以自己服务器IP开头的两行复制进去即可
-
创建工作流
在自己项目根目录下新建文件: 根目录/.github/workflow/deploy.yml
其中deploy.yml是可以自己命名的, 命名可随意
下面示例中, 我docker镜像名称为ly-admin-pc, 未指定版本, 你可以自有修改
内容
# 名字随意
name: deploy to my tencent
# 触发机制, 可以定时, 或其他, 具体可自行百度, 示例为main分支push时触发
on:
push:
branches:
- main
# 要执行的计划
jobs:
# 我们只有一个任务, 就是发版, publish可以自己写其它的名字
publish:
# 指定环境, 即创建环境机密时, 给环境的命名. 当然如果你创建的是仓库机密, 则无需下面这行
environment: deploy to tencent
# 指定在Ubuntu机器上运行此工作流
runs-on: ubuntu-latest
env:
# 私钥
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
# 用户名
SSH_USERNAME: ${{ secrets.SSH_USERNAME }}
# 主机地址
SSH_HOST: ${{ secrets.SSH_HOST }}
# 指纹
SSH_KNOWN_HOSTS: ${{ secrets.SSH_KNOWN_HOST }}
steps:
# 创建ssh目录, 并启动ssh代理
- name: setup ssh
shell: bash
run: |
mkdir -p $HOME/.ssh
# 保存公钥到known_hosts
- name: configure ssh public key
shell: bash
run: echo "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts
# 保存私钥到ssh-agent
- name: setup ssh private key
shell: bash
run: |
# 启动ssh-agent
eval $(ssh-agent)
# 将进程信息保存到环境变量, 方便后面的程序使用, 如docker
echo "SSH_AUTH_SOCK=$SSH_AUTH_SOCK" >> $GITHUB_ENV
echo "SSH_AGENT_PID=SSH_AGENT_PID" >> $GITHUB_ENV
# 将密钥添加的ssh-agent
echo "$SSH_PRIVATE_KEY" | ssh-add -
# 创建并使用docker远程上下文
- name: create and use docker remote context
shell: bash
run: |
docker context create remote --docker "host=ssh://$SSH_USERNAME@$SSH_HOST"
docker context use remote
# 检出代码
- name: checkout
uses: actions/checkout@v3
# 安装nodejs 18和yarn
- name: setup node
uses: actions/setup-node@v3
with:
node-version: 18
cache: yarn
# 安装依赖
- name: install dependencies
run: yarn install
# 构建
- name: build
run: yarn build
# 移除历史镜像
- name: remove docker image and container
run: |
docker rm -f ly-admin-pc || true
docker rmi -f ly-admin-pc || true
# 构建docker镜像
- name: build docker image
run: docker build --no-cache -f ./build/docker/Dockerfile -t ly-admin-pc .
# 启动新的docker镜像
- name: start docker container
run: docker run -d -p 8001:80 --name ly-admin-pc ly-admin-pc
验证效果
将代码提交推送到github
然后在仓库的Actions页面即可看到工作流的执行状态
如果执行完成, 访问服务器12.34.56.78:80001
即可正常访问项目
常见问题排查
-
工作流执行过程中连不上服务器
(Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password))
可能原因: 禁止了root用户通过ssh登录
服务器上执行
vi /etc/ssh/sshd_config
修改以下几行(分别是公钥鉴权, root用户登录, 严格模式), 保存后重启ssh:
service sshd restart
PubkeyAuthentication yes PermiRootLogin yes StrictModes yes
-
访问8001端口, 502或者连接失败
服务器防火墙放行即可, 根据各厂商有所区别, 自己去云主机控制台找找, 一般叫
防火墙
/安全组
之类的名称
完
如需查看Dockerfile和nginx.conf示例, 可以在github中找到