Docker 做为轻量级虚拟化技术,拥有持续集成、版本控制、可移植性、隔离性和安全性等优点。本文使用Docker来部署一个vue的前端应用,并尽量详尽的介绍了实现思路和具体步骤,以方便有相似须要的同窗参考。javascript
Docker 是一个开源的应用容器引擎,让开发者能够打包他们的应用以及依赖包到一个可移植的容器中,该容器包含了应用程序的代码、运行环境、依赖库、配置文件等必需的资源,经过容器就能够实现方便快速而且与平台解耦的自动化部署方式,不管你部署时的环境如何,容器中的应用程序都会运行在同一种环境下。(更多详情请移步docker官网查看docker)html
默认已经安装了 docker,@vue/cli前端
相关版本:vue
Docker version 18.09.2, build 6247962java
vue cli --version 3.3.0node
macOS Mojave Verison 10.14.1ios
运行环境为macOS,若是与阅读者操做系统之间存在差别,请自行调整nginx
相关镜像:git
- 用 vue cli 建立一个vue项目,修改一下建立出来的项目,在页面上写一个前端接口请求,构建一版线上资源 ,基于nginx docker镜像构建成一个前端工程镜像,而后基于这个前端工程镜像,启动一个容器 vuenginxcontainer。
- 启动一个基于 node 镜像的容器 nodewebserver,提供后端接口。
- 修改 vuenginxcontainer 的 nginx 配置,使前端页面的接口请求转发到 nodewebserver 上。
- 稍做优化和改进。
yarn serve / npm run serve
复制代码
稍微改写一下页面,在App.vue中 传入HelloWorld 组件中的 msg 改成Hello Docker ; created 生命周期中加入一个接口请求web
import axios from 'axios';
……
axios.get('/api/json', {
params: {}
}).then(
res => {
console.log(res);
}
).catch(
error => {
console.log(error);
}
)
……
复制代码
这时候会在页面控制台看到一个报错信息:
运行命令
yarn build / npm run build
复制代码
dist
文件夹
若是将该dist目录整个传到服务器上,部署成静态资源站点就能直接访问到该项目。
接下来就来构建一个这样的静态资源站点。
nginx 是一个高性能的HTTP和反向代理服务器,此处咱们选用 nginx 镜像做为基础来构建咱们的vue应用镜像。
docker pull nginx
复制代码
docker
镜像(Image)一个特殊的文件系统。Docker镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。 镜像不包含任何动态数据,其内容在构建以后也不会被改变。- docker 镜像相关操做有: 搜索镜像
docker search [REPOSITORY[:TAG]]
、拉取镜像docker pull [REPOSITORY[:TAG]]
、查看镜像列表docker image ls
、删除镜像:docker image rm [REPOSITORY[:TAG]] / docker rmi [REPOSITORY[:TAG]]
等等。- docker 镜像名称由REPOSITORY和TAG组成
[REPOSITORY[:TAG]]
,TAG默认为latest
在项目根目录下建立nginx
文件夹,该文件夹下新建文件default.conf
server {
listen 80;
server_name localhost;
#charset koi8-r;
access_log /var/log/nginx/host.access.log main;
error_log /var/log/nginx/error.log error;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
复制代码
该配置文件定义了首页的指向为 /usr/share/nginx/html/index.html
, 因此咱们能够一会把构建出来的index.html文件和相关的静态资源放到/usr/share/nginx/html
目录下。
FROM nginx
COPY dist/ /usr/share/nginx/html/ COPY nginx/default.conf /etc/nginx/conf.d/default.conf 复制代码
- 自定义构建镜像的时候基于Dockerfile来构建。
FROM nginx
命令的意思该镜像是基于 nginx:latest 镜像而构建的。COPY dist/ /usr/share/nginx/html/
命令的意思是将项目根目录下dist文件夹下的全部文件复制到镜像中 /usr/share/nginx/html/ 目录下。COPY nginx/default.conf /etc/nginx/conf.d/default.conf
命令的意思是将nginx目录下的default.conf 复制到 etc/nginx/conf.d/default.conf,用本地的 default.conf 配置来替换nginx镜像里的默认配置。
运行命令(注意不要少了最后的 “.” )
docker build -t vuenginxcontainer .
复制代码
-t
是给镜像命名.
是基于当前目录的Dockerfile来构建镜像
docker image ls | grep vuenginxcontainer
复制代码
vue
应用镜像 vuenginxcontainer 已经成功建立。接下来,咱们基于该镜像启动一个
docker
容器。
Docker 容器Container: 镜像运行时的实体。镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例同样,镜像是静态的定义,容器是镜像运行时的实体。容器能够被建立、启动、中止、删除、暂停等 。
基于 vuenginxcontainer 镜像启动容器,运行命令:
docker run \
-p 3000:80 \
-d --name vueApp \
vuenginxcontainer
复制代码
docker run
基于镜像启动一个容器-p 3000:80
端口映射,将宿主的3000端口映射到容器的80端口-d
后台方式运行--name
容器名 查看 docker 进程
docker ps
复制代码
docker
容器部署了一个静态资源服务,能够访问到静态资源文件。还有 /api/json这个接口数据没有,接下来咱们来解决一下这个问题。
再部署一个 node 的容器来提供接口服务
用 node web 框架 express
来写一个服务,注册一个返回json数据格式的路由 server.js:
'use strict';
const express = require('express');
const PORT = 8080;
const HOST = '0.0.0.0';
const app = express();
app.get('/', (req, res) => {
res.send('Hello world\n');
});
app.get('/json', (req, res) => {
res.json({
code: 0,
data :'This is message from node container'
})
});
app.listen(PORT, HOST);
console.log(`Running on http://${HOST}:${PORT}`);
复制代码
运行该 express
应用须要 node
环境,咱们基于 node
镜像来构建一个新镜像
node
镜像docker pull node
复制代码
express
应用 docker
化FROM node
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 8080
CMD [ "npm", "start" ] 复制代码
构建镜像的时候 node_modules 的依赖直接经过 RUN npm install
来安装,项目中建立一个 .dockerignore
文件来忽略一些直接跳过的文件:
node_modules
npm-debug.log
复制代码
运行构建命令:
docker build -t nodewebserver .
复制代码
基于刚刚构建的 nodewebserver 镜像 启动一个名为 nodeserver 的容器来提供接口服务8080端口,并映射宿主的5000端口
docker run \
-p 5000:8080 \
-d --name nodeserver \
nodewebserver
复制代码
查看当前docker进程
docker ps
复制代码
想要将 vueApp 容器 上的请求转发到 nodeserver 容器上。首先须要知道 nodeserver 容器的ip
地址和端口,目前已知 nodeserver 容器内部服务监听在 8080 端口,还须要知道ip
便可。
查看容器内部 ip
有多种方式,这里提供两种:
docker exect -it 02277acc3efc bash
复制代码
cat /etc/hosts
复制代码
docker inspect 02277acc3efc
复制代码
在其中找到 Networks 相关配置信息:
location /api/ {
rewrite /api/(.*) /$1 break;
proxy_pass http://172.17.0.2:8080;
}
复制代码
修改完了以后意识到一个问题:vueApp 容器是基于 vuenginxcontainer 这个镜像运行的,而在一开始构建镜像的时候是将 nginx配置 default.conf 直接构建进去了。所以若是须要修改 default.conf 还得再从新构建一个新的镜像,再基于新镜像来运行新的容器。
能不能每次修改配置文件后直接重启容器就能让新配置生效,答案固然是有。
在构建镜像的时候 不把 Nginx 配置复制到镜像中,而是直接挂载到宿主机上,每次修改配置后,直接重启容器便可。
把 vueclidemo 项目下的 Dockerfile 修改一下
FROM nginx
COPY dist/ /usr/share/nginx/html/ COPY nginx/default.conf /etc/nginx/conf.d/default.conf 复制代码
将COPY nginx/default.conf /etc/nginx/conf.d/default.conf
命令删除,nginx配置都经过挂载命令挂载在宿主机上。再看 COPY dist/ /usr/share/nginx/html/
命令,若是每次构建的项目dist/下的内容变更都须要从新走一遍构建新镜像再启动新容器的操做,所以这条命令也能够删除,使用挂载的方式来启动容器。
直接基于nginx镜像来启动容器 vuenginxnew ,运行命令:
docker run \
-p 3000:80 \
-d --name vuenginxnew \
--mount type=bind,source=$HOME/SelfWork/docker/vueclidemo/nginx,target=/etc/nginx/conf.d \
--mount type=bind,source=$HOME/SelfWork/docker/vueclidemo/dist,target=/usr/share/nginx/html \
nginx
复制代码
--mount type=bind,source={sourceDir},target={targetDir}
将宿主机的sourceDir 挂载到容器的 targetDir 目录上。- 此处运行的命令较长,若是每次从新输入不免麻烦,咱们能够将完整的命令保存到一个
shell
文件vueapp.sh
中,而后直接执行sh vueapp.sh
。
这样就能每次修改了nginx配置或者 从新构建了vue应用的时候,只需重启容器就能立马生效。 此时咱们再访问 http://localhost:3000/api/json 能看到接口能正常返回,说明转发生效了。
后端服务通常都是双机或者多机以确保服务的稳定性。咱们能够再启动一个后端服务容器,并修改
nginx
的配置 来优化资源利用率,最大化吞吐量,减小延迟,确保容错配置。
基于前面 4.5 节的相似操做,新启动一个容器,并基于 5.1 节相似的操做,查看到 新容器的 IP (172.17.0.3)
修改一下 nginx/default.conf
(新增 upstream ,修改 location /api/ 中的 proxy_pass):
upstream backend {
server 172.17.0.2:8080;
server 172.17.0.3:8080;
}
……
location /api/ {
rewrite /api/(.*) /$1 break;
proxy_pass backend;
}
复制代码
不习惯命令行的同窗能够选用 Kitematic 来管理docker
容器的状态、数据目录和网络。全部对容量的操做均可以可视化的操做,这里就不作过多介绍了,有兴趣的同窗能够自行体验下。
docker提供了很是强大的自动化部署方式与灵活性,对多个应用程序之间作到了解耦,提供了开发上的敏捷性、可控性以及可移植性。本文以vue项目为例实现一个先后分离项目使用docker
部署的完整步骤,但愿能给想要拥抱 docker 的同窗带来一点帮助。
快狗打车前端团队专一前端技术分享,按期推送高质量文章,欢迎关注点赞。