每次写一篇新的文章或者有一点改动,都要手动放到服务器上,特别麻烦,所以今天来搭建一个自动部署环境。每次修改之后只要 push 到 github 上就可以了。
我对 Docker 还是很喜欢的,所以这次环境也用 Docker 进行搭建。
安装 Docker
安装 Docker
# 卸载旧版本
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
# 设置存储库
sudo yum install -y yum-utils
sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
# 安装 Docker
sudo yum install docker-ce docker-ce-cli containerd.io
# 启动docker
sudo systemctl start docker
# 运行此命令以下载 Docker Compose 的当前稳定版本
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# 对二进制文件应用可执行权限
sudo chmod +x /usr/local/bin/docker-compose
搭建环境
环境的源码可以到我的 GitHub查看
首先确认一下我们的环境需要什么东西:
Git
首先需要 Git 从 github 上拉取源码hugo
然后使用 hugo 来将源码生成静态文件webhook
使用 github 的 webhook 来完成自动部署Nginx
使用 Nginx 完成域名解析与 webhook 工具的反向代理
webhook 我工具选择使用adnanh/webhook,这款工具和 hugo 一样是使用 Go 语言开发的,所以只需要下载可执行文件就可以使用了,非常方便。
构建镜像
我们使用 Git 镜像bitnami/git
来作为基础镜像,然后下载hugo与webhook的可执行文件。
Dockerfile
FROM bitnami/git
# 将hugo与webhook可执行文件复制到镜像中
COPY hugo /usr/local/bin
COPY webhook /usr/local/bin
# 添加执行权限
RUN chmod +x -R /usr/local/bin
webhook
准备 webhook 的配置文件,查看 webhook 配置文件的模板,以及配置文件中字段的含义。
webhook 启动之后默认监听:9000/hooks/{id}
路径下的请求,id 为 hooks.json 中配置的 id。
hooks.json
[
{
"id": "blog",
"execute-command": "/sh/blog-webhook.sh", //这里试了几次好像不能直接执行命令,只能写成shell脚本
"trigger-rule": {
"and": [
{
"match": {
"type": "payload-hmac-sha1",
"secret": "你在github设置的secret",
"parameter": {
"source": "header",
"name": "X-Hub-Signature"
}
}
},
{
"match": {
"type": "value",
"value": "refs/heads/master",
"parameter": {
"source": "payload",
"name": "ref"
}
}
}
]
}
}
]
blog-webhook.sh
#!/bin/sh
cd "/home/blog"
git pull
hugo
GitHub
Nginx
上面说了 webhook 监听 9000 端口,所以配置一个域名转发到 9000 端口。
webhook.conf
server {
listen 80;
listen [::]:80;
server_name webhook.chance.fyi;
#把http的域名请求转成https
return 301 https://$host$request_uri;
}
server {
#SSL 访问端口号为 443
listen 443 ssl;
server_name webhook.chance.fyi;
location / {
proxy_pass http://blog:9000;
proxy_set_header Host $proxy_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
可能看到这个
proxy_pass http://blog:9000;
会不太理解,为什么不是
proxy_pass http://127.0.0.1:9000;
呢。因为我们下面会使用 docker-compose 来编排服务,一个是
nginx
服务一个是blog
服务,两者之间是通过服务名访问。
docker-compse 编排
docker-compose.yml
version: "3.7"
services:
blog:
image: blog
build: ./git
working_dir: /home
tty: true
ports:
- 9000:9000
volumes:
- ./www:/home
- ./webhook:/webhook
- ./sh:/sh
command:
- /bin/bash
- -c
- |
rm -rf /home/blog
cd /home
git clone git://github.com/Chance-fyi/blog.git
cd /home/blog
hugo
chmod +x -R /sh
webhook -hooks /webhook/hooks.json -hotreload
nginx:
image: nginx
working_dir: /home
tty: true
ports:
- 80:80
- 443:443
volumes:
- ./www:/home
- ./sh:/sh
- ./nginx/conf:/etc/nginx/conf.d
- ./nginx/cert:/etc/nginx/cert
问题
Nginx 服务退出
当我执行docker-compose up -d
之后 nginx 服务立即退出了,原因是webhook
还没有启动成功,而webhook.conf
配置中又依赖于 webhook,监听到 9000 端口还没启动就报错退出了。
解决办法
使用一个wait-for-it的 shell 脚本来监听 webhook 是否启动成功,然后在启动 Nginx。
修改后的 docker-compose.yml 文件为:
version: "3.7"
services:
blog:
image: blog
build: ./git
working_dir: /home
tty: true
ports:
- 9000:9000
volumes:
- ./www:/home
- ./webhook:/webhook
- ./sh:/sh
command:
- /bin/bash
- -c
- |
rm -rf /home/blog
cd /home
git clone git://github.com/Chance-fyi/blog.git
cd /home/blog
hugo
chmod +x -R /sh
webhook -hooks /webhook/hooks.json -hotreload
nginx:
image: nginx
working_dir: /home
tty: true
ports:
- 80:80
- 443:443
volumes:
- ./www:/home
- ./sh:/sh
- ./nginx/conf:/etc/nginx/conf.d
- ./nginx/cert:/etc/nginx/cert
command:
- /bin/bash
- -c
- |
chmod +x -R /sh
/sh/wait-for-it.sh blog:9000 -- nginx -g 'daemon off;'
再次docker-compose up -d
之后 Nginx 服务就不会退出啦。
blog-webhook.sh 执行失败
当我 push 到 github 上的时候,webhook 请求是成功了的,但是修改并没有被更新。
经过排查发现如下报错:
error occurred: fork/exec /sh/blog-webhook.sh: no such file or directory
排查发现文件是存在的,然后进入容器执行这个脚本:
root@cc8ce34686cd:/home# /sh/blog-webhook.sh
bash: /sh/blog-webhook.sh: /bin/bash^M: bad interpreter: No such file or directory
经过搜索得知是因为在 Windows 下编辑的 sh 脚本是 dos 格式的,而 Linux 环境下需要文件是 unix 格式才行。
解决办法
参考这篇文章使用 vscode 修改了文件格式,再上传就没有问题了。