文章已合并进 e1200
接下来我们实战迁移一个由 Vuejs 写的纯静态 SPA 单页站点:
本章节还会讲到 CI 和 Nginx 反向代理的内容
在没迁移 Docker 之前,若我想更新线上网站中内容时,需要:
npm run build
打包产出静态文件git push
更新 Github 源码稍微有点麻烦,因此我打算这样改:
git push
而这样做的好处是:
git push
,而不必本地npm run build
首先是让 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
即可DOCKER_USERNAME
和DOCKER_PASSWORD
环境变量。这样保证我们可以秘密的登录 Docker Hub 而不被其他人看到自己的密码。如下图然后需要添加 Dockerfile 文件来描述如何打包 Docker 镜像。
按照.travis.yml
的命令次序,在打包镜像时,npm run build
已经执行过了,项目产出已经有了。不必在 Docker 容器中运行npm install
和npm 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]
Note: 接下来的操作都是在你的远程 VPS 服务器上操作,并非本地电脑,或者容器中
目前我们将容器挂到了 8082 端口,但是线上不可能让用户手动输入 8082 端口进行访问。而如果将容器直接挂到 80 端口,虽然这样用户可以直接不加端口直接访问,但是如果有第二个容器,或者更多容器呢?
这时候就需要在宿主机跑一个 Nginx,由它来独占 80 端口,然后根据域名来讲请求分发给响应的容器。如下图:
这种方案叫做“反向代理”
登录VPS服务器,安装 Nginx。因为我是 Ubuntu,所以可以用apt
安装。其他 Linux 发行版可以百度下安装方法,通常2行内可以搞定:
[code lang=bash]
apt update # 更新软件包
apt-get install nginx # 安装 Nginx
systemctl status nginx # 查看 Nginx 状态
[/code]
此时本地通过浏览器访问 VPS 的公网 IP 可用看到 Nginx 的欢迎页面
然后在 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
[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]
命令还是有些长?我们在下面会进一步优化它
Daniel 2021年6月8日 上午9:12
很实用