Docker新手入门——————了解镜像的分层、使用docker commit构建镜像、使用dockerfile构建镜像

1.镜像的分层结构

1)docker容器启动之后是共享宿主机的。

  • 查看当前的docker信息。
[root@docker docker]# docker info # 查看docker信息
………………
WARNING: bridge-nf-call-iptables is disabled # 出现两个错误
WARNING: bridge-nf-call-ip6tables is disabled

[root@docker docker]# sysctl -a | grep bridge # 查看内核有关参数
net.bridge.bridge-nf-call-arptables = 1
net.bridge.bridge-nf-call-ip6tables = 0
net.bridge.bridge-nf-call-iptables = 0
net.bridge.bridge-nf-filter-pppoe-tagged = 0
net.bridge.bridge-nf-filter-vlan-tagged = 0
net.bridge.bridge-nf-pass-vlan-input-dev = 0
[root@docker docker]# cd /etc/sysctl.d/ # 将它写入那个子目录配置文件
[root@docker docker]# vim docker.conf # 建立一个docker文件,表示为docker专门修改的。

inet.bridge.bridge-nf-call-ip6tables = 1 # 写入内容修改为1
net.bridge.bridge-nf-call-iptables = 1
[root@docker docker]# sysctl --system  # 重新加载所有子目录,使其生效。
  • docker所有的数据存放在:尽量不要动
[root@docker sysctl.d]# cd /var/lib/docker
[root@docker docker]# ls
builder  buildkit  containers  image  network  overlay2  plugins  runtimes  swarm  tmp  trust  volumes
  • 测试是共享内核:
[root@docker docker]# docker pull ubuntu # 利用阿里云镜像加速器拉取ubuntu
Using default tag: latest
latest: Pulling from library/ubuntu
54ee1f796a1e: Pull complete 
f7bfea53ad12: Pull complete 
46d371e02073: Pull complete 
b66c17bbf772: Pull complete 
Digest: sha256:31dfb10d52ce76c5ca0aa19d10b3e6424b830729e32a89a7c6eee2cda2be67a5
Status: Downloaded newer image for ubuntu:latest
[root@docker docker]# docker images  
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              latest              4e2eef94cd6b        2 weeks ago         73.9MB
game2048            latest              19299002fdbe        3 years ago         55.5MB
[root@docker docker]# docker run -it --name ubuntu-vm1 ubuntu # 使用交互式运行容器,运行很快秒级的启动
root@e2f653224e43:/# ls
bin   dev  home  lib32  libx32  mnt  proc  run   srv  tmp  var
boot  etc  lib   lib64  media   opt  root  sbin  sys  usr
root@e2f653224e43:/# uname -r # 查看内核版本与宿主机相同,可以证明。
3.10.0-862.el7.x86_64

2)base镜像提供最小的linux发行版:

[root@docker docker]# docker run -it --name ubuntu-vm1 ubuntu
root@e2f653224e43:/# ls
bin   dev  home  lib32  libx32  mnt  proc  run   srv  tmp  var
boot  etc  lib   lib64  media   opt  root  sbin  sys  usr

3)统一docker主机支持运行多种linux发行版本。用户可以根据自己的需求添加自己的分层。

4)采用分层结构最大的好处是:共享资源

5)容器层可以写:linux内核的Copy-on-Write,当需要对底下的层做修改的时候,其实是复制上去容器层,再修改。

root@e2f653224e43:/# touch file1
root@e2f653224e43:/# touch file2
root@e2f653224e43:/# ls
bin   dev  file1  home  lib32  libx32  mnt  proc  run   srv  tmp  var
boot  etc  file2  lib   lib64  media   opt  root  sbin  sys  usr

6)容器层以下的所有镜像层都是只读。

7)docker从上往下依次查找文件,先看容器层,再看镜像层。

8)容器层保存镜像的变化部分,并不会对镜像本身进行任何修改。

9)一个镜像最多127层镜像。越小的镜像,分发部署的时候越快。

2. 镜像的构建docker commit

2.1 修改后不保存就会消失

1)修改一个容器,直接退出:

root@e2f653224e43:/# touch file1
root@e2f653224e43:/# touch file2
root@e2f653224e43:/# ls
bin   dev  file1  home  lib32  libx32  mnt  proc  run   srv  tmp  var
boot  etc  file2  lib   lib64  media   opt  root  sbin  sys  usr
root@e2f653224e43:/# exit
exit

2)查看运行的docker容器:

[root@docker docker]# docker ps # 没有运行
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                         NAMES
[root@docker docker]# docker ps -a # 但依旧存在
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS                         NAMES
e2f653224e43        ubuntu              "/bin/bash"              15 minutes ago      Exited (0) 40 seconds ago                                 ubuntu-vm1

3)删除这个容器:

[root@docker docker]# docker rm ubuntu-vm1
ubuntu-vm1

4)再次开启一个容器:之前容器层的内容消失

[root@docker docker]# docker run -it --name ubuntu-vm1 ubunturoot@322f01e0b31c:/# ls
bin   dev  home  lib32  libx32  mnt  proc  run   srv  tmp  var
boot  etc  lib   lib64  media   opt  root  sbin  sys  usr

5)查看镜像的构建历史:

[root@docker docker]# docker history ubuntu:latest 
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
4e2eef94cd6b        2 weeks ago         /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B                  
<missing>           2 weeks ago         /bin/sh -c mkdir -p /run/systemd && echo 'do…   7B                  
<missing>           2 weeks ago         /bin/sh -c set -xe   && echo '#!/bin/sh' > /811B                
<missing>           2 weeks ago         /bin/sh -c [ -z "$(apt-get indextargets)" ]     1.01MB              
<missing>           2 weeks ago         /bin/sh -c #(nop) ADD file:9f937f4889e7bf646…   72.9MB

2.1 修改保存构建新的镜像

无法审计,有风险:

1)拉取一个busybox(最简化的文件系统):

[root@docker docker]# docker pull busybox
Using default tag: latest
latest: Pulling from library/busybox
9c075fe2c773: Pull complete 
Digest: sha256:c3dbcbbf6261c620d133312aee9e858b45e1b686efbcead7b34d9aae58a37378
Status: Downloaded newer image for busybox:latest

2)运行新的测试容器:新建一个文件new,写入testfile。然后退出

[root@docker docker]# docker run -it --name test busybox
/ # ls
bin   dev   etc   home  proc  root  sys   tmp   usr   var
/ # vi new
/ # cat new 
testfile
/ # exit
[root@docker docker]#

3)查看docker容器:

[root@docker docker]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                         NAMES
[root@docker docker]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                          PORTS                         NAMES
bfe78caf4cb7        busybox             "sh"                     3 minutes ago       Exited (0) About a minute ago                                 test
[root@docker docker]# docker start test
test
[root@docker docker]# docker attach test
/ # ls
bin   dev   etc   home  new   proc  root  sys   tmp   usr   var
/ #

4)使用Ctrl+d直接退出停止运行;使用Ctrl+pq退出再后台继续运行。

[root@docker ~]# docker attach test 
/ # ls
bin   dev   etc   home  new   proc  root  sys   tmp   usr   var
/ # read escape sequence # 使用Ctrl+pq退出
[root@docker ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
bfe78caf4cb7        busybox             "sh"                5 hours ago         Up 40 seconds

5)将修改的容器进行保存提交:

[root@docker ~]# docker commit test test:v1
sha256:551c5d30e56de2bb177a0906b63fab993073c444d4a14465fbf7eff2c008aa60
[root@docker ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
test                v1                  551c5d30e56d        10 seconds ago      1.22MB

6)这是基于busybox,查看:在容器里做的操作,都看不出来,所以无法审计。

[root@docker ~]# docker history test:v1
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
551c5d30e56d        3 minutes ago       sh                                              36B                 
edabd795951a        6 days ago          /bin/sh -c #(nop)  CMD ["sh"]                   0B                  
<missing>           6 days ago          /bin/sh -c #(nop) ADD file:4e5169fa630e0afed…   1.22MB

[root@docker ~]# docker history busybox:latest 
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
edabd795951a        6 days ago          /bin/sh -c #(nop)  CMD ["sh"]                   0B                  
<missing>           6 days ago          /bin/sh -c #(nop) ADD file:4e5169fa630e0afed…   1.22MB

7)强制删除运行的容器:正再运行的镜像无法删除,做一强制删除。

[root@docker ~]# docker rm test
Error response from daemon: You cannot remove a running container bfe78caf4cb7170d0f9a5c283af1cede83b66b543504d1c24463657fd66322ac. Stop the container before attempting removal or force remove
[root@docker ~]# docker rm -f test
test
[root@docker ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                     PORTS               NAMES
4cf56480c371        game2048            "/bin/sh -c 'sed -i …"   6 hours ago         Exited (137) 2 hours ago                       game1

8)通过新打包的镜像建立一个容器:这个容器中就有之前建立的测试文件。

[root@docker ~]# docker run -it --name vm1 test:v1 
/ # ls
bin   dev   etc   home  new   proc  root  sys   tmp   usr   var
/ # cat new
testfile
/ # 

3. 通过镜像文件构建镜像 dockerfile

  • 可以审计+自动化。
  • 具有缓存特性。

3.1 可审计

1)新建一个目录用来编写docker文件:如果在根目录下建立文件,会将很目录下的所有内容进行封装。

[root@docker ~]# mkdir dockerfile
[root@docker ~]# cd dockerfile/
[root@docker dockerfile]# vim dockerfile

2)写入文件内容:

FROM busybox # 通过哪个镜像作为基础
RUN echo testfile >file1 # 所执行的动作1
RUN echo testfile >file2 # 所执行的动作2

3)构建镜像:song:v1(如果使用/作为dockerfile的目录,他会将根下的所有文件发送给docker引擎)

[root@docker dockerfile]# docker build -t song:v1 .
# 将本地目录下的所有文件发送给docker引擎。
Sending build context to Docker daemon  2.048kB
Step 1/3 : FROM busybox
 ---> edabd795951a
Step 2/3 : RUN echo testfile >file1
 ---> Running in 515c3990e5b1 # 生成容器
Removing intermediate container 515c3990e5b1 # 删除容器
 ---> 1ce32b0d2fc7 # 生成的镜像层
Step 3/3 : RUN echo testfile >file2
 ---> Running in 10c5523481ac # 生成容器
Removing intermediate container 10c5523481ac # 删除容器
 ---> 26ef12576bbc # 生成的镜像层
Successfully built 26ef12576bbc
Successfully tagged song:v1

4)查看镜像层:有审计可以看到做了什么。

[root@docker dockerfile]# docker history song:v1 
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
26ef12576bbc        3 minutes ago       /bin/sh -c echo testfile >file2                 9B                  
1ce32b0d2fc7        3 minutes ago       /bin/sh -c echo testfile >file1                 9B                  
edabd795951a        6 days ago          /bin/sh -c #(nop)  CMD ["sh"]                   0B                  
<missing>           6 days ago          /bin/sh -c #(nop) ADD file:4e5169fa630e0afed…   1.22MB 

3.2 有缓存

1)修改dockerfile:使用缓存特性,之前的设定一点点都不能改

[root@docker dockerfile]# vim dockerfile
FROM busybox
RUN echo testfile >file1
RUN echo testfile >file2
RUN echo testfile >file3

2)构建镜像:

[root@docker dockerfile]# docker build -t song:v2 .
Sending build context to Docker daemon  2.048kB
Step 1/4 : FROM busybox
 ---> edabd795951a
Step 2/4 : RUN echo testfile >file1
 ---> Using cache # 使用缓存
 ---> 1ce32b0d2fc7
Step 3/4 : RUN echo testfile >file2
 ---> Using cache # 使用缓存
 ---> 26ef12576bbc
Step 4/4 : RUN echo testfile >file3
 ---> Running in 8778c3b1ef49 # 只有第三个新建容器
Removing intermediate container 8778c3b1ef49 # 删除容器
 ---> dc518b689204 # 构建镜像层
Successfully built dc518b689204
Successfully tagged song:v2

3)查看镜像层:file1和file2都是共享的层,只有file3是v2独有的层。

[root@docker dockerfile]# docker history song:v2 
IMAGE               CREATED              CREATED BY                                      SIZE                COMMENT
dc518b689204        About a minute ago   /bin/sh -c echo testfile >file3                 9B                  
26ef12576bbc        8 minutes ago        /bin/sh -c echo testfile >file2                 9B                  
1ce32b0d2fc7        8 minutes ago        /bin/sh -c echo testfile >file1                 9B                  
edabd795951a        6 days ago           /bin/sh -c #(nop)  CMD ["sh"]                   0B                  
<missing>           6 days ago           /bin/sh -c #(nop) ADD file:4e5169fa630e0afed…   1.22MB              
[root@docker dockerfile]# docker history song:v1 
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
26ef12576bbc        8 minutes ago       /bin/sh -c echo testfile >file2                 9B                  
1ce32b0d2fc7        8 minutes ago       /bin/sh -c echo testfile >file1                 9B                  
edabd795951a        6 days ago          /bin/sh -c #(nop)  CMD ["sh"]                   0B                  
<missing>           6 days ago          /bin/sh -c #(nop) ADD file:4e5169fa630e0afed…   1.22MB

总结:

  • 最好使用dockerfile构建镜像。有审计+缓存内容。
  • dockerfile的每一步都是使用docker commit来形成的。
  • docker commit,无法审计。

版权声明:本文为mango_kid原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。