[2/4] Dockerify:迁移静态站点

文章已合并进 e1200

迁移静态站点

接下来我们实战迁移一个由 Vuejs 写的纯静态 SPA 单页站点:

本章节还会讲到 CI 和 Nginx 反向代理的内容

我打算怎么做

在没迁移 Docker 之前,若我想更新线上网站中内容时,需要:

  1. 本地npm run build打包产出静态文件
  2. 手动通过 FTP 上传到服务器
  3. git push更新 Github 源码

稍微有点麻烦,因此我打算这样改:

  1. 执行git push
  2. 自动检测到 github 有代码更新,自动打包出一个 Docker 镜像
  3. CI 编译完成后,SSH 登录 VPS,删掉现有容器,用新镜像创建一个新容器

而这样做的好处是:

  1. 不必再手动 FTP 上传文件
  2. 当我进行修改错别字这样的简单操作时,可以免测。改完直接git push,而不必本地npm run build

Github中的CI

首先是让 Github 在我每次更新代码时打包出一个镜像

在 Github,可以有免费的 CI 资源用,它就是 Travis CI

在项目中根目录中添加.travis.yml文件,内容如下:

[code lang=text]
language: node_js
node_js:
- "12"
services:
- docker

before_install:
- npm install

script:
- npm run build
- echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
- docker build -t pea3nut/pea3nut-info:latest .
- docker push pea3nut/pea3nut-info:latest

[/code]

文件内容非常简单,就是使用npm run build编译静态产出后,打包一个镜像并且 push 到远程。有几点需要详细说一下:

  • 为了能够让镜像上传到服务器,你需要在hub.docker.com中注册一个账号,然后替换代码中的pea3nut/pea3nut-info:latest用户名/包名:latest即可
  • 使用 Github 登录 Travis CI 后,在左边点击+加号添加自己的 Github 仓库后,需要移步到 Setting 为项目添加DOCKER_USERNAMEDOCKER_PASSWORD环境变量。这样保证我们可以秘密的登录 Docker Hub 而不被其他人看到自己的密码。如下图

add-a-now-project-in-travis-ci

然后需要添加 Dockerfile 文件来描述如何打包 Docker 镜像。

按照.travis.yml的命令次序,在打包镜像时,npm run build已经执行过了,项目产出已经有了。不必在 Docker 容器中运行npm installnpm run build之类的,直接复制文件即可:

[code lang=bash]
FROM nginx

COPY ./dist/ /usr/share/nginx/html/

EXPOSE 80
[/code]

Note: 过程虽然简单但是线条很长,建议本地多测试测试再进行git push

若你编译出的静态站点也是一个 SPA 单页应用,需要增加额外的 Nginx 配置来保证请求都能打到index.html。下边是我写的vhost.nginx.conf Nginx 配置文件,将不访问文件的请求全部重定向到/index.html

[code lang=text]
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
proxy_set_header Host $host;

if (!-f $request_filename) {
rewrite ^.*$ /index.html break;
}

}

error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
[/code]

然后在 Dockerfile 中新加一行,将本机的vhost.nginx.conf文件复制到容器的/etc/nginx/conf.d/pea3nut-info.conf,让 Nginx 能够读取该配置文件:

[code lang=diff]
FROM nginx

COPY ./dist/ /usr/share/nginx/html/
+ COPY ./vhost.nginx.conf /etc/nginx/conf.d/pea3nut-info.conf

EXPOSE 80
[/code]

然后执行git push后,你可以在 Travis CI 看到 CI 的编译结果。如果编译没问题,远程实际上就有了pea3nut/pea3nut-info:latest这个镜像。本地可以试试看该镜像工作是否正常:

[code lang=bash]
docker image pull pea3nut/pea3nut-info:latest
docker container create -p 8082:80 pea3nut/pea3nut-info:latest
docker container start xxx # xxx 为上一条命令执行的返回值
[/code]

运行完成后,浏览器访问127.0.0.1:8082应该就能看到效果了!

然后你可以登录远程 VPS 服务器,安装 Docker,执行同样的命令。然后访问远程 VPS 服务器的公网 IP + 8082 端口号,应该能看到和本地相同的效果

Tips: 忘了如何在 VPS 上安装 Docker?在上文“安装 Docker”一节,你可能需要的是 Linux 的安装方式

[code lang=bash]
curl https://get.docker.com/ > install-docker.sh # 下载安装脚本
sh install-docker.sh # 执行安装脚本
[/code]

Nginx 反向代理

Note: 接下来的操作都是在你的远程 VPS 服务器上操作,并非本地电脑,或者容器中

目前我们将容器挂到了 8082 端口,但是线上不可能让用户手动输入 8082 端口进行访问。而如果将容器直接挂到 80 端口,虽然这样用户可以直接不加端口直接访问,但是如果有第二个容器,或者更多容器呢?

这时候就需要在宿主机跑一个 Nginx,由它来独占 80 端口,然后根据域名来讲请求分发给响应的容器。如下图:

nginx_anti-proxy

这种方案叫做“反向代理”

登录VPS服务器,安装 Nginx。因为我是 Ubuntu,所以可以用apt安装。其他 Linux 发行版可以百度下安装方法,通常2行内可以搞定:

[code lang=bash]
apt update # 更新软件包
apt-get install nginx # 安装 Nginx
systemctl status nginx # 查看 Nginx 状态
[/code]

此时本地通过浏览器访问 VPS 的公网 IP 可用看到 Nginx 的欢迎页面

nginx_welcome

然后在 VPS 服务器的/etc/nginx/conf.d/中建立一个vhost.conf文件,配置如下内容:

[code lang=text]
server {
listen 80;
server_name pea3nut.info;

location / {
proxy_pass http://127.0.0.1:8082;
}
}
[/code]

配置的意思是,监听来自 80 端口的流量,若访问域名是pea3nut.info(替换为你自己的域名),则全部转发到http://127.0.0.1:8082

配置完成后,重启 Nginx 服务器。若是 Ubuntu 可以使用systemctl restart nginx命令,不同 Linux 发行版稍有不同

配置成功后,访问pea3nut.info会看到和VPS公网IP:8082相同的效果

更新站点

而迁移完成 Docker 后,我想改一个错别字的流程变为:

  • 本地修改完成,执行git push
  • 等待 CI 编译完成
  • 登录 VPS 服务器,执行:

[code lang=bash]
docker image pull pea3nut/pea3nut-info:latest
docker container create -p 8082:80 pea3nut/pea3nut-info:latest # 得到 yyy
docker container stop xxx # xxx 为当前运行的容器ID,可用 docker container ls 查看
docker container start yyy # yyy 第二条命令返回值
[/code]

命令还是有些长?我们在下面会进一步优化它

  • 浏览:2530
  • 评论:1

发表新的回复

取消回复


Daniel 2021年6月8日 上午9:12

很实用

回复