1. Docker 镜像原理
思考:
- Docker镜像本质是什么?
答:是一个分层的文件系统。 - Docker中一个centos镜像为什么只有200MB,而一个centos操作系统的iso文件要几个G?
答:Centos的iso镜像包含bootfs和rootfs,而docker的centos镜像复用操作系统的bootfs,只有rootfs和其他镜像层。 - Docker中一个tomcat镜像为什么有500MB,而一个tomcat安装包只有70多MB?
答:由于docker中镜像是分层的,tomcat虽然只有70多MB,但他需要依赖父镜像和基础镜像,所以整个对外暴露的tomcat镜像大小500MB。
首先要了解操作系统的组成部分当中,有个很重要的部分叫文件管理子系统
那么我们所用的docker是基于centos,或者说基于linux,所以在这里以linux的文件管理子系统做阐述
Linux文件系统由bootfs和rootfs俩部分组成
- bootfs:包含bootloader(引导加载程序)和kernel(内核)
- rootfs:root文件系统,包含的就是典型linux系统中的/dev,/proc,/bin,/etc等标准目录和文件
- 不同的linux发行版,bootfs基本一样,而rootfs不同,如ubuntu,centos等
在了解了bootfs和rootfs之后,我们可以知道Docker镜像是由特殊的文件系统叠加而成
- 如何叠加?
- 最低端是bootfs,并使用宿主机的bootfs,意思就是镜像使用的是宿主机的内核
- 第二层是root文件系统rootfs,称为base image
- 然后再往上可以叠加其他的镜像文件
- 统一文件系统技术能够将不同的层整合成一个文件系统,为这些层提供了一个统一的视角,这样就隐藏了多层的存在,在用户的角度看来,只存在一个文件系统
- 一个镜像可以放在另一个镜像的上面,位于下面的镜像称为父镜像,最底部的镜像,成为基础镜像。
以tomcat镜像为例:
所以tomcat镜像为什么有500MB原因就是用户只看到了tomcat镜像,看不到具体的细节,在这个tomcat镜像的背后还隐藏着200多MB的JDK和rootfs基础镜像
2. Docker 镜像制作
1. 容器转为镜像
#容器转为镜像
docker commit 容器id 镜像名称:版本号
#将镜像转为压缩文件
docker save -o 压缩文件名称 镜像名称:版本号
#将压缩文件还原为镜像
docker load -i 压缩文件名称
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
注:在原容器转为镜像之后,目录挂载会失效
2. dockerfile
概念:
- Dockerfile是一个文本文件
- 包含了一条条的指令
- 每一条指令构建一层,属于基础镜像,最终构建出一个新的镜像
- 对于开发人员:可以为开发团队提供一个完全一致的开发环境
- 对于测试人员:可以直接拿着开发时所构建的镜像或者通过Dockerfile文件构建一个新的镜像开始工作了
- 对于运维人员:在部署时,可以实现应用的无缝移植
2.1 Dockerfile常用指令
(1) FROM 指定基础镜像
FROM centos
- 1
(2)MAINTAINER 指定镜像的维护者信息,一般为邮箱
MAINTAINER hitredrose@
- 1
(3)RUN 镜像构建时需要执行的命令
RUN yum install -y wget
- 1
(4)ADD 增加文件,会自动解压
ADD /usr/local/
- 1
(5)WORKDIR 设置当前工作目录
WORKDIR /usr/local/python/
- 1
(6)VOLUME 挂载主机目录
VOLUME ["/usr/local/python","/usr/local/java/"]
- 1
(7)EXPOSE 暴露端口,注意这里指仅暴露容器的端口,并不会将容器端口与宿主机端口映射。也就是说在使用docker run的时候仍然需要继续使用-p进行端口映射,换言之,EXPOSE更多的作用在于给Dockerfile开发者提供开发端口的提示提示作用
EXPOSE 80
- 1
(8)CMD 指定容器启动的时候需要执行的命令,注意CMD只有最后一个命令会生效
CMD /bin/bash
- 1
(9)ENTRYPOINT 指定容器启动时需要运行的命令,注意ENTRYPOINT命令可以追加命令,即如果有多条ENTRYPOINT命令会全部执行,这是ENTRYPOINT命令和CMD命令最大的区别
ENTRYPOINT cd /opt
ENTRYPOINT /bin/bash
- 1
- 2
(10)ONBUILD 当构建一个被继承Dockerfile,这个时候就会运行ONBUILD指令
(11)COPY 类似ADD命令,将文件拷贝到镜像中
(11)ENV 构建的时候设置环境变量
2.2 Dockerfile实战测试
- 编写如下Dockerfile文件,创建自己的centos镜像
FROM centos
MAINTAINER redrose2100<hitredrose@>
ENV JAVA_HOME /usr/local/jdk_1.8/
WORKDIR /usr/local
RUN yum install -y vim
RUN yum install -y net-tools
EXPOSE 80
CMD echo $JAVA_HOME
CMD echo "---end---"
CMD /bin/bash
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 编译镜像
docker build -f Dockerfile -t mycentos:1.0 .
- 1
- 然后执行docker images 查看如下:
[root@iZbp1flzt6x7pxmxfhmxeeZ opt]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mycentos 1.0 122504aa874c About a minute ago 337MB
redrose2100/centos 1.1 2184c3aadaab 30 hours ago 231MB
nginx latest f8f4ffc8092c 4 weeks ago 133MB
mysql 5.7 9f35042c6a98 4 weeks ago 448MB
centos latest 5d0da3dc9764 6 weeks ago 231MB
[root@iZbp1flzt6x7pxmxfhmxeeZ opt]#
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 测试运行
如下,当前工作目录已经切换到 /usr/local 目录下,JAVA_HOME变量也是有值的,ifconfig命令也支持了
[root@iZbp1flzt6x7pxmxfhmxeeZ opt]# docker run -it mycentos:1.0
[root@b868b5ba93e9 local]# pwd
/usr/local
[root@b868b5ba93e9 local]# echo $JAVA_HOME
/usr/local/jdk_1.8/
[root@b868b5ba93e9 local]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.3 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:ac:11:00:03 txqueuelen 0 (Ethernet)
RX packets 8 bytes 656 (656.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[root@b868b5ba93e9 local]#
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
参考:
Dockerfile关键字详解