Docker Image执行流程
Container本来也不是什么新技术,为什么Docker就火了,而前辈们如lxc、OpenVZ等没这么火。其实一部分原因得益于Docker的Image管理。Docker借鉴了vm的方式,让用户像管理vm一样的管理他们的container镜像,并且也同样叫做Image。在实现上,Docker利用container的Rootfs是从host上挂载的、并且能挂载多个目录这个特点,将Docker Image分成多个小块(这是按照vm Image的思维来说的,实际上这多个小块,每个都是一个Image,最终使用的是一个Image组合),方便管理与共享。
我们已经了解了Container是什么,那么Image是怎么转换为Container的Rootfs的?Image本身是怎么在磁盘上存储的?带着这些疑问,我们一起来看看Docker的实现。
磁盘上的image
先来看看磁盘中存储的image是什么样子的,这里以aufs为例,devicemapper的存储形式和aufs还不太一样,后续有空再来分析。
现在我们有一个image:
- ubuntu@ubuntu:~$ sudo docker images
- [sudo] password for ubuntu:
- REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
- ubuntu-12.04 latest 212e4aaf49e7 25 minutes ago 172.7 MB
对应的/var/lib/docker目录下就有这些东西:
- ubuntu@ubuntu:~$ sudo ls -lh /var/lib/docker
- total 48K
- drwxr-xr-x 2 root root 4.0K Apr 16 22:26 apparmor
- drwxr-xr-x 5 root root 4.0K Jun 21 16:14 aufs
- drwx------ 3 root root 4.0K Jun 22 13:01 containers
- drwx------ 5 root root 4.0K Jun 22 12:59 devicemapper
- drwx------ 3 root root 4.0K Apr 16 22:16 execdriver
- drwx------ 6 root root 4.0K Jul 13 11:32 graph
- drwx------ 2 root root 4.0K Jul 13 11:40 init
- -rw-r--r-- 1 root root 5.0K Jun 22 13:01 linkgraph.db
- -rw------- 1 root root 111 Jul 13 11:32 repositories-aufs
- -rw------- 1 root root 180 Apr 16 22:56 repositories-devicemapper
- drwx------ 2 root root 4.0K Apr 16 22:16 volumes<span style="letter-spacing: 0px; color: rgb(68, 68, 68); font-family: Baskerville;"> </span>
抛开其他的不管,现在只关心里面的aufs, graph目录和repositories-aufs文件(如果是devicemapper,则是devicemapper目录和repositories-devicemapper文件,graph为共用的目录)。
aufs目录的结构如下:
- ubuntu@ubuntu:~$ sudo tree /var/lib/docker/aufs -L 3
- /var/lib/docker/aufs
- |-- diff
- | `-- 212e4aaf49e7cde3c280d05f1a6bd74ecf66ad83917fa757137deb0dae82806d
- | |-- bin
- | |-- boot
- | |-- dev
- | |-- etc
- | |-- home
- | |-- lib
- | |-- lib64
- | |-- media
- | |-- mnt
- | |-- opt
- | |-- proc
- | |-- root
- | |-- run
- | |-- sbin
- | |-- selinux
- | |-- srv
- | |-- sys
- | |-- tmp
- | |-- usr
- | `-- var
- |-- layers
- | `-- 212e4aaf49e7cde3c280d05f1a6bd74ecf66ad83917fa757137deb0dae82806d
- `-- mnt
- `-- 212e4aaf49e7cde3c280d05f1a6bd74ecf66ad83917fa757137deb0dae82806d
layers目录和mnt目录里面目前还只有一个空目录,后面再来看。这里主要是diff目录下对应image的目录,image内部的所有文件都在这。
而graph目录的结构如下:
- ubuntu@ubuntu:~$ sudo tree /var/lib/docker/graph -L 3
- /var/lib/docker/graph
- |-- 212e4aaf49e7cde3c280d05f1a6bd74ecf66ad83917fa757137deb0dae82806d
- | |-- json
- | `-- layersize
- |-- 317c1f4475ad860bdcf0e529fd03f181b2c6b64e5b78358051efc94c8f728cd7
- | |-- json
- | `-- layersize
- |-- bcd86fdd0ba0b84f10f4539f99e8730958fc1028d35495f8dd11ae1913370e42
- | |-- json
- | `-- layersize
- `-- _tmp
这里只看212e这个image,另外两个image其实是devicemapper下的image,所有image的描述都放在graph目录下。json文件为image的描述文件,主要是创建这个image的container配置信息,layersize文件内为该image的大小。
最后看看repositories-aufs文件:
- ubuntu@ubuntu:~$ sudo cat /var/lib/docker/repositories-aufs |python -m json.tool
- {
- "Repositories": {
- "ubuntu-12.04": {
- "latest": "212e4aaf49e7cde3c280d05f1a6bd74ecf66ad83917fa757137deb0dae82806d"
- }
- }
- }
其实就是描述在aufs模式下有哪些image可用。
了解了image包括哪些东西,接下来再看看这些东西是怎么用的。
从Image到Container
当我们通过命令行docker run创建一个container并运行时,其中就经历了从image到container rootfs的转化,蓝图如下(省略了其他操作):
上图横轴为执行流程,纵轴是对每个过程的解释。
因为docker run命令实际的执行主要分两步:create和start。在create过程中,主要是将image挂载到/var/lib/docker/aufs/mnt/:id-init目录 (:id为container id),并且取消掉对某些文件/文件夹的挂载,重新创建一份新的。这里的文件/文件夹主要为:
- "/dev/pts": "dir",
- "/dev/shm": "dir",
- "/proc": "dir",
- "/sys": "dir",
- "/.dockerinit": "file",
- "/.dockerenv": "file",
- "/etc/resolv.conf": "file",
- "/etc/hosts": "file",
- "/etc/hostname": "file",
- "/dev/console": "file",
- "/etc/mtab": "/proc/mounts",
然后在start流程中,主要是生成container真正的rootfs目录/var/lib/docker/aufs/mnt/:id, 然后又将几个/host上的目录挂载到rootfs,主要是 /etc/hosts, /etc/hostname, /etc/resolv.conf等。
(其实这里没看明白为啥这几个文件要这样处理,也没看明白为什么要用:id-init目录隔一层。主要是对aufs不熟悉,后面再学习一下。)
现在来看看,当我们创建了一个container后,aufs目录有什么变化:
- ubuntu@ubuntu:~$ sudo tree -L 3 /var/lib/docker/aufs
- [sudo] password for ubuntu:
- /var/lib/docker/aufs
- |-- diff
- | |-- 09b1be94a4444076375b7cb386609990622a1746802858ea85f1de607c1e5167
- | |-- 09b1be94a4444076375b7cb386609990622a1746802858ea85f1de607c1e5167-init
- | | |-- dev
- | | `-- etc
- | `-- 212e4aaf49e7cde3c280d05f1a6bd74ecf66ad83917fa757137deb0dae82806d
- | |-- bin
- | |-- boot
- | |-- dev
- | |-- etc
- | |-- home
- | |-- lib
- | |-- lib64
- | |-- media
- | |-- mnt
- | |-- opt
- | |-- proc
- | |-- root
- | |-- run
- | |-- sbin
- | |-- selinux
- | |-- srv
- | |-- sys
- | |-- tmp
- | |-- usr
- | `-- var
- |-- layers
- | |-- 09b1be94a4444076375b7cb386609990622a1746802858ea85f1de607c1e5167
- | |-- 09b1be94a4444076375b7cb386609990622a1746802858ea85f1de607c1e5167-init
- | `-- 212e4aaf49e7cde3c280d05f1a6bd74ecf66ad83917fa757137deb0dae82806d
- `-- mnt
- |-- 09b1be94a4444076375b7cb386609990622a1746802858ea85f1de607c1e5167
- | |-- bin
- | |-- boot
- | |-- dev
- | |-- etc
- | |-- home
- | |-- lib
- | |-- lib64
- | |-- media
- | |-- mnt
- | |-- opt
- | |-- proc
- | |-- root
- | |-- run
- | |-- sbin
- | |-- selinux
- | |-- srv
- | |-- sys
- | |-- tmp
- | |-- usr
- | `-- var
- |-- 09b1be94a4444076375b7cb386609990622a1746802858ea85f1de607c1e5167-init
- `-- 212e4aaf49e7cde3c280d05f1a6bd74ecf66ad83917fa757137deb0dae82806d
这里创建了一个id为09b1的container,其中/aufs/mnt/09b1xxx 为rootfs, /aufs/layers目录下的文件,主要存储image的parents image id。
小结
Docker的image管理涉及到不少linux文件系统使用的细节,对linux文件系统掌握得不深的话,这部分就只能看个大概的流程。而且这只是其中的aufs部分,其他的devicemapper、btrfs、vfs部分的都不太一样。下来先补习一下linux文件系统知识,再回过头来看看docker的image管理,可能会稍微轻松些。
Container本来也不是什么新技术,为什么Docker就火了,而前辈们如lxc、OpenVZ等没这么火。其实一部分原因得益于Docker的Image管理。Docker借鉴了vm的方式,让用户像管理vm一样的管理他们的container镜像,并且也同样叫做Image。在实现上,Docker利用container的Rootfs是从host上挂载的、并且能挂载多个目录这个特点,将Docker Image分成多个小块(这是按照vm Image的思维来说的,实际上这多个小块,每个都是一个Image,最终使用的是一个Image组合),方便管理与共享。
我们已经了解了Container是什么,那么Image是怎么转换为Container的Rootfs的?Image本身是怎么在磁盘上存储的?带着这些疑问,我们一起来看看Docker的实现。
磁盘上的image
先来看看磁盘中存储的image是什么样子的,这里以aufs为例,devicemapper的存储形式和aufs还不太一样,后续有空再来分析。
现在我们有一个image:
- ubuntu@ubuntu:~$ sudo docker images
- [sudo] password for ubuntu:
- REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
- ubuntu-12.04 latest 212e4aaf49e7 25 minutes ago 172.7 MB
对应的/var/lib/docker目录下就有这些东西:
- ubuntu@ubuntu:~$ sudo ls -lh /var/lib/docker
- total 48K
- drwxr-xr-x 2 root root 4.0K Apr 16 22:26 apparmor
- drwxr-xr-x 5 root root 4.0K Jun 21 16:14 aufs
- drwx------ 3 root root 4.0K Jun 22 13:01 containers
- drwx------ 5 root root 4.0K Jun 22 12:59 devicemapper
- drwx------ 3 root root 4.0K Apr 16 22:16 execdriver
- drwx------ 6 root root 4.0K Jul 13 11:32 graph
- drwx------ 2 root root 4.0K Jul 13 11:40 init
- -rw-r--r-- 1 root root 5.0K Jun 22 13:01 linkgraph.db
- -rw------- 1 root root 111 Jul 13 11:32 repositories-aufs
- -rw------- 1 root root 180 Apr 16 22:56 repositories-devicemapper
- drwx------ 2 root root 4.0K Apr 16 22:16 volumes<span style="letter-spacing: 0px; color: rgb(68, 68, 68); font-family: Baskerville;"> </span>
抛开其他的不管,现在只关心里面的aufs, graph目录和repositories-aufs文件(如果是devicemapper,则是devicemapper目录和repositories-devicemapper文件,graph为共用的目录)。
aufs目录的结构如下:
- ubuntu@ubuntu:~$ sudo tree /var/lib/docker/aufs -L 3
- /var/lib/docker/aufs
- |-- diff
- | `-- 212e4aaf49e7cde3c280d05f1a6bd74ecf66ad83917fa757137deb0dae82806d
- | |-- bin
- | |-- boot
- | |-- dev
- | |-- etc
- | |-- home
- | |-- lib
- | |-- lib64
- | |-- media
- | |-- mnt
- | |-- opt
- | |-- proc
- | |-- root
- | |-- run
- | |-- sbin
- | |-- selinux
- | |-- srv
- | |-- sys
- | |-- tmp
- | |-- usr
- | `-- var
- |-- layers
- | `-- 212e4aaf49e7cde3c280d05f1a6bd74ecf66ad83917fa757137deb0dae82806d
- `-- mnt
- `-- 212e4aaf49e7cde3c280d05f1a6bd74ecf66ad83917fa757137deb0dae82806d
layers目录和mnt目录里面目前还只有一个空目录,后面再来看。这里主要是diff目录下对应image的目录,image内部的所有文件都在这。
而graph目录的结构如下:
- ubuntu@ubuntu:~$ sudo tree /var/lib/docker/graph -L 3
- /var/lib/docker/graph
- |-- 212e4aaf49e7cde3c280d05f1a6bd74ecf66ad83917fa757137deb0dae82806d
- | |-- json
- | `-- layersize
- |-- 317c1f4475ad860bdcf0e529fd03f181b2c6b64e5b78358051efc94c8f728cd7
- | |-- json
- | `-- layersize
- |-- bcd86fdd0ba0b84f10f4539f99e8730958fc1028d35495f8dd11ae1913370e42
- | |-- json
- | `-- layersize
- `-- _tmp
这里只看212e这个image,另外两个image其实是devicemapper下的image,所有image的描述都放在graph目录下。json文件为image的描述文件,主要是创建这个image的container配置信息,layersize文件内为该image的大小。
最后看看repositories-aufs文件:
- ubuntu@ubuntu:~$ sudo cat /var/lib/docker/repositories-aufs |python -m json.tool
- {
- "Repositories": {
- "ubuntu-12.04": {
- "latest": "212e4aaf49e7cde3c280d05f1a6bd74ecf66ad83917fa757137deb0dae82806d"
- }
- }
- }
其实就是描述在aufs模式下有哪些image可用。
了解了image包括哪些东西,接下来再看看这些东西是怎么用的。
从Image到Container
当我们通过命令行docker run创建一个container并运行时,其中就经历了从image到container rootfs的转化,蓝图如下(省略了其他操作):
上图横轴为执行流程,纵轴是对每个过程的解释。
因为docker run命令实际的执行主要分两步:create和start。在create过程中,主要是将image挂载到/var/lib/docker/aufs/mnt/:id-init目录 (:id为container id),并且取消掉对某些文件/文件夹的挂载,重新创建一份新的。这里的文件/文件夹主要为:
- "/dev/pts": "dir",
- "/dev/shm": "dir",
- "/proc": "dir",
- "/sys": "dir",
- "/.dockerinit": "file",
- "/.dockerenv": "file",
- "/etc/resolv.conf": "file",
- "/etc/hosts": "file",
- "/etc/hostname": "file",
- "/dev/console": "file",
- "/etc/mtab": "/proc/mounts",
然后在start流程中,主要是生成container真正的rootfs目录/var/lib/docker/aufs/mnt/:id, 然后又将几个/host上的目录挂载到rootfs,主要是 /etc/hosts, /etc/hostname, /etc/resolv.conf等。
(其实这里没看明白为啥这几个文件要这样处理,也没看明白为什么要用:id-init目录隔一层。主要是对aufs不熟悉,后面再学习一下。)
现在来看看,当我们创建了一个container后,aufs目录有什么变化:
- ubuntu@ubuntu:~$ sudo tree -L 3 /var/lib/docker/aufs
- [sudo] password for ubuntu:
- /var/lib/docker/aufs
- |-- diff
- | |-- 09b1be94a4444076375b7cb386609990622a1746802858ea85f1de607c1e5167
- | |-- 09b1be94a4444076375b7cb386609990622a1746802858ea85f1de607c1e5167-init
- | | |-- dev
- | | `-- etc
- | `-- 212e4aaf49e7cde3c280d05f1a6bd74ecf66ad83917fa757137deb0dae82806d
- | |-- bin
- | |-- boot
- | |-- dev
- | |-- etc
- | |-- home
- | |-- lib
- | |-- lib64
- | |-- media
- | |-- mnt
- | |-- opt
- | |-- proc
- | |-- root
- | |-- run
- | |-- sbin
- | |-- selinux
- | |-- srv
- | |-- sys
- | |-- tmp
- | |-- usr
- | `-- var
- |-- layers
- | |-- 09b1be94a4444076375b7cb386609990622a1746802858ea85f1de607c1e5167
- | |-- 09b1be94a4444076375b7cb386609990622a1746802858ea85f1de607c1e5167-init
- | `-- 212e4aaf49e7cde3c280d05f1a6bd74ecf66ad83917fa757137deb0dae82806d
- `-- mnt
- |-- 09b1be94a4444076375b7cb386609990622a1746802858ea85f1de607c1e5167
- | |-- bin
- | |-- boot
- | |-- dev
- | |-- etc
- | |-- home
- | |-- lib
- | |-- lib64
- | |-- media
- | |-- mnt
- | |-- opt
- | |-- proc
- | |-- root
- | |-- run
- | |-- sbin
- | |-- selinux
- | |-- srv
- | |-- sys
- | |-- tmp
- | |-- usr
- | `-- var
- |-- 09b1be94a4444076375b7cb386609990622a1746802858ea85f1de607c1e5167-init
- `-- 212e4aaf49e7cde3c280d05f1a6bd74ecf66ad83917fa757137deb0dae82806d
这里创建了一个id为09b1的container,其中/aufs/mnt/09b1xxx 为rootfs, /aufs/layers目录下的文件,主要存储image的parents image id。
小结
Docker的image管理涉及到不少linux文件系统使用的细节,对linux文件系统掌握得不深的话,这部分就只能看个大概的流程。而且这只是其中的aufs部分,其他的devicemapper、btrfs、vfs部分的都不太一样。下来先补习一下linux文件系统知识,再回过头来看看docker的image管理,可能会稍微轻松些。
Docker Image执行流程相关推荐
- 追源索骥:透过源码看懂Flink核心框架的执行流程
https://www.cnblogs.com/bethunebtj/p/9168274.html 追源索骥:透过源码看懂Flink核心框架的执行流程 前言 1.从 Hello,World WordC ...
- 步步深入MySQL:架构-gt;查询执行流程-gt;SQL解析顺序!
一.前言 本文将从MySQL总体架构--->查询执行流程--->语句执行顺序来探讨一下其中的知识. 二.MySQL架构总览 架构最好看图,再配上必要的说明文字. 下图根据参考书籍中一图为原 ...
- 追源索骥:透过源码看懂Flink核心框架的执行流程--来自GitHub
追源索骥:透过源码看懂Flink核心框架的执行流程 联系qq2499496272可进行删除,需要文件版本的私聊!!~ 文章目录 追源索骥:透过源码看懂Flink核心框架的执行流程 前言 1.从 ~~H ...
- docker技术学习流程
docker安装 安装docker(乌班图)-需要su权限 官网: Install Docker Engine on Ubuntu | Docker Documentation 帮助文档: 1.卸载旧 ...
- Mysql复习计划(一)- 字符集、文件系统和SQL执行流程
Mysql复习计划(一)- 字符集.文件系统和SQL执行流程 前言 一. Mysql字符集 1.1 Mysql5.7和8.0的默认字符集 1.1.1 修改默认的字符集 1.1.2 修改已有库表的字符集 ...
- Docker的RUN流程和Docker原理、Docker的常用命令、其他命令
Docker的RUN流程和Docker原理 Run流程 底层原理 Docker是怎么工作的 Docker为什么比VM快 Docker的常用命令 帮助命令 镜像命令 查看镜像 搜索镜像 下载镜像 指定版 ...
- MyBatis 的执行流程,面试的时候用得上
前言 MyBatis可能很多人都一直在用,但是MyBatis的SQL执行流程可能并不是所有人都清楚了,那么既然进来了,通读本文你将收获如下: 1.Mapper接口和映射文件是如何进行绑定的 2.MyB ...
- 动态执行流程分析和性能瓶颈分析的利器——gperftools的Cpu Profiler
在<动态执行流程分析和性能瓶颈分析的利器--valgrind的callgrind>中,我们领略了valgrind对流程和性能瓶颈分析的强大能力.本文将介绍拥有相似能力的gperftools ...
- 动态执行流程分析和性能瓶颈分析的利器——valgrind的callgrind
在<内存.性能问题分析的利器--valgrind>一文中我们简单介绍了下valgrind工具集,本文将使用callgrind工具进行动态执行流程分析和性能瓶颈分析.(转载请指明出于brea ...
最新文章
- 乔布斯当年是这样面试我的,你能挺到哪一步?
- 数据结构 - 反转单链表(C++)
- 读《分布式一致性原理》JAVA客户端API操作3
- Vue学习(组件的定义及调用、路由)-学习笔记
- C#的async和await
- 前端学习(804):替换字符串和转换为数组
- 【PAT甲级 - 1013】Battle Over Cities (25分)(并查集)
- javascirpt历史澄清误解基本概念特点编程语言web2.0网页javascript - javascirpt知识大全...
- MATLAB中的清除,oop – 在MATLAB中清除类定义
- javaScript笔记整理(一)
- 学python能赚钱吗-哪种Python程序员最赚钱?爬虫数据告诉你!
- 2018ACM-ICPC南京赛区网络赛: B. The writing on the wall
- java 对象与引用_Java --对象引用与对象的区别
- SQL Server 远程连接出错~~~无法访问服务器
- 计算机视觉 || Canny算子实现边缘分割并进一步处理
- 时尚html输入框,12款经典时尚的HTML5应用
- 《嵌入式系统设计师教程》读后感:2.6嵌入式系统电源
- ecshop小京东首页分类楼层左侧广告修改方法
- 盘点程序员的花式赚外快的骚操作
- 5. 第五阶段 测试开发技术 - JAVA
热门文章
- fonts.conf
- DELETE_FAILED_INTERNAL_ERROR Error while Installing APK
- 模拟jQuery--获取事件的封装
- VS2012:出现devenv.sln解决方案保存对话框
- 话里话外:参展管理信息化年会 聚会谈咨询需求有市场
- 网络管理员考试案例梳理、真题透解与强化训练
- HackerOne漏洞奖励计划扩展至开源漏洞
- 追风猎洞只能喝西北风吗?
- VMware ESXi 高危漏洞的补丁被指不完整
- Codeforces Round #542(Div. 2) B.Two Cakes