Docker镜像制作

1 Docker中的镜像分层

Docker 支持通过扩展现有镜像创建新的镜像。DockerHub 中 99% 的镜像都是通过在base镜像的基础上安装和配置需要的软件所构建出来的。
在这里插入图片描述

1.1 Docker 镜像为什么分层

镜像分层最大的一个好处就是共享资源。
多个镜像均以同一个 base 镜像为基础构建而来,而Docker Host 只需在磁盘上保存一份 base 镜像,同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了,且镜像每一层都可以被共享
如果多个容器共享一份基础镜像,当某个容器修改了基础镜像的内容,比如 /etc 下的文件,这时其他容器的 /etc 是不会被修改的,修改只会被限制在单个容器内,这就是容器 Copy-on-Write 特性。

1.2 可写的容器层

当容器启动时,一个新的可写层被加载到镜像的顶部,这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。
在这里插入图片描述
所有对容器的改动,无论添加、删除还是修改文件都只会发生在容器层中。只有容器层可写的,容器层下面的所有镜像层都是只读的。

1.3 容器层的细节说明

镜像层数量可能会很多,所有镜像层联合在一起组成一个统一的文件系统。如果不同层中有一个相同路径的文件,比如/a上层/a覆盖下层/a,也就是说用户只能访问到上层中的文件/a。在容器层中,用户看到的是一个叠加之后的文件系统
在这里插入图片描述
只有当需要修改时才复制一份数据,这种特性被称作 Copy-on-Write。可见,容器层保存的是镜像变化的部分不会对镜像本身进行任何修改
这样就解释了我们前面提出的问题:容器层记录对镜像的修改,所有镜像层都是只读的,不会被容器修改,所以镜像可以被多个容器共享。

2 制作镜像

2.1 镜像的生成途径

  • 基于容器制作
  • dockerfile & docker build(后面单独讲

2.2 基于容器制作

2.2.1 使用 commit

格式

Usage: docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]

参数

Options:
	-a 作者(例如,“along along@along.com”)
	-c 修改Dockerfile指令应用于创建的镜像
	-m 提交消息(可以理解是注释)
	-p 在提交期间暂停容器(默认为true
2.2.1.2 示例一
[root@johnnyg03 ~]# docker run -it --name b1 busybox:latest /bin/sh
/ # mkdir /data/html -p
/ # echo "hello world" > /data/html/index.html
/ # cat /data/html/index.html 
hello world
[root@johnnyg03 ~]# docker commit -a "johnnyg johnnyg@test.com" -p b1
sha256:0b187f35d8cbe31aa845c2247dd25ee968b45cc20e76a54390904d45e5884a41
[root@johnnyg03 ~]# docker images
REPOSITORY                        TAG       IMAGE ID       CREATED         SIZE
<none>                            <none>    0b187f35d8cb   4 seconds ago   1.24MB   
[root@johnnyg03 ~]# docker tag 0b187f35d8cb johnnyg/busybox:latest
[root@johnnyg03 ~]# docker images
REPOSITORY                        TAG       IMAGE ID       CREATED          SIZE
johnnyg/busybox                   v1    0b187f35d8cb   58 seconds ago   1.24MB
[root@johnnyg03 ~]# docker run -it --name b2 johnnyg/busybox:v1 /bin/sh
/ # ls
bin   data  dev   etc   home  proc  root  sys   tmp   usr   var
/ # cat /data/html/index.html 
hello world
2.2.1.2 示例二
[root@johnnyg03 ~]# docker commit -a "johnnyg <johnnyg@test.com>" -c 'CMD ["/bin/httpd","-f","-h","/data/html"]' -p b1 johnnyg/busybox:v2
[root@johnnyg03 ~]# docker images
REPOSITORY                        TAG       IMAGE ID       CREATED          SIZE
johnnyg/busybox                   v2        6601a1526ad0   6 seconds ago    1.24MB
[root@johnnyg03 ~]# docker run -d --name b3 johnnyg/busybox:v2 
a0e5fc970f34cbe2097a0a57b90f34ce7616285310cf05c48ff61332ac0bf6ec
[root@johnnyg03 ~]# docker inspect b3 | grep IPA
            "SecondaryIPAddresses": null,
            "IPAddress": "172.17.0.4",
                    "IPAMConfig": null,
                    "IPAddress": "172.17.0.4",

[root@johnnyg03 ~]# curl 172.17.0.4
hello world

2.2.2 使用 export 和 import

2.2.2.1 导出(容器转变为镜像文件)

格式

[root@johnnyg03 ~]# docker export --help

Usage:  docker export [OPTIONS] CONTAINER

参数

Options:
	-o 输出(可以用>取代)后面跟路径文件名

演示

[root@johnnyg03 ~]# docker export b1 > docker_image_b1.tar

or

[root@johnnyg03 ~]# docker export b1 -o docker_image_b1.tar
[root@johnnyg03 ~]# ll docker_image_b1.tar 
-rw-r--r-- 1 root root 1467392 Aug 13 17:23 docker_image_b1.tar
2.2.2.2 导入(镜像文件转变为镜像)

格式

[root@johnnyg03 ~]# docker import --help

Usage:  docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]]

参数

Options:
	-c 应用docker 指令创建镜像;
	-m 提交时的说明文字(注释)

演示

[root@johnnyg03 ~]# docker import docker_image_b1.tar johnnyg/busybox:v3
[root@johnnyg03 ~]# docker images
REPOSITORY                        TAG       IMAGE ID       CREATED             SIZE
johnnyg/busybox                   v3        c74a65ab0d71   6 seconds ago       1.24MB
[root@johnnyg03 ~]# docker run -it --name b4 johnnyg/busybox:v3 /bin/sh
/ # ls
bin   data  dev   etc   home  proc  root  sys   tmp   usr   var
/ # cat /data/html/index.html 
hello world

2.2.3 使用 save 和 load

2.2.3.1 保存(镜像转变为镜像文件)

格式

[root@johnnyg03 ~]# docker save --help

Usage:  docker save [OPTIONS] IMAGE [IMAGE...]

参数

Options:
	-o 输出(可以用>取代)后面跟路径文件名
2.2.3.1.1 演示一(保存单镜像)
[root@johnnyg03 ~]# docker save johnnyg/busybox > docker_image_b1_2.tar

or

[root@johnnyg03 ~]# docker save johnnyg/busybox -o docker_image_b1_2.tar
[root@johnnyg03 ~]# ll docker_image_b1_2.tar 
-rw-r--r-- 1 root root 2956288 Aug 13 18:11 docker_image_b1_2.tar
2.2.3.1.1 演示一(保存多镜像)

【注:如果需要load(加载),操作是一样的】

[root@johnnyg03 ~]# docker save busybox:latest nginx:latest > docker_images_busybox_nginx.tar
[1]+  Done                    docker save busybox:latest nginx:latest > docker_images_busybox
[root@johnnyg03 ~]# ll docker_images_busybox_nginx.tar 
-rw-r--r-- 1 root root 147370496 Aug 13 19:11 docker_images_busybox_nginx.tar
2.2.3.2 加载(镜像文件转变为镜像)

格式

[root@johnnyg03 ~]# docker load --help

Usage:  docker load [OPTIONS]

参数

Options:
	-i 指定导入的文件,代替 STDIN(标准输入“<”)
	-q 精简输出信息

演示

[root@johnnyg03 ~]# docker load < docker_image_b1_2.tar

or

[root@johnnyg03 ~]# docker load -i docker_image_b1_2.tar

2.2.4 两种方案的差别

特别注意:两种方法不可混用。
如果使用 import 导入 save 产生的文件,虽然导入不提示错误,但是启动容器时会提示失败,会出现类似"docker: Error response from daemon: Container command not found or does not exist"的错误。

  • 文件大小不同

export 导出的镜像文件体积小于 save 保存的镜像

  • 是否可以对镜像重命名

docker import 可以为镜像指定新名称
docker load 不能对载入的镜像重命名

  • 是否可以同时将多个镜像打包到一个文件中

docker export 不支持
docker save 支持

  • 是否包含镜像历史

export 导出(import 导入)是根据容器拿到的镜像,再导入时会丢失镜像所有的历史记录和元数据信息(即仅保存容器当时的快照状态),所以无法进行回滚操作。
save 保存(load 加载)的镜像,没有丢失镜像的历史,可以回滚到之前的层(layer)。

  • 应用场景不同

docker export 的应用场景:主要用来制作基础镜像,比如我们从一个 ubuntu 镜像启动一个容器,然后安装一些软件和进行一些设置后,使用 docker export 保存为一个基础镜像。然后,把这个镜像分发给其他人使用,比如作为基础的开发环境。
docker save 的应用场景:如果我们的应用是使用 docker-compose.yml 编排的多个镜像组合,但我们要部署的客户服务器并不能连外网。这时就可以使用 docker save 将用到的镜像打个包,然后拷贝到客户服务器上使用 docker load 载入。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值