xiaohanliang
Docker
Docker
  • hi
  • STORAGE DRIVER
    • 1. 什么叫联合挂载
    • 2. 镜像ID是从哪来的
    • 3. 如何组装出一个镜像
    • 4. 为什么有这么多fs@aufs
    • 5. 为什么有这么多fs@overlay
    • 6. 为什么有这么多fs@dm
    • 7. 正确安装devicemapper
  • EXEC DRIVER
    • 1. 资源限制-cgroup
    • 2. 制造小型监狱
    • 3. 切换根目录是什么概念
    • 4. 标准极简容器runC
    • 5. 尝试安装runc工具
  • KUBERNETES NETWORK
    • 0. [WIP]我想串联容器网络的故事
    • 1. 容器网络是什么样的网络
    • 2. cnm认为应该怎样让容器组网
    • 3. 为什么会有一大堆cni插件
    • 4. 为什么要设计出pod
    • 5. 怎样形成一个服务
    • 6. Service就是iptables规则
    • 7. IPVS也能实现Service
    • 8. 从集群外访问服务-nodeport
    • 9. 从集群外访问服务-ingress
    • 10. 想要把域名变成IP
    • 11. DNS是怎么实现的
    • 12. 最常见的方案@flannel
    • 13. 使用tun设备封包@flannel
    • 14. 使用vxlan设备封包@flannel
    • 15. 可不可以不封包@flannel
Powered by GitBook
On this page
  • 准备工作
  • 镜像ID是怎么决定的
  • 那么顶层的ID又是怎么计算出来的呢?

Was this helpful?

  1. STORAGE DRIVER

2. 镜像ID是从哪来的

准备工作

这句话好像被说过无数次了, 以至于所有人都知道镜像的确是分层的, 在上面一节我们说了多层镜像是如何merge成一个统一的目录结构. 这一节我们再由顶向下看看实际操作中镜像是怎么玩的. 首先我们将Docker的文件系统 (从默认的overlay2) 切换成传统的 aufs 模式:

# 确认一下你的系统是否支持aufs挂载模式
$ grep aufs /proc/filesystems
nodev   aufs

# 指定Docker使用aufs模式启动
$ echo '{"storage-driver": "aufs"}' > /etc/docker/daemon.json

# 重启Docker
$ systemctl restart docker

# 检查Docker是不是按照aufs模式挂载
$ docker info | grep aufs
Storage Driver:  aufs
Root Dir:        /var/lib/docker/aufs

# 拉个镜像当示例, 我们选择最简单的busybox
$ docker pull busybox

下面开始整活👇

镜像ID是怎么决定的

提前说一下, 本节会涉及一大堆镜像层ID, 看起来会比较蛋疼

# 拿到镜像ID
$ docker images
REPOSITORY          TAG              IMAGE ID           SIZE
busybox             latest           f0b02e9d092d       1.23MB

# 检查镜像层级结构
$ docker history busybox:latest
IMAGE               CREATED BY                             SIZE
f0b02e9d092d        /bin/sh -c #(nop)  CMD ["sh"]          0B
ef4da5b60185        /bin/sh -c #(nop) ADD file:6098…       1.23MB

#
#         busybox:latest # f09
#                  |-- 顶层 # f09 由dockerfile中的 CMD 命令生成
#                  `-- 底层 # ef4 由dockerfile中的 ADD 命令生成
#

这回搞真的了, 我们看看docker是怎么玩的, 我们可以看到这个镜像分成两层, 其中顶层的ID被拿来当成镜像ID, 换句话说, 如果我们制造一个镜像, 我们就拿它顶层的ID当做镜像ID, 验证一下:

# 因为dockerfile里有"CMD", 因此即使不指定命令, 也按照"sh"运行
$ docker run busybox:latest

# 现在把刚刚跑起来的容器, 以commit的方式制作成镜像
$ docker commit 9c2376480769 xiaohan-building:latest
sha256:f6f28010e18c8853a38cf5889cbeabd5d3a15e42aa0bef1d1b769358780d36f0

# 看看新生成的 xiaohan-building 镜像, 镜像ID为f6f
$ docker images
REPOSITORY          TAG      IMAGE ID      SIZE
xiaohan-building    latest   f6f28010e18c  1.23MB

# 果然, 顶层ID被拿来当成镜像ID了
$ docker history
IMAGE               CREATED BY                        SIZE
f6f28010e18c        sh                                0B
f0b02e9d092d        /bin/sh -c #(nop)  CMD ["sh"]     0B
<missing>           /bin/sh -c #(nop) ADD file:609…   1.23MB

那么顶层的ID又是怎么计算出来的呢?

# 通过保存 / 解压的方式拿到镜像的详细数据
$ docker save -o xiaohan-image.tar xiaohan-building:latest
$ tar -xvf xiaohan-image.tar

# 看看出来了
$ cat f6f.json | sha256sum
f6f28010e18c8853a38cf5889cbeabd5d3a15e42aa0bef1d1b769358780d36f0  -

# 这个f6f.json是什么鬼畜
$ cat f6f.json | jq -M
{
  "architecture": "amd64",
  "config": {
    "Hostname": "9c2376480769",
    "Env": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],
  }
  ...
}

懂了, f6f 就是这个镜像的参数, 一个大json, 然后我们把这个json经过sha256计算就能拿到这一层的镜像ID, 因为每个镜像参数是唯一的, 因此sha256 → 镜像层ID一定是唯一的

# 镜像的所有内容现在都会存在这里, 我们进去看看都有啥 
$ cd /var/lib/docker/aufs && ls
diff  layers  mnt

$ ls diff
Previous1. 什么叫联合挂载Next3. 如何组装出一个镜像

Last updated 4 years ago

Was this helpful?