深耕系列之docker部署vue项目

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

vue项目完成后,如何部署到正式环境呢?

一、需求分析

我司前端项目的部署原是生成静态文件由运维传到cdn上的,为了提高效率,也避免编译文件纳入代码库,就由开发人员自己部署。因此,我分析需求并整理如下:

  1. 可以部署多个vue项目。
  2. 不依赖于机器有安装node和npm等环境。
  3. 更新项目时,用户是无感知的。

二、确定方案

决定采用docker部署,不依赖node,npm等环境。

三、使用步骤

1.gif

1. 创建deploy目录并拉取web_docker代码

配.png

vue项目要放在/deploy目录下,如果想放到其他目录,需改动相关配置文件。

2. 执行sh init.sh 命令

2.png

该init.sh脚本的作用:

  1. 下载所有配置好的vue项目
  2. 自动安装依赖并生成编译文件
  3. 根据docker-compose.yml启动nginx容器

init.sh文件

#!/bin/bash

# $1 :: project
# $2 :: branch

sh ./update.sh $1 $2
docker-compose -f docker-compose.yml up -d
复制代码

Tips: 可传入两个参数,分别是project和branch,branch默认为master分支,用于指定安装某个项目,比如 sh init.sh vue-admin-template master。如不传参数,则安装所有vue项目

update.sh文件

#!/bin/bash

project="all"
branch="master"

if [ "$1" != '' ]; then
    project=$1
fi
if [ "$2" != '' ]; then
    branch=$2
fi

if [ "$project" == 'vue-admin-template' ] || [ "$project" == 'all' ]; then
    echo '-------start update vue-admin-template-------'
    cd ../
    if [ ! -d './vue-admin-template' ]; then
        git clone -b $branch https://github.com/PanJiaChen/vue-admin-template.git
    fi
    cp web_docker/build/docker-build.sh vue-admin-template/docker-build.sh
    cp web_docker/build/build.sh vue-admin-template/build.sh
    cd vue-admin-template
    sh ./docker-build.sh
    echo '-------end update vue-admin-template-------'
fi
复制代码

这里是下载vue-admin-template项目,如果想部署多个项目,就新增配置到update.sh。

脚本中的 docker-build.sh 和 build.sh 是用来做什么呢?

docker-build.sh文件

#!/bin/bash
echo '---start build---'
docker run --rm -v $(pwd):/work node:14.2.0-slim bash -c "cd /work && sh build.sh"
echo '---end build---'
复制代码

该脚本使用docker run命令来启动一个临时容器,使用node:14.2.0-slim镜像,会把项目的文件映射到容器的/work目录,然后在容器内执行sh build.sh

这也是docker的强大之处,容器内已经有node环境和npm环境,在容器内可以安装项目依赖和生成编译文件,也就不依赖于宿主机去安装node环境。那么build.sh脚本做了什么呢?

build.sh文件

#!/bin/bash

npm install -P && npm run build:prod
if [ -d './dist_docker' ]; then
    mv ./dist_docker ./dist_docker_copy
fi
mv ./dist ./dist_docker
if [ -d './dist_docker_copy' ]; then
    rm -rf ./dist_docker_copy
fi
复制代码

该脚本用于安装项目依赖并生成编译文件,一般vue项目的编译文件是默认放到dist目录下的,为了在项目编译过程中不影响用户的使用,所以额外使用dist_docker文件夹。用户看到的页面是dist_docker里的静态文件。

编译需要耗费较长时间,而更改文件夹名称耗时非常短,通过dist和dist_docker文件夹的来回切换来保证项目更新时,用户是无感知的。

docker-compose.yml文件

version: "3"
services:
  nginx:
    image: nginx
    build: ./nginx
    container_name: nginx_docker
    volumes:
      - /deploy:/deploy
      - /deploy/web_docker/nginx/conf.d:/etc/nginx/conf.d
    restart: always
  #   ports:
  #     - "80:80"
  # web:
  #   image: web
  #   build: ./web
  #   container_name: web_server_docker
  #   restart: always
  #   volumes:
  #     - /deploy/web_docker/web/node_server:/node_server
  #   ports:
  #     - "20000:20000"
复制代码

根据docker-compose.yml来启动nginx容器,/deploy/web_docker/nginx/conf.d会映射到容器的/etc/nginx/conf.d。nginx容器作为web服务器,可监听端口并部署vue项目。

可以看出,这里还有一个web容器被注释掉,因为不一定会被使用,所以注释了,是用来自动更新项目的。如果你希望你push代码到代码仓库后,可以自动更新正式环境的项目,就可以启动该容器,同时代码仓库中配置web钩子。具体实现细节,可以看该容器的相关配置,这里就不赘述了。

那么/deploy/web_docker/nginx/conf.d 目录下有哪些配置呢?

vue-admin-template.conf文件

server{
    listen 20001;
    server_name vue-admin-template;
    root /deploy/vue-admin-template/dist_docker/;
    gzip on;
    gzip_static on;
    gzip_disable "msie6";
    gzip_min_length 10240;
    gzip_buffers 4 16k;
    gzip_comp_level 3;
    gzip_types text/plain application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/peg image/gif image/png;
    gzip_vary off;

    location ~ .*\.(gif|jpg|jpeg|png|css|js|ico|eot|otf|fon|font|ttf|ttc|woff|woff2)(.*) {
        add_header Cache-Control "public, max-age=2592000";
    }

    location ~* .*\.(?!gif|jpg|jpeg|png|css|js|ico|eot|otf|fon|font|ttf|ttc|woff|woff2$){
        add_header Cache-Control 'no-cache, must-revalidate, proxy-revalidate, max-age=0';
    }

    location / {
        try_files $uri $uri/ /index.html;
        error_page 404 /index.html;
    }
}
复制代码

这定义了vue-admin-template项目在nginx容器的端口为20001,nginx配置了gzip,缓存头等内容。

domain.conf文件

server {
    listen  80;
    server_name domain.com;
    access_log  /var/log/nginx/domain.com.log;

    location / {
        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-NginX-Proxy true;
        proxy_pass http://172.24.0.2:20001/;
    }
}
复制代码

这是用来做nginx转发使用的,如果宿主机没有安装nginx监听到80端口,那么可以在docker-compose.yml文件内把80端口映射出来,在容器内做nginx转发。

3. 查询docker容器启动情况

image.png

可以看出,nginx_docker容器正常启动,容器id为 eb70ff5855e8。如果容器启动失败,那么在STATUS那栏,会不断尝试重启,这时候我们可以通过docker logs eb70ff5855e8 来查看容器启动日志,找到失败原因并解决。

4. 查询分配给docker容器的ip

因为docker-compose.yml文件中并没有配置port端口,所以容器的端口和宿主机的端口并没有一一映射。我们知道,vue-admin-template在容器内的监听端口是20001,假如宿主机的ip是 192.168.x.x, 我们是无法访问 http://192.168.x.x:20001 的,浏览器会报无法访问此网站。这时,我们可通过docker inspect eb70ff5855e8 去查看宿主机分配给容器的ip。

image.png

可以看到,分配给容器eb70ff5855e8的ip是172.24.0.2,那么我们尝试在宿主机内访问 http://172.24.0.2:20001

image.png

访问成功。那么浏览器如何访问该vue项目呢。我们默认宿主机是有安装nginx的,这时就需要在宿主机的nginx配置转发。如果宿主机没有安装nginx且没有监听80端口,我们可以放开80端口映射,在容器内配置转发。

image.png

5. 宿主机的nginx配置转发

增加domain.conf文件,内容如下:

server {
    listen  80;
    server_name domain.com;
    access_log  /var/log/nginx/domain.com.log;

    location / {
        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-NginX-Proxy true;
        proxy_pass http://172.24.0.2:20001/;
    }
}
复制代码

然后宿主机执行nginx -s reload 重新加载配置。

image.png

6. 用户配置host,domain.com指向宿主机ip,浏览器访问 domain.com

image.png

完美运行。

四、FAQ

问题:如果想添加新项目,该如何做?

  1. 添加新项目到update.sh脚本。
  2. 新增nginx/conf.d 目录下的配置,给该项目添加配置。
  3. 宿主机nginx增加配置来处理转发。
  4. 执行sh init.sh 新项目。

问题:项目代码有更新,该如何做?

进入到该项目所在目录下,执行git pull && sh docker-build.sh。

问题:项目监听端口有变化,该如何做?

  1. 修改nginx/conf.d 目录下的配置。
  2. 进入nginx容器内reload,或者重启nginx容器。

五、总结

该docker部署方案已应用到我司的项目中,后续会不断完善,更多代码细节请查看 web_docker。 如果觉得对你有帮助,不要吝啬点个赞哈。如果有更好的优化建议,欢迎在评论区讨论,也欢迎大家fork该项目并提交pull request。

猜你喜欢

转载自juejin.im/post/7018747900096151589