Docker镜像原理
Docker镜像是什么?
镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。
1. UnionFS(联合文件系统)
UnionFS(联合文件系统):Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual
filesystem)。Union文件系统是Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
特性:
一次同时加载多个文件系统,但从外面看来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
2. Docker镜像加载原理
Docker镜像加载原理:
Docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。
bootfs(boot file system) 主要包含bootloader和kernel, bootloader主要是引导加载kernel, Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。
rootfs (root file system) ,在bootfs之上。包含的就是典型Linux系统中的/dev, /proc, /bin, /etc等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu,CentOS等等。
平时我们安装的虚拟机CentOS都是好几个G,为什么docker里面才200M?
对于一个精简的OS,rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供 rootfs就行了。由此可见对于不同的linux发行版, bootfs基本是一致的, roots会有差别,因此不同的发行版可以公用bootfs。
3. 分层的镜像
我们在pull镜像的过程中,在下载的过程中可以看到docker的镜像好像是在一层一层的下载的。
而且还有一个现象,为什么CentOS只有200MB,而Tomcat却有600多MB呢?
[root@VeejaAliYun ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat latest 040bdb29ab37 6 days ago 649MB
centos latest 300e315adb2f 6 weeks ago 209MB
hello-world latest bf756fb1ae65 12 months ago 13.3kB
其实表面上看tomcat并不大,但是tomcat的镜像却是Kernel、CentOS、Java叠加起来的,构成了一个精简版的基于Linux的Tomcat。
4. 为什么要采用这种分层结构呢?
最大的一个好处就是——资源共享。
比如:有多个镜像都从相同的base镜像构建而来,那么宿主机只需在磁盘上保存一份base镜像。
同时内存中也只需加载一份base镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。
特点:
Docker镜像都是只读的。
当容器启动时,一个新的可写层被加载到镜像的顶部。
这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。
Docker commit
操作补充
docker commit
:从容器创建一个新的镜像,提交容器副本使之成为一个新的镜像。
语法:
docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
参数说明:
-a
:提交的镜像作者;-c
:使用Dockerfile指令来创建镜像;-m
:提交时的说明文字;-p
:在commit时,将容器暂停。
我们演示一下:
-
先从HUB上下载tomcat并且运行成功。
下载Tomcat。[root@VeejaAliYun ~]# docker pull tomcat Using default tag: latest latest: Pulling from library/tomcat Digest: sha256:94cc18203335e400dbafcd0633f33c53663b1c1012a13bcad58cced9cd9d1305 Status: Image is up to date for tomcat:latest docker.io/library/tomcat:latest
运行一个Tomcat,我们使用-p来指定端口:
[root@VeejaAliYun ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE mongo latest 29d9c9b800fa 5 days ago 493MB tomcat latest 040bdb29ab37 6 days ago 649MB centos latest 300e315adb2f 6 weeks ago 209MB hello-world latest bf756fb1ae65 12 months ago 13.3kB [root@VeejaAliYun ~]# docker run -it -p 8888:8080 tomcat Using CATALINA_BASE: /usr/local/tomcat Using CATALINA_HOME: /usr/local/tomcat Using CATALINA_TMPDIR: /usr/local/tomcat/temp Using JRE_HOME: /usr/local/openjdk-11 Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar Using CATALINA_OPTS: NOTE: Picked up JDK_JAVA_OPTIONS: --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED 20-Jan-2021 01:40:25.900 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version name: Apache Tomcat/9.0.41 20-Jan-2021 01:40:25.908 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server built: Dec 3 2020 11:43:00 UTC 20-Jan-2021 01:40:25.909 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version number: 9.0.41.0 20-Jan-2021 01:40:25.909 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Name: Linux 20-Jan-2021 01:40:25.909 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Version: 3.10.0-514.26.2.el7.x86_64 20-Jan-2021 01:40:25.909 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Architecture: amd64 20-Jan-2021 01:40:25.909 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Java Home: /usr/local/openjdk-11 20-Jan-2021 01:40:25.909 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Version: 11.0.9.1+1 20-Jan-2021 01:40:25.909 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Vendor: Oracle Corporation 20-Jan-2021 01:40:25.909 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_BASE: /usr/local/tomcat 20-Jan-2021 01:40:25.909 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_HOME: /usr/local/tomcat 20-Jan-2021 01:40:25.955 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: --add-opens=java.base/java.lang=ALL-UNNAMED 20-Jan-2021 01:40:25.955 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: --add-opens=java.base/java.io=ALL-UNNAMED 20-Jan-2021 01:40:25.955 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED 20-Jan-2021 01:40:25.955 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties 20-Jan-2021 01:40:25.960 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager 20-Jan-2021 01:40:25.961 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djdk.tls.ephemeralDHKeySize=2048 20-Jan-2021 01:40:25.961 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.protocol.handler.pkgs=org.apache.catalina.webresources 20-Jan-2021 01:40:25.961 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 20-Jan-2021 01:40:25.961 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dignore.endorsed.dirs= 20-Jan-2021 01:40:25.961 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dcatalina.base=/usr/local/tomcat 20-Jan-2021 01:40:25.961 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dcatalina.home=/usr/local/tomcat 20-Jan-2021 01:40:25.961 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.io.tmpdir=/usr/local/tomcat/temp 20-Jan-2021 01:40:26.001 INFO [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent Loaded Apache Tomcat Native library [1.2.25] using APR version [1.6.5]. 20-Jan-2021 01:40:26.002 INFO [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true]. 20-Jan-2021 01:40:26.002 INFO [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent APR/OpenSSL configuration: useAprConnector [false], useOpenSSL [true] 20-Jan-2021 01:40:26.010 INFO [main] org.apache.catalina.core.AprLifecycleListener.initializeSSL OpenSSL successfully initialized [OpenSSL 1.1.1d 10 Sep 2019] 20-Jan-2021 01:40:27.149 INFO [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["http-nio-8080"] 20-Jan-2021 01:40:27.259 INFO [main] org.apache.catalina.startup.Catalina.load Server initialization in [2194] milliseconds 20-Jan-2021 01:40:27.442 INFO [main] org.apache.catalina.core.StandardService.startInternal Starting service [Catalina] 20-Jan-2021 01:40:27.442 INFO [main] org.apache.catalina.core.StandardEngine.startInternal Starting Servlet engine: [Apache Tomcat/9.0.41] 20-Jan-2021 01:40:27.479 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-nio-8080"] 20-Jan-2021 01:40:27.592 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in [331] milliseconds
我们可以看一下现在的容器:
[root@VeejaAliYun ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 4c463d6ed686 tomcat "catalina.sh run" 14 minutes ago Up 14 minutes 0.0.0.0:8888->8080/tcp strange_wiles
我们尝试访问一下8888端口:
我们看到,是可以访问Tomcat的,只是没有资源。 -
我们进入Tomcat,进行一些修改:
[root@VeejaAliYun ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 4c463d6ed686 tomcat "catalina.sh run" 14 minutes ago Up 14 minutes 0.0.0.0:8888->8080/tcp strange_wiles [root@VeejaAliYun ~]# docker exec -it 4c463d6ed686 /bin/bash root@4c463d6ed686:/usr/local/tomcat# ls -l total 156 -rw-r--r-- 1 root root 18982 Dec 3 11:48 BUILDING.txt -rw-r--r-- 1 root root 5409 Dec 3 11:48 CONTRIBUTING.md -rw-r--r-- 1 root root 57092 Dec 3 11:48 LICENSE -rw-r--r-- 1 root root 2333 Dec 3 11:48 NOTICE -rw-r--r-- 1 root root 3257 Dec 3 11:48 README.md -rw-r--r-- 1 root root 6898 Dec 3 11:48 RELEASE-NOTES -rw-r--r-- 1 root root 16507 Dec 3 11:48 RUNNING.txt drwxr-xr-x 2 root root 4096 Jan 13 08:25 bin drwxr-xr-x 1 root root 4096 Jan 20 01:40 conf drwxr-xr-x 2 root root 4096 Jan 13 08:25 lib drwxrwxrwx 1 root root 4096 Jan 20 01:40 logs drwxr-xr-x 2 root root 4096 Jan 13 08:25 native-jni-lib drwxrwxrwx 2 root root 4096 Jan 13 08:25 temp drwxr-xr-x 2 root root 4096 Jan 13 08:25 webapps drwxr-xr-x 7 root root 4096 Dec 3 11:45 webapps.dist drwxrwxrwx 2 root root 4096 Dec 3 11:43 work root@4c463d6ed686:/usr/local/tomcat# cd webapps root@4c463d6ed686:/usr/local/tomcat/webapps# mkdir ROOT ..................修改
-
这个时候Tomcat已经有了改变,我们可以尝试docker commit来形成一个新的镜像。
[root@VeejaAliYun ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 4c463d6ed686 tomcat "catalina.sh run" 28 minutes ago Up 3 minutes 0.0.0.0:8888->8080/tcp strange_wiles [root@VeejaAliYun ~]# docker commit -a="veeja" -m="tomcat test" 4c463d6ed686 veeja/tomcatveeja:1.1 sha256:cc4277f237876df762c72a728081a42a9eee0f62a9aecc9582f449760cd7e373 [root@VeejaAliYun ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE veeja/tomcatveeja 1.1 cc4277f23787 21 seconds ago 649MB mongo latest 29d9c9b800fa 5 days ago 493MB tomcat latest 040bdb29ab37 6 days ago 649MB centos latest 300e315adb2f 6 weeks ago 209MB hello-world latest bf756fb1ae65 12 months ago 13.3kB
上面我们可以看到,在我们commit之后,再查看镜像的时候,就有了两个Tomcat的镜像,一个是官方的,一个是我们自己的。
-
我们尝试运行一下,我们自己的镜像:
[root@VeejaAliYun ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE veeja/tomcatveeja 1.1 cc4277f23787 6 minutes ago 649MB mongo latest 29d9c9b800fa 5 days ago 493MB tomcat latest 040bdb29ab37 6 days ago 649MB centos latest 300e315adb2f 6 weeks ago 209MB hello-world latest bf756fb1ae65 12 months ago 13.3kB [root@VeejaAliYun ~]# docker run -it -p 7777:8080 veeja/tomcatveeja:1.1 Using CATALINA_BASE: /usr/local/tomcat Using CATALINA_HOME: /usr/local/tomcat Using CATALINA_TMPDIR: /usr/local/tomcat/temp Using JRE_HOME: /usr/local/openjdk-11 Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar Using CATALINA_OPTS: NOTE: Picked up JDK_JAVA_OPTIONS: --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED 20-Jan-2021 02:20:15.414 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version name: Apache Tomcat/9.0.41 20-Jan-2021 02:20:15.428 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server built: Dec 3 2020 11:43:00 UTC 20-Jan-2021 02:20:15.444 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version number: 9.0.41.0 20-Jan-2021 02:20:15.444 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Name: Linux 20-Jan-2021 02:20:15.445 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Version: 3.10.0-514.26.2.el7.x86_64 20-Jan-2021 02:20:15.445 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Architecture: amd64 20-Jan-2021 02:20:15.445 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Java Home: /usr/local/openjdk-11 20-Jan-2021 02:20:15.445 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Version: 11.0.9.1+1 20-Jan-2021 02:20:15.445 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Vendor: Oracle Corporation 20-Jan-2021 02:20:15.445 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_BASE: /usr/local/tomcat 20-Jan-2021 02:20:15.445 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_HOME: /usr/local/tomcat 20-Jan-2021 02:20:15.470 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: --add-opens=java.base/java.lang=ALL-UNNAMED 20-Jan-2021 02:20:15.470 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: --add-opens=java.base/java.io=ALL-UNNAMED 20-Jan-2021 02:20:15.470 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED 20-Jan-2021 02:20:15.470 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties 20-Jan-2021 02:20:15.470 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager 20-Jan-2021 02:20:15.471 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djdk.tls.ephemeralDHKeySize=2048 20-Jan-2021 02:20:15.471 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.protocol.handler.pkgs=org.apache.catalina.webresources 20-Jan-2021 02:20:15.471 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 20-Jan-2021 02:20:15.471 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dignore.endorsed.dirs= 20-Jan-2021 02:20:15.471 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dcatalina.base=/usr/local/tomcat 20-Jan-2021 02:20:15.471 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dcatalina.home=/usr/local/tomcat 20-Jan-2021 02:20:15.471 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.io.tmpdir=/usr/local/tomcat/temp 20-Jan-2021 02:20:15.489 INFO [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent Loaded Apache Tomcat Native library [1.2.25] using APR version [1.6.5]. 20-Jan-2021 02:20:15.490 INFO [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true]. 20-Jan-2021 02:20:15.490 INFO [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent APR/OpenSSL configuration: useAprConnector [false], useOpenSSL [true] 20-Jan-2021 02:20:15.509 INFO [main] org.apache.catalina.core.AprLifecycleListener.initializeSSL OpenSSL successfully initialized [OpenSSL 1.1.1d 10 Sep 2019] 20-Jan-2021 02:20:16.780 INFO [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["http-nio-8080"] 20-Jan-2021 02:20:16.907 INFO [main] org.apache.catalina.startup.Catalina.load Server initialization in [2239] milliseconds 20-Jan-2021 02:20:17.139 INFO [main] org.apache.catalina.core.StandardService.startInternal Starting service [Catalina] 20-Jan-2021 02:20:17.140 INFO [main] org.apache.catalina.core.StandardEngine.startInternal Starting Servlet engine: [Apache Tomcat/9.0.41] 20-Jan-2021 02:20:17.166 INFO [main] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [/usr/local/tomcat/webapps/ROOT]
我们就可以在新镜像的运行的容器中看到我们的修改了。