手把手教你实现Docker 部署 vue 项目
1.写在前面:
Docker作为轻量级虚拟化技术,拥有持续集成、版本控制、可移植性、隔离性和安全性等优势。本文使用Docker来部署一个vue的前端应用,并尽可能详尽的介绍了实现思路和具体步骤,以方便有类似需要的同学参考。
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,该容器包含了应用程序的代码、运行环境、依赖库、配置文件等必需的资源,通过容器就可以实现方便快速并且与平台解耦的自动化部署方式,无论你部署时的环境如何,容器中的应用程序都会运行在同一种环境下。(更多详情请移步docker官网查看docker)
默认已经安装了docker,@vue/cli
相关版本:
- Dockerversion18.09.2,build6247962
- vuecli--version3.3.0
- macOSMojaveVerison10.14.1
运行环境为macOS,如果与阅读者操作系统之间存在差异,请自行调整
相关镜像:
- nginx:latest
- node:latest
2.具体实现:
- 用vuecli创建一个vue项目,修改一下创建出来的项目,在页面上写一个前端接口请求,构建一版线上资源,基于nginxdocker镜像构建成一个前端工程镜像,然后基于这个前端工程镜像,启动一个容器vuenginxcontainer。
- 启动一个基于node镜像的容器nodewebserver,提供后端接口。
- 修改vuenginxcontainer的nginx配置,使前端页面的接口请求转发到nodewebserver上。
- 稍作优化和改进。
3创建vue应用
3.1vuecli创建一个vue项目
运行命令
yarnserve/npmrunserve
稍微改写一下页面,在App.vue中传入HelloWorld组件中的msg改为HelloDocker;created生命周期中加入一个接口请求
importaxiosfrom'axios'; …… axios.get('/api/json',{ params:{} }).then( res=>{ console.log(res); } ).catch( error=>{ console.log(error); } ) ……
这时候会在页面控制台看到一个报错信息:
/api/json接口404,当然此时这个接口还不存在,暂时写到这里,一会再调这个接口。
3.3构建vue项目
运行命令
yarnbuild/npmrunbuild
文件夹
如果将该dist目录整个传到服务器上,部署成静态资源站点就能直接访问到该项目。
接下来就来构建一个这样的静态资源站点。
4构建vue应用镜像
nginx是一个高性能的HTTP和反向代理服务器,此处我们选用nginx镜像作为基础来构建我们的vue应用镜像。
4.1获取nginx镜像
dockerpullnginx
- docker镜像(Image)一个特殊的文件系统。Docker镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。
- docker镜像相关操作有:搜索镜像dockersearch[REPOSITORY[:TAG]]、拉取镜像dockerpull[REPOSITORY[:TAG]]、查看镜像列表dockerimagels、删除镜像:dockerimagerm[REPOSITORY[:TAG]]/dockerrmi[REPOSITORY[:TAG]]等等。
- docker镜像名称由REPOSITORY和TAG组成[REPOSITORY[:TAG]],TAG默认为latest
4.2创建nginxconfig配置文件
在项目根目录下创建nginx文件夹,该文件夹下新建文件default.conf
server{ listen80; server_namelocalhost; #charsetkoi8-r; access_log/var/log/nginx/host.access.logmain; error_log/var/log/nginx/error.logerror; location/{ root/usr/share/nginx/html; indexindex.htmlindex.htm; } #error_page404/404.html; #redirectservererrorpagestothestaticpage/50x.html # error_page500502503504/50x.html; location=/50x.html{ root/usr/share/nginx/html; } }
该配置文件定义了首页的指向为/usr/share/nginx/html/index.html,所以我们可以一会把构建出来的index.html文件和相关的静态资源放到/usr/share/nginx/html目录下。
4.3创建Dockerfile文件
FROMnginx COPYdist//usr/share/nginx/html/ COPYnginx/default.conf/etc/nginx/conf.d/default.conf
- 自定义构建镜像的时候基于Dockerfile来构建。
- FROMnginx命令的意思该镜像是基于nginx:latest镜像而构建的。
- COPYdist//usr/share/nginx/html/命令的意思是将项目根目录下dist文件夹下的所有文件复制到镜像中/usr/share/nginx/html/目录下。
- COPYnginx/default.conf/etc/nginx/conf.d/default.conf命令的意思是将nginx目录下的default.conf复制到etc/nginx/conf.d/default.conf,用本地的default.conf配置来替换nginx镜像里的默认配置。
4.4基于该Dockerfile构建vue应用镜像
运行命令(注意不要少了最后的“.”)
dockerbuild-tvuenginxcontainer.
-t是给镜像命名.是基于当前目录的Dockerfile来构建镜像
查看本地镜像,运行命令
dockerimagels|grepvuenginxcontainer
容器。
4.5启动vueapp容器
Docker容器Container:镜像运行时的实体。镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
基于vuenginxcontainer镜像启动容器,运行命令:
dockerrun\ -p3000:80\ -d--namevueApp\ vuenginxcontainer
dockerrun基于镜像启动一个容器
-p3000:80端口映射,将宿主的3000端口映射到容器的80端口
-d后台方式运行
--name容器名查看docker进程
dockerps
可以发现名为vueApp的容器已经运行起来。此时访问http://localhost:3000
应该就能访问到该vue应用:
5接口服务
再部署一个node的容器来提供接口服务
5.1express服务
用nodeweb框架express来写一个服务,注册一个返回json数据格式的路由server.js:
'usestrict'; constexpress=require('express'); constPORT=8080; constHOST='0.0.0.0'; constapp=express(); app.get('/',(req,res)=>{ res.send('Helloworld\n'); }); app.get('/json',(req,res)=>{ res.json({ code:0, data:'Thisismessagefromnodecontainer' }) }); app.listen(PORT,HOST); console.log(`Runningonhttp://${HOST}:${PORT}`);
运行该express应用需要node环境,我们基于node镜像来构建一个新镜像
5.2获取node镜像
dockerpullnode
5.3编写Dockerfile将express应用docker化
FROMnode WORKDIR/usr/src/app COPYpackage*.json./ RUNnpminstall COPY.. EXPOSE8080 CMD["npm","start"]
构建镜像的时候node_modules的依赖直接通过RUNnpminstall来安装,项目中创建一个.dockerignore文件来忽略一些直接跳过的文件:
node_modules npm-debug.log
5.4构建nodewebserver镜像
运行构建命令:
dockerbuild-tnodewebserver.
基于刚刚构建的nodewebserver镜像启动一个名为nodeserver的容器来提供接口服务8080端口,并映射宿主的5000端口
dockerrun\ -p5000:8080\ -d--namenodeserver\ nodewebserver
查看当前docker进程
dockerps
可以发现nodeserver的容器也正常的运行起来。访问以下http://localhost:5000/json
能访问到前面写的json数据
到目前为止,后端接口服务也正常启动了。只需最后把页面请求的接口转发到后端接口服务就能调通接口。
6.跨域转发
想要将vueApp容器上的请求转发到nodeserver容器上。首先需要知道nodeserver容器的ip地址和端口,目前已知nodeserver容器内部服务监听在8080端口,还需要知道ip即可。
6.1查看nodeserver容器的ip地址:
查看容器内部ip有多种方式,这里提供两种:
进入容器内部查看
dockerexect-it02277acc3efcbash
cat/etc/hosts
dockerinspect[containerId]直接查看容器信息:
dockerinspect02277acc3efc
在其中找到Networks相关配置信息:
记录下node服务容器对应的ip,一会儿配置nginx转发的时候会用到。
6.2修改nginx配置
Nginx配置location指向node服务default.conf(前端想要了解的Nginx,关于Nginx的配置已经location的具体写法可以参考(一文弄懂Nginx的location匹配))
添加一条重写规则,将/api/{path}转到目标服务的/{path}接口上。在前面的nginx/default.conf文件中加入:
location/api/{ rewrite/api/(.*)/$1break; proxy_passhttp://172.17.0.2:8080; }
修改完了之后意识到一个问题:vueApp容器是基于vuenginxcontainer这个镜像运行的,而在一开始构建镜像的时候是将nginx配置default.conf直接构建进去了。因此如果需要修改default.conf还得再重新构建一个新的镜像,再基于新镜像来运行新的容器。
7.改进
能不能每次修改配置文件后直接重启容器就能让新配置生效,答案当然是有。
在构建镜像的时候不把Nginx配置复制到镜像中,而是直接挂载到宿主机上,每次修改配置后,直接重启容器即可。
7.1修改Dockerfile文件
把vueclidemo项目下的Dockerfile修改一下
FROMnginx COPYdist//usr/share/nginx/html/ COPYnginx/default.conf/etc/nginx/conf.d/default.conf
将COPYnginx/default.conf/etc/nginx/conf.d/default.conf命令删除,nginx配置都通过挂载命令挂载在宿主机上。再看COPYdist//usr/share/nginx/html/命令,如果每次构建的项目dist/下的内容变动都需要重新走一遍构建新镜像再启动新容器的操作,因此这条命令也可以删除,使用挂载的方式来启动容器。
7.2重新运行vue应用容器
直接基于nginx镜像来启动容器vuenginxnew,运行命令:
dockerrun\ -p3000:80\ -d--namevuenginxnew\ --mounttype=bind,source=$HOME/SelfWork/docker/vueclidemo/nginx,target=/etc/nginx/conf.d\ --mounttype=bind,source=$HOME/SelfWork/docker/vueclidemo/dist,target=/usr/share/nginx/html\ nginx
- --mounttype=bind,source={sourceDir},target={targetDir}将宿主机的sourceDir挂载到容器的targetDir目录上。
- 此处运行的命令较长,如果每次重新输入难免麻烦,我们可以将完整的命令保存到一个shell文件vueapp.sh中,然后直接执行shvueapp.sh。
这样就能每次修改了nginx配置或者重新构建了vue应用的时候,只需重启容器就能立马生效。此时我们再访问http://localhost:3000/api/json能看到接口能正常返回,说明转发生效了。
至此接口服务的转发也调通了。
7.3配置负载均衡
后端服务一般都是双机或者多机以确保服务的稳定性。我们可以再启动一个后端服务容器,并修改nginx的配置来优化资源利用率,最大化吞吐量,减少延迟,确保容错配置。
基于前面4.5节的类似操作,新启动一个容器,并基于5.1节类似的操作,查看到新容器的IP(172.17.0.3)
修改一下nginx/default.conf(新增upstream,修改location/api/中的proxy_pass):
upstreambackend{ server172.17.0.2:8080; server172.17.0.3:8080; } …… location/api/{ rewrite/api/(.*)/$1break; proxy_passbackend; }
8.写在后面
不习惯命令行的同学可以选用Kitematic来管理docker容器的状态、数据目录和网络。所有对容量的操作都可以可视化的操作,这里就不做过多介绍了,有兴趣的同学可以自行体验下。
nginx官网
docker从入门到实践
Kitematicuserguide
前端想要了解的Nginx
一文弄懂Nginx的location匹配
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。