轻量级虚拟化技术
5.1 教学目标
1. 能力目标 
(1)能够根据项目实际,运用Docker设计资源隔离运行环境解决方案,以支持开发
复杂软件系统的解决方案。
(2)能够根据项目需求,在容器和虚拟机技术之间进行准确评估和恰当选择,以解决
复杂工程的关键问题。
(3)能够基于工程实际,将Docker、CephFS和Hadoop进行有效集成,以解决复杂软
件工程问题。
2. 素质目标
(1)能够准确撰写Docker实现运行空间隔离的解决方案,并对方案分析和评估性
价比。
(2)能够翔实撰写Docker环境搭建的文档,对所遇问题和解决措施予以记录和分析。
5.2 Docker 容器实践基础
5.2.1 安装Docker 
Docker是一个开源的应用容器引擎,基于Go语言并遵从Apache2.0开源协议。
Docker可以让开发者打包应用以及依赖包到一个轻量级、可移植的容器中,然后发布到
任何流行的Linux机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不
会有任何接口,更重要的是容器性能开销极低。
Docker使用客户端/服务器(C/S)架构模式,使用远程API来管理和创建Docker容
器。Docker容器通过Docker镜像来创建。容器与镜像的关系类似于面向对象编程中的
对象与类。Docker的官方安装说明网址如下。 
https://docs.docker.com/install/linux/docker- ee/centos/# install- from - the 
-repository 
5

1 40 
1. 检查系统内核
Docker要求CentOS 系统的内核版本高于3.20,查看本页面的前提条件来验证
CentOS版本是否支持Docker。查看当前内核版本,执行如下的命令。 
[root@master 189]#uname -r 
命令执行结果显示如下。 
3.20.0-693.el7.x86_64 
2. 安装Docker 
Docker软件包和依赖包包含在默认的CentOS-Extras软件源里,安装命令如下。 
[root@master 189]#yum -y install docker 
3. 查看Docker 版本
启动Docker版本,执行如下的命令。 
[root@master 189]#docker version 
命令执行结果显示如下。 
Client: 
Version: 1.13.2 
API version: 1.26 
Package version: 
Cannot connect to the Docker daemon at unix:///var/run/docker. sock. Is the 
docker daemon running? 
4. 启动Docker 
启动Docker,执行如下的命令。 
[root@master 189]#systemctl start docker.service 
5. 验证Docker 启动是否成功
验证启动是否成功,执行如下的命令。 
[root@master 189]# docker version 
输出信息中如果有Client和Server两部分,表示Docker安装与启动均成功。
6. 加入开机启动
加入开机启动,执行如下的命令。

1 41 
[root@master 189]#sudo systemctl enable docker 
5.2.2 Docker基本操作
1. Docker 镜像基本操作 
本次实验包含Docker基本操作,仅提供简单Docker操作命令演示,更多操作请访问
官方文档。
(1)手动启动Docker服务,执行如下的命令。 
#service docker start 
(2)查看本机所有的镜像,执行如下的命令。 
#docker images 
命令执行结果显示如下。 
REPOSITORY TAG IMAGE ID CREATED SIZE 
实验环境中没有镜像,所以只输出头信息。
(3)查找镜像。
通过dockersearch命令查找镜像,如查找alpine镜像,执行如下的命令。 
#docker search alpine 
(4)拉取镜像。
查找到需要的镜像以后,可以通过dockerpull命令拉取指定的镜像。以拉取alpine 
镜像为例,执行如下的命令。 
#docker pull alpine 
如果不指定镜像标签,则默认拉取最新版本的镜像。查看已拉取的镜像,执行如下的
命令。 
#docker images 
命令执行结果显示如下。 
REPOSITORY TAG IMAGE ID CREATED SIZE 
docker.io/alpine latest 389fef711851 3 weeks ago 5.58 MB 
(5)构建镜像。
当搜索不到需要的镜像时,可以使用dockerbuild命令构建镜像,以alpine:latest为
基础镜像,添加自定义脚本,并在容器启动时执行脚本,输出“hellodockermy New 
Build”。
首先查看test.sh文件,该脚本仅输出“hellodocker”到终端,不执行其他操作。 
#vi test.sh

1 42 
文件打开后,仅有一个如下的输出操作。 
echo "hello docker my New Build" 
查看并编辑Dockerfile文件,执行如下的命令。 
#vim Dockerfile 
文件内容如下。 
FROM alpine:latest 
ADD ./test.sh /test.sh 
RUN chmod +x /test.sh 
CMD ["/bin/sh", "-c", "/test.sh"] 
构建镜像,执行如下的命令。 
#docker build -t hello-docker. 
运行构建的容器,执行如下的命令。 
#docker run --name hello-docker hello-docker 
命令执行结果显示如下。 
hello docker my New Build 
可以看到容器正确执行了自定义脚本。制作Docker镜像有如下两种方式。
第1种:dockercommit,保存容器(Container)的当前状态到镜像后,然后生成对应
的镜像。
第2种:dockerbuild,使用Dockerfile文件自动化制作镜像。
A.dockercommit 
启动一个实例,执行如下的命令。 
[root@master 189]#docker images 
[root@master 189]#docker run -it centos:latest /bin/bash 
安装Apache,执行如下的命令。 
[root@DMaster]#yum -y install httpd 
[root@DMaster]#exit 
查看容器的状态,执行如下的命令。 
[root@master docker]#docker ps -a 
命令执行结果显示如下。 
CONTAINER ID IMAGE COMMAND CREATED STATUS 
72ad7c24ba38 centos:latest "/bin/bash" 3 hours ago Exited (0) 48 seconds ago 
21eac7115704 hello-docker "/bin/sh -c /test.sh" 4 hours ago Exited (0) 4 hours ago

1 43 
e4e63beea0e6 hello-world "/hello" 5 hours ago Exited (0) 5 hours ago 
根据容器当前状态制作一个镜像,语法:dockercommit<容器ID> [仓库]:[标
签],其具体示例语句如下。 
[root@master docker]#docker commit 72ad7c24ba38 centos:httpd 
命令执行结果显示如下。 
sha256:6ec494cd22012b53698d3733b6bce4aa824d714f0f8384d29310d21c23dc7e15 
[root@master docker]#docker images 
命令执行结果显示如下。 
REPOSITORY TAG IMAGE ID CREATED SIZE 
centos httpd 6ec494cd2201 About a minute ago 209 MB 
hello-docker latest 864d2be3c4db 4 hours ago 5.58 MB 
docker.io/alpine latest 389fef711851 3 weeks ago 5.58 MB 
docker.io/centos latest 300e315adb2f 5 weeks ago 209 MB 
docker.io/hello-world latest bf756fb1ae65 12 months ago 13.4 kB 
启动新创建的镜像,查看是否存在httpd服务,执行如下的命令。 
[root@master docker]#docker run -it centos:httpd /bin/bash 
[root@master docker /]#rpm -qa httpd 
命令执行结果显示如下。 
httpd-2.4.6-89.el7.centos.1.x86_64 
如果看到上面的输出信息,则说明httpd存在。
B.dockerbuild 
使用dockerbuild 创建镜像时,需要使用Dockerfile 文件自动化制作镜像。
Dockerfile类似源码编译./configure 后产生的Makefile。首先创建工作目录,制作
Dockerfile,执行如下的命令。 
[root@master docker]#mkdir /docker-build 
[root@master docker]#vim /docker-build/Dockerfile 
文件打开后,编辑文件内容如下。 
FROM centos:latest #以哪个镜像为基础
MAINTAINER <youxi@163.com> #镜像创建者
RUN yum -y install httpd #运行安装httpd 命令
ADD start.sh /usr/local/bin/start.sh 
#将本地文件复制到镜像中,权限为755,uid 和gid 为0 
ADD index.html /var/www/html/index.html

1 44 
CMD /usr/local/bin/start.sh 
#实例启动后执行的命令,在strat.sh 里添加需要开机启动的服务或脚本
创建start.sh和index.html,执行如下的命令。 
[root @ master docker]# echo "/usr/sbin/httpd - DFOREGROUND" > /docker - build/ 
start.sh 
[root@master docker]#chmod +x /docker-build/start.sh 
[root @ master docker ]# echo " docker image build test " > /docker - build/ 
index.html 
删除已有的centos:httpd,先查看其容器ID,然后根据容器ID予以删除,执行如下的
命令。 
[root@master docker]#docker ps -a 
命令执行结果显示如下。 
CONTAINER ID IMAGE COMMAND CREATED STATUS 
660fb6e03ba3 centos:httpd "/bin/bash" 21 minutes ago Exited (127) 6 seconds ago 
72ad7c24ba38 centos:latest "/bin/bash" 4 hours ago Exited (0) 35 minutes ago 
21eac7115704 hello-docker "/bin/sh -c /test.sh" 5 hours ago Exited (0) 5 hours ago 
e4e63beea0e6 hello-world "/hello" 5 hours ago Exited (0) 5 hours ago 
根据容器ID对容器予以先停止后删除,执行如下的命令。 
[root@master docker]#docker stop 660fb6e03ba3 
[root@master docker]#docker rm 660fb6e03ba3 
[root@master docker]#docker ps -a 
命令执行结果显示如下。 
CONTAINER ID IMAGE COMMAND CREATED STATUS 
72ad7c24ba38 centos:latest "/bin/bash" 4 hours ago Exited (0) 35 minutes ago 
21eac7115704 hello-docker "/bin/sh -c /test.sh" 5 hours ago Exited (0) 5 hours ago 
e4e63beea0e6 hello-world "/hello" 5 hours ago Exited (0) 5 hours ago 
[root@master docker]#docker rmi centos:httpd 
命令执行结果显示如下。 
Untagged: centos:httpd 
Deleted: 
sha256:6ec494cd22012b53698d3733b6bce4aa824d714f0f8384d29310d21c23dc7e15 
Deleted: 
sha256:2c9b167f19cee62b426761a4e48d02ec6d1b8edd8107eeccb5617c4cd9f94868 
[root@master docker]#docker images

1 45 
命令执行结果显示如下。 
REPOSITORY TAG IMAGE ID CREATED SIZE 
hello-docker latest 864d2be3c4db 5 hours ago 5.58 MB 
docker.io/alpine latest 389fef711851 3 weeks ago 5.58 MB 
docker.io/centos latest 300e315adb2f 5 weeks ago 209 MB 
docker.io/hello-world latest bf756fb1ae65 12 months ago 13.4 kB 
使用build创建新的镜像,语法:dockerbuild-t[仓库名]:[标签][Dockerfile文件
路径],其示例语句如下。 
[root@master docker]#docker build -t centos:httpd /docker-build/ 
[root@master docker]#docker images 
命令执行结果显示如下。 
REPOSITORY TAG IMAGE ID CREATED SIZE 
centos httpd 5fde376f6cb5 13 minutes ago 250 MB 
hello-docker latest 864d2be3c4db 5 hours ago 5.58 MB 
docker.io/alpine latest 389fef711851 3 weeks ago 5.58 MB 
docker.io/centos latest 300e315adb2f 5 weeks ago 209 MB 
docker.io/hello-world latest bf756fb1ae65 12 months ago 13.4 kB 
(6)Docker镜像发布有发布到本地和发布到网上两种方式,具体如下。
① 发布到本地。
语法:dockersave -o[tar包名][仓库名]:[标签],示例命令如下。 
[root @ master docker]# docker save - o docker. id - centos - httpd - image. tar 
centos:httpd 
[root@master docker]#ll -h 
② 发布到网上。
一般先到https://hub.docker.com/(DockerHub)上注册一个账号,并创建一个存储
库,然后使用如下的登录命令。 
[root@master docker]#docker login -u [用户名]-p [密码] 
上传镜像。注意:上传前需要修改仓库名,否则上传有问题。 
[root@master docker]#docker tag centos:httpd 738441242/centos 
738441242是笔者的Docker用户名,centos是建立的存储库。 
[root@master docker]#docker push 738441242/centos 
发布成功后,登录DockHub用户,查看镜像仓库,如图5-1所示。
(7)删除镜像,使用dockerrmi<ID> 命令予以删除。如果镜像已经被容器运行, 
则先停止并删除对应的容器,而后删除镜像。

1 46 
图5-1 发布到远程DockHub用户下的仓库
2. Dockerfile 文件
(1)什么是Dockerfile。
Dockerfile是组合镜像命令的文本文档,可以在命令行中调用任何命令。Docker通
过读取Dockerfile中的指令自动生成镜像。dockerbuild命令用于从Dockerfile构建镜
像。可以在dockerbuild命令中使用-f标志指向文件系统中任何位置的Dockerfile,如下
所示。 
docker build -f /path/to/a/Dockerfile 
(2)Dockerfile的基本结构。
Dockerfile一般分为基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指
令四部分,#开头的内容为Dockerfile中的注释。
(3)Dockerfile文件说明。
Docker以从上到下的顺序运行Dockerfile的指令。为了指定基本镜像,第一条指令
必须是FROM。一个声明以#字符开头则被视为注释。可以在Docker文件中使用
RUN、CMD、FROM、EXPOSE、ENV 等指令。下面列出了一些常用的指令。
FROM:指定基础镜像,必须为第一个命令,格式如下。 
FROM <image> 
FROM <image>:<tag> 
FROM <image>@<digest> 
示例:FROM mysql:5.6 
tag或digest是可选的,如果不使用这两个值时,会使用latest版本的基础镜像。
MAINTAINER:维护者信息,格式如下。 
MAINTAINER <name> 
示例如下所示。 
MAINTAINER Jasper Xu

1 47 
MAINTAINER sorex@163.com 
MAINTAINER Jasper Xu <sorex@163.com> 
RUN:构建镜像时执行的命令,用于在镜像容器中执行命令,有以下两种命令执行
方式。
shell执行,格式: 
RUN <command> 
exec执行,格式: 
RUN ["executable", "param1", "param2"] 
示例如下所示。 
RUN ["executable", "param1", "param2"] 
RUN apk update 
RUN ["/etc/execfile", "arg1", "arg1"] 
RUN 指令创建的中间镜像会被缓存,并会在下次构建中使用。如果不想使用这些
缓存镜像,可以在构建时指定--no-cache参数,如:dockerbuild--no-cache。
ADD:将本地文件添加到容器中,tar类型文件会自动解压(网络压缩资源不会被解
压),可以访问网络资源,类似wget,格式如下。 
ADD <src>... <dest> 
ADD ["<src>",..."<dest>"]用于支持包含空格的路径。
示例如下所示。 
ADD hom* /mydir/ #添加所有以"hom"开头的文件
ADD hom?.txt /mydir/ #?替代一个单字符,例如: "home.txt" 
ADD test relativeDir/ #添加"test" 到`WORKDIR`/relativeDir/ 
ADD test /absoluteDir/ #添加"test" 到/absoluteDir/ 
COPY:功能类似ADD,但是不会自动解压文件,也不能访问网络资源。
CMD:构建容器后调用,也就是在容器启动时才进行调用,其格式如下。 
CMD ["executable","param1","param2"](执行可执行文件,优先) 
CMD ["param1","param2"](设置了ENTRYPOINT,则直接调用ENTRYPOINT 添加参数) 
CMD command param1 param2 (执行shell 内部命令) 
示例如下所示。 
CMD echo "This is a test." | wc - 
CMD ["/usr/bin/wc","--help"] 
CMD不同于RUN,CMD用于指定在容器启动时所要执行的命令,而RUN 用于指
定镜像构建时所要执行的命令。

1 48 
ENTRYPOINT:配置容器,使其可执行化。配合CMD 可省去“application”,只使用
参数,具体格式如下所示。 
ENTRYPOINT ["executable", "param1", "param2"](可执行文件, 优先) 
ENTRYPOINT command param1 param2 (shell 内部命令) 
示例如下所示。 
FROM ubuntu 
ENTRYPOINT ["top", "-b"] 
CMD ["-c"] 
ENTRYPOINT与CMD非常类似,不同的是通过dockerrun执行的命令不会覆盖
ENTRYPOINT,而dockerrun命令中指定的任何参数,都会被当作参数再次传递给
ENTRYPOINT。Dockerfile中只允许有一个ENTRYPOINT 命令,多指定时会覆盖前
面的设置,而只执行最后的ENTRYPOINT指令。
LABEL:用于为镜像添加元数据,其格式如下所示。 
LABEL <key>=<value><key>=<value><key>=<value>... 
示例如下所示。 
LABEL version="1.0" description="这是一个Web 服务器" by="IT 笔录" 
使用LABEL指定元数据时,一条LABEL指定可以指定一或多条元数据,指定多条
元数据时不同元数据之间通过空格分隔。推荐将所有的元数据通过一条LABEL指令指
定,以免生成过多的中间镜像。
ENV:设置环境变量,其格式如下所示。
ENV <key> <value> #<key>之后的所有内容均会被视为其<value>的组成
部分,因此,一次只能设置一个变量。
ENV <key>=<value>...#可以设置多个变量,每个变量为一个“<key>= 
<value>”的键值对,如果<key>中包含空格,可以使用\来进行转义,也可以通过""来
进行标示;另外,反斜线也可以用于续行。
示例如下所示。 
ENV myName John Doe 
ENV myDog Rex The Dog 
ENV myCat=fluffy 
EXPOSE:指定与外界交互的端口,格式:EXPOSE <port> [<port>...],示例如
下所示。 
EXPOSE 80 443 
EXPOSE 8080 
EXPOSE 11211/tcp 11211/udp