docker镜像结构
docker镜像结构
一、docker镜像揭秘
从整体的角度来讲,一个完整的Docker镜像可以支撑一个Docker容器的运行,在Docker容器运行过程中主要提供文件系统。例如一个centos:7的镜像,提供了一个基本的centos:7的发行版,当然此镜像是不包含操作系统Linux内核的。
从根本上讲,一个容器不过是一个正在运行的进程,并对其应用了一些附加的封装功能,以使其与主机和其他容器隔离。容器隔离的最重要方面之一是每个容器都与自己的专用文件系统进行交互。该文件系统由Docker镜像提供。镜像包括运行应用程序所需的一切代码或二进制文件,运行时,依赖项以及所需的任何其他文件系统对象。

1、镜像通过Docker Daemon守护进程生成容器
2、json文件中指定了一些Env(环境变量)、Cmd(命令),这些json文件由/bin/bash环境来进行解析运行
3、镜像层的layer内容可以理解为它对应的文件系统,也就是数据,运行成容器时数据原封不动的拷贝到容器,
rootfs也就是容器中的文件系统,镜像是只读模版的,不能修改数据,只有到容器中才能对数据有写的权限
二、docker镜像与docker容器的关系
Docker镜像是Docker容器运行的基础,没有Docker镜像,就不可能有Docker容器,这也是Docker的设计原则之一。
可以理解的是Docker镜像毕竟是镜像,属于静态的内容。而Docker容器就不一样了,容器属于动态的内容。动态的内容,大家很容易联想到进程,内存,CPU等之类的东西。的确,Docker容器作为动态的内容,都会包含这些。
为了便于理解,大家可以把Docker容器,理解为一个或多个运行进程,而这些运行进程将占有相应的内存,相应的CPU计算资源,相应的虚拟网络设备以及相应的文件系统资源。而Docker容器所占用的文件系统资源,则通过Docker镜像的镜像层文件来提供。
那么作为静态的镜像,如何才有能力转化为一个动态的Docker容器呢?
其实,转化的依据是每个镜像的json文件,Docker可以通过解析Docker镜像的json的文件,获知应该在这个镜像之上运行什么样的进程,应该为进程配置怎么样的环境变量,此时也就实现了静态向动态的转变。
是由Docker守护进程来完成这个转化工作的。Docker容器实质上就是一个或者多个进程,而容器的父进程就是Docker守护进程(Docker Daemon)。这样的,转化工作的执行就不难理解了。Docker守护进程 手握Docker镜像的json文件,为容器配置相应的环境,并真正运行Docker镜像所指定的进程,完成Docker容器的真正创建。Docker容器运行起来之后,Docker镜像json文件就失去作用了。此时Docker镜像的绝大部分作用就是为Docker容器提供一个文件系统,供容器内部的进程访问文件资源。
三、docker镜像分层结构
1、base镜像
(1)不依赖其他镜像,从scratch构建(难度大)
(2)以此为基础镜像,进行扩展
base镜像通常都是各种Linux发行版的Docker镜像。不同Linux发行版的区别主要就是rootfs。比如Ubuntu 14.04使用upstart管理服务,apt管理软件包;而 CentOS7使用systemd和yum。这些都是用户空间上的区别,Linux kernel差别不大。所以Docker可以同时支持多种Linux镜像,模拟出多种操作系统环境。容器只能使用Docker host的kernel,并且不能修改。

2、分层结构
Docker里的镜像绝大部分都是在别的镜像的基础上去进行创建的,也就是使用镜像的分层结构。实际上,Docker Hub中99%的镜像都是通过在base镜像中安装和配置需要的软件构建出来的。

简单镜像构建:
[root@stw ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 41f689c20910 6 weeks ago 192MB
httpd latest 65005131d37e 7 weeks ago 117MB
centos 7 eeb6ee3f44bd 4 years ago 204MB
[root@stw ~]# vim Dockerfile
[root@stw ~]# cat Dockerfile
FROM centos:7
RUN mkdir /galaxy
RUN touch /galaxy/cy
CMD ["/bin/bash"]
[root@stw ~]# docker build -t galaxy:v1 . //-t 镜像名称 Dockerfile的父目录
[+] Building 1.6s (7/7) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 108B 0.0s
=> [internal] load metadata for docker.io/library/centos:7 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [1/3] FROM docker.io/library/centos:7 0.0s
=> [2/3] RUN mkdir /galaxy 0.9s
=> [3/3] RUN touch /galaxy/cy 0.4s
=> exporting to image 0.1s
=> => exporting layers 0.1s
=> => writing image sha256:358cb5259f154f9213baee360b391d4a912d03bc375857 0.0s
=> => naming to docker.io/library/galaxy:v1 0.0s
[root@stw ~]# pwd
/root
[root@stw ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
galaxy v1 358cb5259f15 19 seconds ago 204MB
nginx latest 41f689c20910 6 weeks ago 192MB
httpd latest 65005131d37e 7 weeks ago 117MB
centos 7 eeb6ee3f44bd 4 years ago 204MB
[root@stw ~]# docker history galaxy:v1 //查看构建的历史记录
IMAGE CREATED CREATED BY SIZE COMMENT
358cb5259f15 46 seconds ago CMD ["/bin/bash"] 0B buildkit.dockerfile.v0
<missing> 46 seconds ago RUN /bin/sh -c touch /galaxy/cy # buildkit 0B buildkit.dockerfile.v0
<missing> 46 seconds ago RUN /bin/sh -c mkdir /galaxy # buildkit 0B buildkit.dockerfile.v0
<missing> 4 years ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 4 years ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B
<missing> 4 years ago /bin/sh -c #(nop) ADD file:b3ebbe8bd304723d4… 204MB
3、容器层
当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。
镜像层数量可能会很多,所有镜像层会联合在一起组成一个统一的文件系统。如果不同层中有一个相同路径的文件,比如/galaxy,上层的/galaxy会覆盖下层的/galaxy,也就是说用户只能访问到上层中的文件 /galaxy。在容器层中,用户看到的是一个叠加之后的文件系统,(容器层的数据是从镜像层复制到容器中)

四、docker镜像构建的三种方法
1、docker commit命令
2、基于本地模版导入
3、Dockerfile构建文件
1、docker commit命令
docker commit命令可以基于容器创建镜像,创建过程大致分为三步,先创建容器,在容器中安装我们所需要的内容,再使用docker commit将容器打包为镜像即可。
案例展示:
(1)先基于centos7运行容器,容器名为stw,并使用-it生成终端进入容器
[root@stw ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
galaxy v1 358cb5259f15 3 hours ago 204MB
nginx latest 41f689c20910 6 weeks ago 192MB
httpd latest 65005131d37e 7 weeks ago 117MB
centos 7 eeb6ee3f44bd 4 years ago 204MB
[root@stw ~]# docker run --name stw -it centos:7 /bin/bash
[root@48a18e33e824 /]#
(2)在容器中创建一个文件
[root@48a18e33e824 /]# mkdir /yyqx
[root@48a18e33e824 /]# ls
anaconda-post.log dev home lib64 mnt proc run srv tmp var
bin etc lib media opt root sbin sys usr yyqx
(3)退出容器后,使用docker commit将容器直接打包成为镜像,新镜像名为centos:v1
[root@48a18e33e824 /]# exit
exit
[root@stw ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
48a18e33e824 centos:7 "/bin/bash" 43 seconds ago Exited (0) 6 seconds ago stw
[root@stw ~]# docker commit stw centosstw:v1
sha256:8afcbcc87f39b44568a22ba6403c402b907cb50577fb735183495884a31460e3
[root@stw ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centosstw v1 8afcbcc87f39 10 seconds ago 204MB
galaxy v1 358cb5259f15 3 hours ago 204MB
nginx latest 41f689c20910 6 weeks ago 192MB
httpd latest 65005131d37e 7 weeks ago 117MB
centos 7 eeb6ee3f44bd 4 years ago 204MB
(4)将新生成的镜像运行成容器,进入容器,查看刚刚创建的目录
[root@stw ~]# docker run -itd --name stw2 centosstw:v1
de44b55d5341e382111556dee14766b57c14501877643aad4fa301e7a41942c4
[root@stw ~]# docker exec -it stw2 /bin/bash
[root@de44b55d5341 /]# ls
anaconda-post.log dev home lib64 mnt proc run srv tmp var
bin etc lib media opt root sbin sys usr yyqx
然而,Docker并不建议用户通过这种方式构建镜像。这是一种手工创建镜像的方式,容易出错,效率低且可重复性弱。更重要的,使用者并不知道镜像是如何创建出来的,里面是否有恶意程序。也就是说无法对镜像进行审计,存在安全隐患。
2、基于本地模版导入
用户可以直接从一个操作系统模板文件导入一个镜像,主要使用 docker [container] import 命令。命令格式为 docker [image] import [OPTIONS] file|URL|-[REPOSITORY[:TAG]] ,
要直接导入一个镜像,可以使用 OpenVZ 提供的模板来创建,或者用其他已导入的镜像模板来创建。OpenVZ 模板的下载地址为 http://openvz.org/Download/templates/precreated
(1)下载了 ubuntu:12.04 的模板压缩包,之后使用以下命令导入即可
[root@stw ~]# docker import ubuntu-12.04-x86-minimal.tar.gz stwbuntu:v1
sha256:73ae18a02dfaef8e492fafd1957b779e51978357e9c8c7402a48aa0f7d654817
[root@stw ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
stwbuntu v1 73ae18a02dfa 9 seconds ago 146MB
centosstw v1 8afcbcc87f39 12 minutes ago 204MB
galaxy v1 358cb5259f15 3 hours ago 204MB
nginx latest 41f689c20910 6 weeks ago 192MB
httpd latest 65005131d37e 7 weeks ago 117MB
centos 7 eeb6ee3f44bd 4 years ago 204MB
3、Dockerfile手动构建(常见方法)
Dockerfile是一个文本文件,其内包含了一条条的指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。有了Dockerfile,当我们需要定制自己额外的需求时,只需在 Dockerfile上添加或者修改指令,重新生成镜像即可,省去了敲命令的麻烦。
1、第一行必须指定,基础镜像信息
FROM centos:7
2、维护者信息(可写可不写,现在一般用LABEL代替)
MAINTAINER stw@example.com
3、镜像操作指令
RUN yum install -y httpd
EXPOSE 80
4、容器启动执行指令
CMD ["/bin/bash"]
CMD [“/usr/sbin/httpd”,“-D”,“FOREGROUND”] //httpd
把构建容器所需要的指令都存放在Dockerfile文件中,这个文件的名字是固定的,不能够更改,再使用docker build命令构建容器, 使用 - t 定义新的镜像名,如果构建镜像的Dockerfile文件不在当前目录下可以使用 - f 指定Dockerfile文件路径,示例如下
[root@docker ~]# docker build -t httpd:cycy /root/ // /root:Dockerfile父目录的名称
dockerfile语法:
5、LABEL指令用于让用户为镜像指定各种元数据(键值对的格式),
LABEL <key>=<value> ````<key>=<value>
6、COPY指令用于复制宿主机上的文件到目标镜像中,
COPY <src>... <dest>
7、ADD指令跟COPY类似,不过它还支持使用tar文件和URL路径。当拷贝的源文件是tar文件时,会自动展开为一个目录并拷贝进新的镜像中;然而通过URL获取到的tar文件不会自动展开。主机可以再联网的情况下,docker build可以将网络上的某文件引用下载并打包到新的镜像中,
ADD <src>... <dest>
8、WORKDIR指令用于指定工作目录,可以指多个,每个WORKDIR只影响他下面的指令,直到遇见下一个WORKDIR为止。WORKDIR也可以调用由ENV指令定义的变量。
WORKDIR 相对路径或者绝对路径 (相当于Linux中的cd)
9、VOLUME指令用于在镜像中创建一个挂载点目录。Volume有两种类型:绑定挂载卷和docker管理的卷。在Dockerfile中只支持Docker管理的卷,也就是说只能指定容器内的路径,不能指定宿主机的路径,
VOLUME <mountpoint>
VOLUME [“<mountpoint>”]
10、EXPOSE指令用于指定容器中待暴露的端口
EXPOSE 80
11、ENV指令用于为镜像定义所需的环境变量(使用docker run启动容器的时候加上-e的参数为variable_name赋值,可以覆盖Dockerfile中ENV指令指定的此variable_name的值)
ENV <key> <value>
ENV <key>=<value> ...
12、RUN指令运行于docker build过程中运行的程序,可以是任何命令。RUN指令后所执行的命令必须在FROM指令后的基础镜像中存在才行
RUN <command>
13、CMD指令用于用户指定启动容器的默认要运行的程序,如果不指定,默认是bash,CMD指令指定的默认程序会被docker run命令行指定的参数所覆盖,Dockerfile中可以存在多个CMD指令,但仅最后一个生效,因为一个Docker容器只能运行一个PID为1的进程。
CMD command param1 param2
CMD [“executable”,“param1”,“param2”]
CMD [“param1”,“param2”]
14、ENTRYPOINT指令类似CMD指令的功能,用于为容器指定默认运行程序。Dockerfile中可以存在多个ENTRYPOINT指令,但仅最后一个生效,与CMD区别在于,由ENTRYPOINT启动的程序不会被docker run命令行指定的参数所覆盖,而且这些命令行参数会被当做参数传递给ENTRYPOINT指令指定的程序
ENTRYPOINT command param1 param2
ENTRYPOINT [“executable”, “param1”, “param2”]
注意:不过,docker run的–entrypoint选项的参数可覆盖ENTRYPOINT指定的默认程序
15、USER用于指定docker build过程中任何RUN、CMD等指令的用户名或者UID。默认情况下容器的运行用户为root
USER <user>[:<group>]
USER <UID>[:<GID>]
案例:下载安装httpd
1、提前将Centos-7.repo、epel-7.repo两个包导入
[root@stw ~]# rz -E
rz waiting to receive.
[root@stw ~]# rz -E
rz waiting to receive.
[root@stw ~]# ls
anaconda-ks.cfg Dockerfile epel-7.repo Pictures ubuntu-12.04-x86-minimal.tar.gz
Centos-7.repo Documents initial-setup-ks.cfg Public Videos
Desktop Downloads Music Templates
2、编写Dockerfile
[root@stw ~]# vim Dockerfile
[root@stw ~]# cat Dockerfile
FROM centos:7
RUN rm -rf /etc/yum.repos.d/*
ADD Centos-7.repo /etc/yum.repos.d/
ADD epel-7.repo /etc/yum.repos.d/
RUN yum -y install httpd
EXPOSE 80
CMD ["/usr/sbin/httpd","-D","FOREGROUND"]
3、使用docker build 命令构建
[root@stw ~]# docker build -t stwhttpd:v1 .
[+] Building 52.9s (10/10) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 230B 0.0s
=> [internal] load metadata for docker.io/library/centos:7 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> CACHED [1/5] FROM docker.io/library/centos:7 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 3.27kB 0.0s
=> [2/5] RUN rm -rf /etc/yum.repos.d/* 1.3s
=> [3/5] ADD Centos-7.repo /etc/yum.repos.d/ 0.1s
=> [4/5] ADD epel-7.repo /etc/yum.repos.d/ 0.1s
=> [5/5] RUN yum -y install httpd 50.1s
=> exporting to image 1.0s
=> => exporting layers 1.0s
=> => writing image sha256:765a412de5175942298396a0b1184f5d55ce53fd85097f80caca6b77014 0.0s
=> => naming to docker.io/library/stwhttpd:v1 0.0s
4、基于镜像运行成容器,测试访问
[root@stw ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
stwhttpd v1 765a412de517 3 minutes ago 535MB
stwbuntu v1 73ae18a02dfa 46 minutes ago 146MB
centosstw v1 8afcbcc87f39 59 minutes ago 204MB
galaxy v1 358cb5259f15 4 hours ago 204MB
nginx latest 41f689c20910 6 weeks ago 192MB
httpd latest 65005131d37e 7 weeks ago 117MB
centos 7 eeb6ee3f44bd 4 years ago 204MB
[root@stw ~]# docker run -itd --name stwhttpd1 -P stwhttpd:v1
913c3b69e446b27b27ffc8a243fa9ba5920471792b8d3391b740bdae0d0976ea
[root@stw ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
913c3b69e446 stwhttpd:v1 "/usr/sbin/httpd -D …" 5 seconds ago Up 3 seconds 0.0.0.0:32768->80/tcp, :::32768->80/tcp stwhttpd1
de44b55d5341 centosstw:v1 "/bin/bash" 58 minutes ago Up 58 minutes stw2

更多推荐


所有评论(0)