【必知必会】通过Dockerfile构建自己的镜像。
构建镜像建议在Docker里操作,所以本章的练习都是在vms100这台机器上操作的。
前面所使用的镜像都是我们从网上下载下来的,有的镜像并不能满足我们的需求,比如CentOS镜像里就没有ifconfig命令,所以很多时候要根据自己的需求来自定义镜像。
自定义镜像的过程并非从零到有,而是在已经存在的镜像的基础上进行修改,这个已经存在的镜像称为“基镜像”。
要自定义镜像,就需要写Dockerfile文件了,如果文件名不是Dockerfile,那么编译镜像时需要使用-f选项来指定文件名,如图2-1所示。
图2-1 用Dockerfile构建镜像的流程
构建镜像的本质就是,先利用基镜像生成一个临时容器,然后在这个临时容器里执行Dockerfile里定义的命令,等做完所有的操作之后,会把这个临时容器导出为一个新的镜像,最后把这个临时容器删除。
关键就是如何写Dockerfile,Dockerfile的格式及常用命令如下。
(1)FROM:指定基镜像。
(2)MAINTAINER:维护者的信息。
(3)RUN:想在临时容器里执行的操作系统命令。
(4)ADD file /path/:把物理机里的file拷贝到镜像的指定目录/path里,可以自动解压压缩文件。
(5)COPY file /path/:把物理机里的file拷贝到镜像的指定目录/path里,不会自动解压压缩文件。
(6)ENV:指定变量。
(7)USER:指定容器内部以哪个用户运行进程。
(8)VOLUME:指定数据卷。
(9)EXPOSE:指定镜像容器所使用的端口,这只是一个标记。
(10)CMD:指定镜像创建出来的容器运行什么进程。
Dockerfile的内容如下。
这个文件里指明了基于hub.c.163.com/library/centos这个镜像自定义新的镜像,在新的镜像里安装net-tools工具包。
在临时容器里执行系统命令时都要以RUN开头,构建语法如下。
这里的“目录”的意思是,后面讲往新镜像里拷贝文件时可以用ADD或COPY,这个“目录”是要拷贝的文件所在目录,如果写“.”,表示从当前目录里拷贝文件到镜像里。
如果构建镜像的文件名不是Dockerfile,需要使用-f选项来指定文件名,具体如下。
开始构建。
构建完成后,查看现有镜像。
使用该镜像创建出一个容器,并验证是否可以执行ifconfig命令。
可以看到,一切是正常的。
先做准备工作,把所需要的repo文件拷贝出来。
这里把物理机/etc/yum.repos.d里的repo文件放在压缩文件repo.tar.gz里了。
物理机目录/etc/yum.repos.d/里的这些repo文件是在一开始安装Docker时就下载下来的。
创建index.html,内容如下。
创建dockerfile1,内容如下。
(1)CentOS自带的yum源里并没有Nginx软件包,所以在执行yum install nginx -y命令之前需要配置yum源,这里把打包好的repo文件拷贝到镜像的/etc/yum.repos.d里。
(2)在容器里Nginx作为守护进程运行,必须以nginx -g daemon off格式运行,这个格式是固定的。
(3)一定要按照拷贝yum源→安装→拷贝index.html的顺序执行,大家可以考虑一下这是为什么。
开始构建,指定镜像的名称为nginx:v1。
因为文件名是dockerfile1,不是Dockerfile,所以这里需要使用-f选项来指定文件名。
使用此镜像运行一个容器并验证。
在浏览器里打开192.168.26.100,查看结果,如图2-2所示。
图2-2 测试新的镜像是否编译成功
有的读者会问,如何修改Nginx的配置文件?其实只要把配置文件修改好,以ADD的方式添加过去即可。
自行删除Web容器。
ADD和COPY都可以把当前目录里的文件拷贝到临时容器里,但是ADD和COPY在拷贝压缩文件时存在一些区别。ADD把压缩文件拷贝到临时容器里时会自动解压,COPY不带解压功能。
在当前目录里随意创建一个压缩文件,这里有个aa.tar.gz,内容如下。
创建dockerfile2,内容如下。
aa.tar.gz以ADD的方式拷贝到镜像的/11目录里。
aa.tar.gz以COPY的方式拷贝到镜像的/22目录里。
编译镜像,镜像名为centos:add-copy。
使用该镜像创建出一个容器并验证结果。
可以看到,以ADD方式拷贝过去的压缩文件进行了解压操作,而以COPY方式拷贝过去的并没有解压。
前面做的镜像里,都是以root来运行进程,如果要以指定的用户来运行进程,可以使用USER命令。创建dockerfile3,内容如下。
这里首先创建出lduan用户,然后使用USER命令指定后面容器里要以lduan来运行进程。
编译镜像,镜像名为centos:user。
使用该镜像创建出一个容器。
可以看到,容器里的进程是以lduan的身份来运行的。如果要以root身份进入容器里,加上--user=root选项即可。
删除这个容器c1。
创建dockerfile4,内容如下。
构建镜像,名称为centos:env。
使用该镜像创建出一个容器。
可以看到,容器里存在一个变量myenv=/aa。
在创建容器时是可以使用-e选项来指定变量的值的。
创建dockerfile5,内容如下。
此新镜像创建出来的容器里,会创建一个目录/data1绑定物理机的随机目录。
构建镜像,名称为centos:volume。
使用该镜像创建出一个容器。
在其他终端上查看此容器的属性。
如果想有多个挂载点,应该写成VOLUME ["/data1", "/data"]。
Dockerfile的内容如下。
更好的写法如下。