docker是一个开源的应用容器引擎,能够为咱们提供安全、可移植、可重复的自动化部署的方式。docker采用虚拟化的技术来虚拟化出应用程序的运行环境。此种方式具备如下优点:css
每一个部署的应用程序都是一个容器,彼此隔离,互不影响;前端
服务器只须要安装docker便可运行构建好的应用程序镜像,不会涉及复杂的服务器环境配置,由于配置都在特定的应用程序所在的镜像中去配置便可;vue
简化了自动化部署和运维的繁琐流程,只需将构建好的镜像load到服务器的docker中便可运行咱们的应用程序;node
能够充分利用服务器的系统资源,一台服务器上能够同时运行多个容器;webpack
docker采用的是c/s架构,Client经过接口与Server进程通讯实现容器的构建,运行和发布。docker比较重要的三个核心概念以下:git
镜像(images):一个只读的模板,能够理解为应用程序的运行环境,包含了程序运行所依赖的环境和基本配置,镜像能够按照层级(从基础镜像开始)来构建,每一层包含特定的环境。程序员
仓库(repository):一个用于存放镜像文件的仓库,若是你对git的仓库熟悉,应该很容易理解,对,就是那个。有私有仓库和公有仓库之分。github
容器(container):一个运行应用程序的虚拟容器,在咱们运行镜像时产生。容器包含本身的文件系统+隔离的进程空间和包含其中的进程。web
sharplook是一款经过大数据分析来解决客户在监控系统中存在的数据采集难、解析难、处理难的IT运维产品。在给客户部署产品的过程当中涉及到比较多的环境配置和组件安装以及复杂的依赖项,这些繁琐的流程下降了安装部署的效率和产品质量。基于此,咱们开发了一款能够快速便捷的安装部署套件,提供一种漂亮的安装部署流程。产品采用 Nuxt + Koa 的基础架构进行开发,其中采用nuxt来提供SSR(服务端渲染)功能,Nuxt.js是基于Vue.js的通用架构,其中集成了如下组件:vue-router
另外,Nuxt.js 使用 Webpack 和 vue-loader 、 babel-loader 来处理代码的自动化构建工做(如打包、代码分层、压缩等等)。
咱们项目使用Nuxt.js做为中间件来进行UI渲染,使用Koa启动咱们本身的服务器,koa2 是由 Express 原班人马打造的,致力于成为一个更小、更富有表现力、更健壮的 Web 框架。
关于如何快速搭建这样一个项目,小生以前在《vue-cli “从入门到放弃”》中介绍过vue-cli的使用,这个项目咱们经过vue-cli工具,使用 nuxt-community/koa-template
模板,vue init nuxt-community/koa-template
快速构建出来。具体的代码逻辑,在此不作赘述。
关于为何选择docker来部署咱们的node服务,前面已经介绍了,咱们基于node的web应用涉及到的部署环境并不复杂,仅仅须要Node.js做为平台便可,因为依赖的包文件太多,并且比较大,业界尚未特别好用的开源node打包工具。作前端的同窗都知道,webpack是一个功能强大的资源加载构建的打包工具,只须要将项目文件打包到一个dist文件下,打包后的文件体量小,解决了文件之间的依赖问题,提取出公共代码库,生产环境只须要部署dist文件夹便可。然而,Nodejs程序涉及到的依赖包,和资源却无法进行打包,node服务开启后仅仅是一个node进程而已。那么咱们如何部署node程序呢?既然无法打包,只能将其所有文件进行部署(虽然可能存在别的问题,小生也在研究中,大神能够给点建议),因而小生就但愿将其放入docker中去部署,免去生产环境node版本不一致等问题。下面小生就将如何用docker来部署Node项目的过程分享给诸位。
如下将进入战备状态,请同志们准备好大脑和电脑,跟着我左手、右手一个慢动做。
安装docker,未安装的同窗,请根据本身的开发环境采用不一样的安装方式去安装,具体操做参考教程,不作赘述。
安装成功后,能够经过docker -v
查看版本号(尽可能使用最新的稳定版本)。
在你的项目根目录下,添加Dockerfile文件,此文件用来配置咱们自定义一个镜像所须要指定的依赖项、环境以及执行的命令等。内容格式以下:
# 指定咱们的基础镜像是node,版本是v8.0.0 FROM node:8.0.0 # 指定制做咱们的镜像的联系人信息(镜像建立者) MAINTAINER EOI # 将根目录下的文件都copy到container(运行此镜像的容器)文件系统的app文件夹下 ADD . /app/ # cd到app文件夹下 WORKDIR /app # 安装项目依赖包 RUN npm install RUN npm rebuild node-sass --force # 配置环境变量 ENV HOST 0.0.0.0 ENV PORT 8000 # 容器对外暴露的端口号 EXPOSE 8000 # 容器启动时执行的命令,相似npm run start CMD ["npm", "start"]
关于Dockerfile
文件中的关键字,解释以下:
FROM
语法:FROM <image>[:<tag>] 解释:设置要制做的镜像基于哪一个镜像,FROM指令必须是整个Dockerfile的第一个指令,若是指定的镜像不存在默认会自动从Docker Hub上下载。
MAINTAINER
语法:MAINTAINER <name> 解释:MAINTAINER指令容许你给将要制做的镜像设置做者信息。
ADD
语法:ADD <src> <dest> 解释:ADD指令用于从指定路径拷贝一个文件或目录到容器的指定路径中,<src>是一个文件或目录的路径,也能够是一个url,路径是相对于该Dockerfile文件所在位置的相对路径,<dest>是目标容器的一个绝对路径。
WORKDIR
语法:WORKDIR /path/to/workdir 解释:WORKDIR指令用于设置Dockerfile中的RUN、CMD和ENTRYPOINT指令执行命令的工做目录(默认为/目录),该指令在Dockerfile文件中能够出现屡次,若是使用相对路径则为相对于WORKDIR上一次的值,例如WORKDIR /data,WORKDIR logs,RUN pwd最终输出的当前目录是/data/logs。
RUN
语法:① RUN <command> #将会调用/bin/sh -c <command> ② RUN ["executable", "param1", "param2"] #将会调用exec执行,以免有些时候shell方式执行时的传递参数问题,并且有些基础镜像可能不包含/bin/sh 解释:RUN指令会在一个新的容器中执行任何命令,而后把执行后的改变提交到当前镜像,提交后的镜像会被用于Dockerfile中定义的下一步操做,RUN中定义的命令会按顺序执行并提交,这正是Docker廉价的提交和能够基于镜像的任何一个历史点建立容器的好处,就像版本控制工具同样。
ENV
语法:ENV <key> <value> 解释:ENV指令用于设置环境变量,在Dockerfile中这些设置的环境变量也会影响到RUN指令,当运行生成的镜像时这些环境变量依然有效,若是须要在运行时更改这些环境变量能够在运行docker run时添加–env <key>=<value>参数来修改。 注意:最好不要定义那些可能和系统预约义的环境变量冲突的名字,不然可能会产生意想不到的结果。
EXPOSE
语法:EXPOSE <port> [ ...] 解释:EXPOSE指令用来告诉Docker这个容器在运行时会监听哪些端口,Docker在链接不一样的容器(使用–link参数)时使用这些信息。
CMD
语法: ① CMD ["executable", "param1", "param2"] #将会调用exec执行,首选方式 ② CMD ["param1", "param2"] #当使用ENTRYPOINT指令时,为该指令传递默认参数 ③ CMD <command> [ <param1>|<param2> ] #将会调用/bin/sh -c执行 解释:CMD指令中指定的命令会在镜像运行时执行,在Dockerfile中只能存在一个,若是使用了多个CMD指令,则只有最后一个CMD指令有效。当出现ENTRYPOINT指令时,CMD中定义的内容会做为ENTRYPOINT指令的默认参数,也就是说可使用CMD指令给ENTRYPOINT传递参数。 注意:RUN和CMD都是执行命令,他们的差别在于RUN中定义的命令会在执行docker build命令建立镜像时执行,而CMD中定义的命令会在执行docker run命令运行镜像时执行,另外使用第一种语法也就是调用exec执行时,命令必须为绝对路径。
其中还有其余的一些关键字:USER、ENTRYPOINT、VOLUME、ONBUILD等,若是你有兴趣能够自行研究。
在项目根目录下添加.dockerignore
文件,此文件的做用相似.gitignore
文件,能够忽略掉添加进镜像中的文件,写法、格式和.gitignore
同样,一行表明一个忽略。本项目添加的忽略以下:
.DS_Store npm-debug.log* selenium-debug.log .nuxt/ /package-lock.json *.tar *.md # Editor directories and files .idea *.suo *.ntvs* *.njsproj *.sln
查看目前本地docker的镜像
> docker images REPOSITORY TAG IMAGE ID CREATED SIZE
cd 到项目根目录下,执行如下命令
> docker build -t deploy:1.0 . Sending build context to Docker daemon 1.436GB .... 此处省略1000个字符。 Successfully built d8f0875e967b Successfully tagged deploy:1.0
deploy
是镜像名,1.0
是镜像的版本号,到此你已经成功构建了一个新的镜像,你能够经过docker images
,查看你的镜像。
> docker images REPOSITORY TAG IMAGE ID CREATED SIZE deploy 1.0 d8f0875e967b 3 minutes ago 2.11GB
启动镜像,测试是否成功。
> docker run -d -p 9000:8000 deploy:1.0 8aec5ee037bb253901d2c2e02c7be546580546c493576139f3789fb660f3401d > docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8aec5ee037bb deploy:1.0 "npm start" 57 seconds ago Up 56 seconds 0.0.0.0:9000->8000/tcp amazing_bassi
docker run -d -p 9000:8000 deploy:1.0
中-d
表示后台运行,-p 9000:8000
表示指定本地的9000端口隐射到容器内的8000端口。 deploy:1.0
为咱们要运行的镜像。经过docker ps -a
查看docker的进程(容器的运行自己就是一种特殊的进程)运行状况,发现咱们的容器已经在运行。本地能够访问localhost:9000
。
经过docker logs
能够查看咱们容器内应用进程的运行日志。docker logs <CONTAINER ID>
> docker logs 8aec5ee037bb npm info it worked if it ends with ok npm info using npm@5.0.0 npm info using node@v8.0.0 npm info lifecycle newlook-deploy@1.0.0~prestart: newlook-deploy@1.0.0 npm info lifecycle newlook-deploy@1.0.0~start: newlook-deploy@1.0.0 > newlook-deploy@1.0.0 start /app > node ./server/index.js Server listening on 0.0.0.0:8000 DONE Compiled successfully in 9310ms06:55:56 > Open http://0.0.0.0:8000
docker stop <CONTAINER ID>能够中止容器运行 docker start <CONTAINER ID>能够启动容器运行 docker restart <CONTAINER ID>能够重启容器 docker rm <CONTAINER ID> -f能够强制删除在运行的容器
没注册DockerHub的同窗,请注册DockerHub
登陆docker
> docker login Username: XXX Password: XXX Login Succeeded
docker tag <name:tag> <namespace>/<name:tag>
上传以前必须给镜像打上tag,namespace
能够指定为你的docker Id
> docker tag deploy:1.0 lzqs/deploy:1.0
docker push <namespace>/<name:tag>
将镜像上传至docker的公共仓库
> docker push lzqs/deploy:1.0
上传成功后,docker logout
退出,登陆 https://hub.docker.com/
查看上传的镜像。
经过docker pull <namespace>/<name:tag>
下载咱们的镜像。
> docker pull lzqs/deploy:1.0
前面说了,咱们能够将上传到仓库的镜像下载下来部署,可是若是镜像比较大或者部署环境压根没法联网,你是否是要跪了。因此咱们采起另外一种方法,将开发好的镜像直接打包保存到安装盘里面,到客户生产环境再将镜像包上传并加载到服务器的docker中便可。
在开发环境打包,docker save <namespace>/<name:tag> <name>.tar
> docker save lzqs/deploy:1.0 > deploy.tar
这里ls
会发现目录下生成了deploy.tar的文件。部署时将此文件copy到生产环境服务器上。
确保生产服务器上已经安装了docker,若没装,请参考相关文档,若不装,对不起小生也无力了,而后在服务器上加载上传的镜像包deploy.tar
。
> docker load < deploy.tar 007ab444b234: Loading layer [==================================================>] 129.3 MB/129.3 MB 4902b007e6a7: Loading layer [==================================================>] 45.45 MB/45.45 MB bb07d0c1008d: Loading layer [==================================================>] 126.8 MB/126.8 MB ecf5c2e2468e: Loading layer [==================================================>] 326.6 MB/326.6 MB 7b3b4fef39c1: Loading layer [==================================================>] 352.3 kB/352.3 kB 677f02386f07: Loading layer [==================================================>] 137.2 kB/137.2 kB 7333bb4665b8: Loading layer [==================================================>] 55.66 MB/55.66 MB e292e64ffb88: Loading layer [==================================================>] 3.757 MB/3.757 MB ee76d0e6f6d9: Loading layer [==================================================>] 1.436 GB/1.436 GB 33dca533c6e5: Loading layer [==================================================>] 331.8 kB/331.8 kB 24630015679d: Loading layer [==================================================>] 35.18 MB/35.18 MB Loaded image: lzqs/deploy:1.0
加载成功后,docker images
便可看到加载的镜像
> docker images REPOSITORY TAG IMAGE ID CREATED SIZE lzqs/deploy 1.0 d8f0875e967b About an hour ago 2.115 GB
运行lzqs/deploy
镜像,成功后,在外部访问服务器的9000端口, <服务器的IP>:9000
> docker run -d -p 9000:8000 lzqs/deploy 1d0db9a5d0c8826171e501b0e86afd444fca8144b1105e63dae8d621bdda7a77 > docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1d0db9a5d0c8 lzqs/deploy:1.0 "npm start" About a minute ago Up About a minute 0.0.0.0:9000->8000/tcp goofy_curran
docker exec -it <CONTAINER ID> /bin/bash
能够进入容器中执行,方便咱们查看内部文件和调试
> docker exec -it 1d0db9a5d0c8 /bin/bash root@1d0db9a5d0c8:/app#
战功,访问部署的docker应用,<服务器的IP>:9000
,效果以下图:
七月流火,程序员的好日子要到了,固然也是你们的好日子快到了,适宜的温度应该更加高产。关于docker的研究还在进行中,为了前端更好的发展,让咱们继续燥起来吧,毕竟没有什么是一段JS解决不了的。