0%

自动机项目docker化部署

背景

之前一直有一个细胞自动机链接的项目部署在搬瓦工的服务器上。是原始的ubuntu一步一命令部署,早就已经没法维护。加上搬瓦工的服务器一年需要19.9刀,虽然不贵但是毕竟有免费的Oracle服务器了,就打算把细胞自动机迁移到Oracle的服务器上,顺便docker化掉。

要做什么呢

  • 新建一个dockerfile文件为正式Node项目的启动服务
  • 通过docker-compose.yml组织切分三个启动段:临时Nginx启动服务,证书申请服务,正式Node项目的启动服务。同时准备好两份Nginx文件
  • 在Server端拉取Git源码,通过docker-compose启动细胞自动机的部署

部署代码和流程

源码

部署代码

docker-compose.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
version: '3'

services:
# 阶段1:临时Web服务(仅用于证书申请)
temp-web:
image: nginx:alpine
ports:
- "80:80"
volumes:
- web-root:/var/www/html
- ./nginx-init.conf:/etc/nginx/nginx.conf
- nginx-cache:/var/cache/nginx
networks:
- app-network
user: "root"
entrypoint: sh -c "mkdir -p /var/cache/nginx && chown -R nginx:nginx /var/cache/nginx && nginx -g 'daemon off;'"
restart: unless-stopped

# 阶段2:证书申请服务
certbot:
image: certbot/certbot
volumes:
- certbot-etc:/etc/letsencrypt
- web-root:/var/www/html
command: certonly --webroot --webroot-path=/var/www/html --email ${your_mail} --non-interactive --agree-tos --no-eff-email -d ${your_domain} --staging
networks:
- app-network

# 阶段3:正式Web服务
web:
build: .
ports:
- "80:80"
- "443:443"
volumes:
- certbot-etc:/etc/letsencrypt
- web-root:/var/www/html
- ./nginx.conf:/etc/nginx/nginx.conf
networks:
- app-network
restart: unless-stopped

volumes:
web-root:
certbot-etc:
certbot-var:
nginx-cache:

networks:
app-network:

dockerfile

这个文件是第三阶段的正式Web服务启动的docker

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Dockerfile 优化版
FROM node:14-alpine

# 安装依赖
RUN apk add --no-cache nginx certbot && \
mkdir -p /var/www/html && \
getent group www-data || addgroup -S www-data && \
getent passwd www-data || adduser -S -G www-data -D www-data && \
chown -R www-data:www-data /var/www/html

WORKDIR /app

COPY package*.json ./
RUN npm install && npm install pm2 -g

COPY . .

# 暴露端口
EXPOSE 80 443

# 启动命令
CMD ["sh", "-c", "pm2 start bin/www && nginx -g 'daemon off;'"]

nginx-init.conf

这个是临时的申请证书用的nginx文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
worker_processes auto;

events {
worker_connections 1024;
}

http {
server {
listen 80;
server_name ${your_domain};

location /.well-known/acme-challenge/ {
root /var/www/html;
}

location / {
return 403;
}
}
}

nginx.conf

这个是正式的nginx文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# nginx.conf (更新版)
user www-data;
worker_processes auto;

events {
worker_connections 1024;
}

http {
server {
listen 80;
server_name ${your_domain};

location /.well-known/acme-challenge/ {
root /var/www/html;
}

location / {
return 301 https://$host$request_uri;
}
}

server {
listen 443 ssl;
server_name ${your_domain};

ssl_certificate /etc/letsencrypt/live/${your_domain}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${your_domain}/privkey.pem;

location / {
proxy_pass http://127.0.0.1:3000; # 这个需要改成本地启动的node服务端口
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering off;
}
}
}

部署流程

启动临时服务

启动临时服务,这个服务是为了给certbot提供域名的path校验,/.well-known/acme-challenge/。这个服务会占用80端口。

1
docker-compose up -d temp-web

certbot证书校验和申请流程

先dry_run一下申请证书的命令,看看证书校验逻辑是否有问题。因为certbot命令加上了--staging命令,所以运行下面的命令并不会实际申请证书,也为了避免测试的时候出发certbot的下发证书限制(7天内只能申请5次证书)链接

1
docker-compose up -d certbot

这里直接启动certbot是因为dry_run执行后查看一下日志是否有问题docker logs ${certbot_container_id}。如果运行没有任何的报错,就可以去掉--staging

停止临时的certbot并且删除临时的certbot

1
2
docker stop ${certbot_container_id}
docker rm ${certbot_container_id}

去除dry_run命令限制

1
sed -i 's/--staging//' docker-compose.yml

去掉--staging再次运行certbot启动命令,就会申请证书的证书。这里采用执行一次就退出的操作,操作会保留volume中的证书。申请好证书后就不要再操作certbot了,特别是不要运行docker-compose down -v操作,会将volume中证书一起删掉。

1
docker-compose run --rm certbot

启动正式服务

首先停止临时服务,防止临时服务一直占用着80端口导致正式服务无法启动

1
docker stop ${temp_web_container_id}

启动正式服务,启动后可以看看${web_container_id}正式服务的日志,看看是否无报错成功拉起正式服务,成功拉起会展示pm2的结果。

1
docker-compose up -d web

证书自动更新流程

部署好之后,需要使用cron创建证书自动更新的逻辑。这样就可以免去手工更新证书的步骤。见工程源代码

1
sh ./scripts/setup_crontab.sh

其他问题记录

发现访问出现(failed)net::ERR_CONTENT_LENGTH_MISMATCH 错误。无法加载js资源文件

解决方案,在nginx中加入proxy_buffering off;