什么事Docker
docker是一个开源的应用容器引擎,可以为我们提供安全、可移植、可重复的自动化部署的方式。docker采用虚拟化的技术来虚拟化出应用程序的运行环境。此种方式具有以下优势:
1、 每个部署的应用程序都是一个容器,彼此隔离,互不影响;
2、 服务器只需要安装docker即可运行构建好的应用程序镜像,不会涉及复杂的服务器环境配置,因为配置都在特定的应用程序所在的镜像中去配置即可;
3、简化了自动化部署和运维的繁琐流程,只需将构建好的镜像load到服务器的docker中即可运行我们的应用程序;
4、可以充分利用服务器的系统资源,一台服务器上可以同时运行多个容器;
docker采用的是c/s架构,Client通过接口与Server进程通信实现容器的构建,运行和发布。docker比较重要的三个核心概念如下:
镜像(images):一个只读的模板,可以理解为应用程序的运行环境,包含了程序运行所依赖的环境和基本配置,镜像可以按照层级(从基础镜像开始)来构建,每一层包含特定的环境。
仓库(repository):一个用于存放镜像文件的仓库,如果你对git的仓库熟悉,应该很容易理解,对,就是那个。有私有仓库和公有仓库之分。
容器(container):一个运行应用程序的虚拟容器,在我们运行镜像时产生。容器包含自己的文件系统+隔离的进程空间和包含其中的进程。
实战开始
1、环境准备
安装docker,未安装的同学,请根据自己的开发环境采用不同的安装方式去安装,具体操作参考教程,不做赘述。
安装成功后,可以通过docker -v查看版本号(尽量使用最新的稳定版本)。
2、项目准备
在你的项目根目录下,添加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
MAINTAINER
语法:MAINTAINER解释:MAINTAINER指令允许你给将要制作的镜像设置作者信息。
ADD
语法:ADD解释:ADD指令用于从指定路径拷贝一个文件或目录到容器的指定路径中,是一个文件或目录的路径,也可以是一个url,路径是相对于该Dockerfile文件所在位置的相对路径,是目标容器的一个绝对路径。
WORKDIR
语法:WORKDIR/path/to/workdir 解释:WORKDIR指令用于设置Dockerfile中的RUN、CMD和ENTRYPOINT指令执行命令的工作目录(默认为/目录),该指令在Dockerfile文件中可以出现多次,如果使用相对路径则为相对于WORKDIR上一次的值,例如WORKDIR /data,WORKDIR logs,RUN pwd最终输出的当前目录是/data/logs。
RUN
语法:① RUN #将会调用/bin/sh -c
② RUN ["executable","param1","param2"]#将会调用exec执行,以避免有些时候shell方式执行时的传递参数问题,而且有些基础镜像可能不包含/bin/sh解释:RUN指令会在一个新的容器中执行任何命令,然后把执行后的改变提交到当前镜像,提交后的镜像会被用于Dockerfile中定义的下一步操作,RUN中定义的命令会按顺序执行并提交,这正是Docker廉价的提交和可以基于镜像的任何一个历史点创建容器的好处,就像版本控制工具一样。 ENV
语法:ENV解释:ENV指令用于设置环境变量,在Dockerfile中这些设置的环境变量也会影响到RUN指令,当运行生成的镜像时这些环境变量依然有效,如果需要在运行时更改这些环境变量可以在运行docker run时添加–env=参数来修改。 注意:最好不要定义那些可能和系统预定义的环境变量冲突的名字,否则可能会产生意想不到的结果。
EXPOSE
语法:EXPOSE[ ...]解释:EXPOSE指令用来告诉Docker这个容器在运行时会监听哪些端口,Docker在连接不同的容器(使用–link参数)时使用这些信息。
CMD
语法: ①CMD["executable","param1","param2"]#将会调用exec执行,首选方式②CMD["param1","param2"]#当使用ENTRYPOINT指令时,为该指令传递默认参数③CMD [ | ]#将会调用/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 directoriesandfiles
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
构建镜像
查看目前本地docker的镜像
> docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
cd 到项目根目录下,执行以下命令
> docker build -t 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
> docker logs 8aec5ee037bb
npm info it worked if it ends with ok
npm info using [email protected]
npm info using [email protected]
npm info lifecycle [email protected]~prestart: [email protected]
npm info lifecycle [email protected]~start: [email protected]
> [email protected] start /app > node ./server/index.jsServer listening on 0.0.0.0:8000 DONE Compiled successfully in 9310ms06:55:56 > Open http://0.0.0.0:8000
docker stop
docker start
docker restart
docker rm
上传镜像(这里用上传到公共仓库来演示)
没注册DockerHub的同学,请注册DockerHub
登录docker
> docker login
Username: XXX
Password: XXXLogin
Succeeded
docker tag
> docker tag deploy:1.0 lzqs/deploy:1.0
docker push
> docker push lzqs/deploy:1.0
上传成功后,docker logout 退出,登录 https://hub.docker.com/ 查看上传的镜像。
下载镜像
通过docker pull
> docker pull lzqs/deploy:1.0
生产部署
前面说了,我们可以将上传到仓库的镜像下载下来部署,但是如果镜像比较大或者部署环境压根无法联网,你是不是要跪了。所以我们采取另一种方法,将开发好的镜像直接打包保存到安装盘里面,到客户生产环境再将镜像包上传并加载到服务器的docker中即可。
在开发环境打包,docker save
> 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
>dockerexec-it 1d0db9a5d0c8 /bin/bash
root@1d0db9a5d0c8:/app#
打完收工,可以再外边访问了