从 0 开始 之 Docker部署Vue项目

什么是Docker

  • 装应用的容器
  • 开发、测试、运维都偏爱的容器化技术
  • 轻量级
  • 扩展性
  • 一次构建、多次分享、随处运行
原理 对 Docker 最简单并且带有一定错误的认知就是 “Docker 是一种性能非常好的虚拟机”。
Docker 相比于传统虚拟机的技术来说先进了不少,具体表现在 Docker 不是在宿主机上虚拟出一套硬件后再虚拟出一个操作系统,而是让 Docker 容器里面的进程直接运行在宿主机上(Docker 会做文件、网络等的隔离),这样一来 Docker 会 “体积更轻、跑的更快、同宿主机下可创建的个数更多”。
Docker 中有三个核心概念:Image、Container、Repository。
  • Image: 有领“好人卡”倾向的广大程序猿一定对 镜像 的概念不会陌生。但和 windows 的那种 iso 镜像相比,Docker 中的镜像是分层的,可复用的,而非简单的一堆文件迭在一起(类似于一个压缩包的源码和一个 git 仓库的区别)。
  • Container: 容器的存在离不开镜像的支持,他是镜像运行时的一个载体(类似于实例和类的关系)。依托 Docker 的虚拟化技术,给容器创建了独立的端口、进程、文件等“空间”,Container 就是一个与宿机隔离 “容器”。容器可宿主机之间可以进行 port、volumes、network 等的通信。
  • Repository: Docker 的仓库和 git 的仓库比较相似,拥有仓库名、tag。在本地构建完镜像之后,即可通过仓库进行镜像的分发。常用的 Docker hub 有 https://hub.docker.com/、http... 等。
腾讯云云服务器安装Docker 腾讯云提供了开发者实验室帮助用户搭建 Docker 环境。
安装与配置 Docker
安装 Docker 添加镜像信息
在实际安装过程中,可能受限于国内网络问题,会出现安装缓存或者失败。
#官方给的镜像 #yum-config-manager --add-repo #建议使用阿里云的镜像进行加速,要不太慢了 yum-config-manager --add-repo

Docker 软件包已经包括在默认的 CentOS-Extras 软件源里。因此想要安装 docker,只需要运行下面的 yum 命令:
yum install docker-io -y
直接yum安装,安装成功后查看版本
docker -v
启动docker
service docker start
【从 0 开始 之 Docker部署Vue项目】设置开机启动
chkconfig docker on
配置 Docker 因为国内访问 Docker Hub 较慢, 可以使用腾讯云提供的国内镜像源, 加速访问 Docker Hub
依次执行以下命令
echo "OPTIONS='--registry-mirror=https://mirror.ccs.tencentyun.com'" >> /etc/sysconfig/dockersystemctl daemon-reloadservice docker restart

报错 从 0 开始 之 Docker部署Vue项目
文章图片

Docker 的简单操作
下载镜像 下载一个官方的 CentOS 镜像到本地
docker pull centos
下载好的镜像就会出现在镜像列表里
docker images
运行容器 这时我们可以在刚才下载的 CentOS 镜像生成的容器内操作了。
生成一个 centos 镜像为模板的容器并使用 bash shell
docker run -it centos /bin/bash
从 0 开始 之 Docker部署Vue项目
文章图片

这个时候可以看到命令行的前端已经变成了 [root@(一串 hash Id)] 的形式, 这说明我们已经成功进入了 CentOS 容器。
在容器内执行任意命令, 不会影响到宿主机, 如下
mkdir -p /data/simple_docker
可以看到 /data 目录下已经创建成功了 simple_docker 文件夹
ls /data
退出容器
exit
查看宿主机的 /data 目录, 并没有 simple_docker 文件夹, 说明容器内的操作不会影响到宿主机
ls /data
从 0 开始 之 Docker部署Vue项目
文章图片

保存容器 查看所有的容器信息, 能获取容器的id
docker ps -a
然后执行如下命令,保存镜像:
docker commit -m="备注" 你的CONTAINER_ID 你的IMAGE
请自行将 -m 后面的信息改成自己的容器的信息
Docker的镜像操作命令 Docker 镜像命令
下载docker镜像
docker pull centos
查看本地所有镜像
docker imagesdocker image ls -a
启动镜像
docker run -it NAME:TAG /bin/bash// 格式
docker run -it centos /bin/bash // 案列
运行 Docker 镜像(守护态方式)
docker run -d {镜像名}
查看镜像详细信息
docker inspect NAME:TAG// 格式
删除指定 Docker 镜像
docker image rm {镜像名}
清理镜像(临时镜像和没有被使用的镜像)
docker image prune
创建镜像别名
docker tag IMAGEID{镜像id} REPOSITORY:TAG(仓库:标签)// 格式
docker tag ccbcea8a6757 test:test// 案列
从 0 开始 之 Docker部署Vue项目
文章图片

Docker 容器命令
查看所有正在运行容器
docker ps
docker ps -a
列出所有容器(包括已停止容器)
docker ps -l
查看所有容器ID
docker ps -a -q
进入运行中的 Docker 容器
docker exec -it {容器ID} /bin/bash
容器重命名
docker rename nginx-1 web-1// 将nginx-1重新命名为web-1
启动已存在容器
docker start {容器ID}
停止指定容器
docker stop {容器ID}
删除指定容器
docker rm -f {容器ID}
删除停止的容器
docker container prune
所有容器的IP地址
docker inspect --format='{{.Name}} - {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -aq)
查看 Docker 容器历史运行日志
docker logs {容器名}
docker logs -f -t {容器ID} // -t 显示时间戳
Docker 文件操作命令
从主机复制文件到 Docker 容器中
sudo docker cp {主机内文件路径} {容器ID}:{容器内文件存储路径}
从 Docker 容器中复制文件到主机中
sudo docker cp {容器ID}:{容器内文件路径} {主机内文件存储路径}
Docker 数据卷命令
创建 Docker 数据卷
docker volume create {数据卷名}
列出所有 Docker 数据卷
docker volume ls
删除指定 Docker 数据卷
docker volume rm {数据卷名}
删除未关联(失效) Docker 数据卷
docker volume prune
docker volume rm $(docker volume ls -qf dangling=true)
删除指定容器
docker rm -f {容器ID}
删除停止的容器
docker container prune
查看 Docker 容器历史运行日志
docker logs {容器名}
docker启动镜像命令科普
docker run :创建一个新的容器并运行一个命令
语法
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

OPTIONS说明:
  • -a stdin: 指定标准输入输出内容类型,可选 STDIN/STDOUT/STDERR 三项;
  • -d: 后台运行容器,并返回容器ID;
  • -i: 以交互模式运行容器,通常与 -t 同时使用;
  • -P: 随机端口映射,容器内部端口随机映射到主机的端口
  • -p: 指定端口映射,格式为:主机(宿主)端口:容器端口
  • -t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用;
  • --name="nginx-lb": 为容器指定一个名称;
  • --dns 8.8.8.8: 指定容器使用的DNS服务器,默认和宿主一致;
  • --dns-search example.com: 指定容器DNS搜索域名,默认和宿主一致;
  • -h "mars": 指定容器的hostname;
  • -e username="ritchie": 设置环境变量;
  • --env-file=[]: 从指定文件读入环境变量;
  • --cpuset="0-2" or --cpuset="0,1,2": 绑定容器到指定CPU运行;
  • -m :设置容器使用内存最大值;
  • --net="bridge": 指定容器的网络连接类型,支持 bridge/host/none/container: 四种类型;
  • --link=[]: 添加链接到另一个容器;
  • --expose=[]: 开放一个端口或一组端口;
  • --volume , -v: 绑定一个卷
实例 使用docker镜像nginx:latest以后台模式启动一个容器,并将容器命名为mynginx。
docker run --name mynginx -d nginx:latest
使用镜像nginx:latest以后台模式启动一个容器,并将容器的80端口映射到主机随机端口。
docker run -P -d nginx:latest
使用镜像 nginx:latest,以后台模式启动一个容器,将容器的 80 端口映射到主机的 80 端口,主机的目录 /data 映射到容器的 /data。
docker run -p 80:80 -v /data:/data -d nginx:latest
绑定容器的 8080 端口,并将其映射到本地主机 127.0.0.1 的 80 端口上。
docker run -p 127.0.0.1:80:8080/tcp ubuntu bash
使用镜像nginx:latest以交互模式启动一个容器,在容器内执行/bin/bash命令。
docker run -it nginx:latest /bin/bash
Docker 部署 vue 项目
  1. 用 vue cli 创建一个vue项目,修改一下创建出来的项目,在页面上写一个前端接口请求,构建一版线上资源 ,基于nginx docker镜像构建成一个前端工程镜像,然后基于这个前端工程镜像,启动一个容器 vuenginxcontainer。
  2. 启动一个基于 node 镜像的容器 nodewebserver,提供后端接口。
  3. 修改 vuenginxcontainer 的 nginx 配置,使前端页面的接口请求转发到 nodewebserver 上。
  4. 稍作优化和改进。
创建 vue 应用
这里就不多说了,指路创建vue-cli3项目。注:项目中要有接口调用
打包项目
yarn build / npm run build
此时工程根目录下多出一个dist文件夹
如果将该dist目录整个传到服务器上,部署成静态资源站点就能直接访问到该项目。
构建vue应用镜像
nginx 是一个高性能的HTTP和反向代理服务器,此处我们选用 nginx 镜像作为基础来构建我们的vue应用镜像。
拉取Nginx的镜像 docker pull nginx
从 0 开始 之 Docker部署Vue项目
文章图片

已经有了nginx镜像。我们根据nginx镜像运行容器
docker run --name=nginx -d -p 4030:80 nginx
然后在浏览器里面访问4030端口,验证容器是否运行正常
从 0 开始 之 Docker部署Vue项目
文章图片

创建 nginx config配置文件 在项目根目录下创建nginx-docker文件夹,该文件夹下新建文件default.conf
server { listen80; server_namelocalhost; #charset koi8-r; access_log/var/log/nginx/host.access.logmain; error_log/var/log/nginx/error.logerror; location /api/ { rewrite/api/(.*)/$1break; proxy_pass http://172.18.0.3:9728; }location / { root/usr/share/nginx/html; indexindex.html index.htm; }#error_page404/404.html; # redirect server error pages to the static page /50x.html # error_page500 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目录下。
添加Dockerfile文件 从 0 开始 之 Docker部署Vue项目
文章图片

FROM nginx COPY dist/ /usr/share/nginx/html/ COPY nginx-docker/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-docker目录下的default.conf 复制到 etc/nginx/conf.d/default.conf,用本地的 default.conf 配置来替换nginx镜像里的默认配置。
基于该Dockerfile构建vue应用镜像 文件上传以后 构建Vue程序的镜像(运行命令 注意不要少了最后的 “.” )
docker build -t dockervue .// -t 是给镜像命名 . 是基于当前目录的Dockerfile来构建镜像
从 0 开始 之 Docker部署Vue项目
文章图片

运行vue容器 基于 dockervue镜像启动容器,运行命令:
docker run --name=dockervue -d -p 9020:80 dockervue
  • docker run 基于镜像启动一个容器
  • -p 3000:80 端口映射,将宿主的3000端口映射到容器的80端口
  • -d 后台方式运行
  • --name 容器名 查看 docker 进程
从 0 开始 之 Docker部署Vue项目
文章图片

可以看到容器在运行,我们在浏览器里面访问9020端口
目前为止,已经通过docker容器部署了一个静态资源服务,可以访问到静态资源文件。
构建node接口服务镜像
获取node镜像 docker pull node:alpine
编写Dockerfile将koa2项目docker化
# 引入node:alpine FROM node:alpine # 创建文件夹 RUN mkdir -p /usr/dockerfile/web/node # 把当前目录所有内容拷贝到目录node内容受.dockerignore影响 COPY . /usr/dockerfile/web/node # 进入到app目录下面,类似cd WORKDIR /usr/dockerfile/web/node # 全局安装 pm2 RUN npm install pm2 -g # 安装项目依赖 RUN npm install # 暴露的端口 EXPOSE 9728 # 程序启动脚本 CMD ["npm", "prd"]

构建镜像的时候 node_modules 的依赖直接通过 RUN npm install 来安装,项目中创建一个 .dockerignore文件来忽略一些直接跳过的文件:
node_modules npm-debug.log

构建镜像 docker build -t dockernode .
启动 docker-node 容器
#启动镜像 -d表示后台执行,-p 5000:9728 (9728:9728)表示(本机端口:容器端口),3000是笔者的nodejs代码中监听的访问端口,也是容器对外暴露的端口 docker run --name=dockernode -d -p 9728:9728 dockernode #查看容器 docker ps

跨域转发 想要将 vue容器 上的请求转发到 node 容器上。首先需要知道 node 容器的ip地址和端口,目前已知 node 容器内部服务监听在 9728端口,还需要知道ip即可。
查看 nodeserver 容器的 ip 地址 docker inspect [ containerId ] 直接查看容器信息:
docker inspect 02277acc3efc
从 0 开始 之 Docker部署Vue项目
文章图片

从 0 开始 之 Docker部署Vue项目
文章图片

在其中找到 Networks 相关配置信息:
从 0 开始 之 Docker部署Vue项目
文章图片

也可以查看所有容器的IP地址
docker inspect --format='{{.Name}} - {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -aq)
从 0 开始 之 Docker部署Vue项目
文章图片

记录下node服务容器对应的ip,一会儿配置nginx转发的时候会用到。
修改 nginx 配置
  • Nginx 配置 location 指向 node 服务 default.conf (前端想要了解的Nginx,关于Nginx的配置已经 location 的具体写法可以参考(一文弄懂Nginx的location匹配))
  • 添加一条重写规则,将 /api/{path} 转到目标服务的 /{path} 接口上。 在前面的nginx-docker/default.conf文件中加入:
location /api/ { rewrite/api/(.*)/$1break; proxy_pass http://172.17.0.2:8080; }

修改完了之后意识到一个问题:vue 容器是基于 dockervue这个镜像运行的,而在一开始构建镜像的时候是将 nginx配置 default.conf 直接构建进去了。因此如果需要修改 default.conf 还得再重新构建一个新的镜像,再基于新镜像来运行新的容器。
改进
能不能每次修改配置文件后直接重启容器就能让新配置生效,答案当然是有。
在构建镜像的时候 不把 Nginx 配置复制到镜像中,而是直接挂载到宿主机上,每次修改配置后,直接重启容器即可。
修改 Dockerfile 文件 把 vueclidemo 项目下的 Dockerfile 修改一下
FROM nginx COPY dist//usr/share/nginx/html/ COPY nginx-docker/default.conf /etc/nginx/conf.d/default.conf

COPY nginx-docker/default.conf /etc/nginx/conf.d/default.conf命令删除,nginx配置都通过挂载命令挂载在宿主机上。再看 COPY dist/ /usr/share/nginx/html/ 命令,如果每次构建的项目dist/下的内容变动都需要重新走一遍构建新镜像再启动新容器的操作,因此这条命令也可以删除,使用挂载的方式来启动容器。
新运行vue应用容器 直接基于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应用的时候,只需重启容器就能立马生效。

    推荐阅读