Docker Advanced

最近看了一本书,书名是<<Docker进阶与实战>>, 这里并不是讲一些基础入门,而是在已经掌握和应用的基础上,告诉你背后的原理和技术细节。平时留意到的很多现象都在这里得到了解释,还是很值得记一下要点的。

Chapter 3 镜像

主要介绍 Docker Image,其实就是启动容器的只读模板,是容器启动所需的rootfs。

Image 表示方法:

1
dockerhub-web-address/namespace/repository:tag
  • namespace: 用于划分用户或组织,有时并没有用到
  • repository: 类似于Git仓库,一个仓库有很多镜像
  • tag: 区分同一镜像不同版本

Layer这个东西类似于git commit。Image ID是最上层layer的ID。

Docker开源了镜像存储部分的代码,也就是docker registry, 在接触Docker的开始阶段我一直没明白registryrepository的区别,这2个词长得有点像哦,新手稍不注意就用混了,中文意思也有点类似,一个是档案室,一个是仓库,都可以放东西。

一般来说,docker registry需要与nginx去添加基本鉴权功能,才是一个合格的secure私有镜像库,但有时我并没有这么做。

已经下载到本地的镜像默认是存储在/var/lib/docker路径下的。

1
2
3
4
5
6
7
8
cd /var/lib/docker/image/devicemapper
ls -ltr

total 4
drwx------ 4 root root 37 May 8 15:21 imagedb
drwx------ 5 root root 45 May 8 15:22 layerdb
drwx------ 4 root root 58 May 8 15:29 distribution
-rw------- 1 root root 1269 Jun 17 09:21 repositories.json

使用Docker镜像

dangling image doesn’t have name and tag (present as <none>), docker commit sometimes can generate dangling image, you can use filter to show dangling:

1
docker images --filter "dangling=true"

只显示image ID:

1
docker images -q

Remove all dangling images:

1
2
3
# if no use {} in xargs
# the input arguments will be placed at end: docker rmi xxx
docker images --filter "dangling=true" -q | xargs docker rmi

There is a tool dockviz can do image analysis job. 可以图形化的展示image的层次。

docker load用于被docker save导出的镜像,还有一个docker import用于导入包含根文件系统的归档,并将之变为镜像, docker import常用来制作Docker baseimage。

1
2
docker save -o busybox.tar busybox
docker load -i busybox.tar

docker commit用于增量生成镜像,效率较低,一般用于前期测试(比如当时non-root开发),最终确定步骤后,可以用docker build

镜像的组织结构

可以用这2个命令去窥探一下镜像结构和元数据

1
2
docker history
docker inspect

镜像扩展知识

Docker引入了联合挂载Union mount技术,使镜像分层成为可能: 发展路径:

1
unionfs -> aufs -> overlayfs

写时复制 (copy-on-write) 是Docker image强大的一个重要原因,操作系统中也广泛用到了,比如fork.当父进程fork子进程时,并没有真正分配内存给子进程,而是共享,当2者之一修改共享内存时,触发缺页异常才导致真正的内存分配。这样加速了子进程的创建,也减少了内存消耗。

联合文件系统是实现写时复制的基础,Ubuntu自带aufs, Red Hat和Suse采用deivcemapper方案(在/var/lib/docker/image下就是这个东西),作为Docker的存储驱动,它们的存储结构和性能都有显著差异,要根据实际情况选用。

Chapter 4 仓库进阶

对Docker registry的API访问,传输对象主要包括镜像layer的块数据(blob)和表单(manifest)。layer数据以二进制方式存放于registry中。主要讲了一下用API进行pull, push的过程,步骤。其实都划分了很多步。

List and Dlete Image 可以参考我这篇博客<<Docker Registry API>>

鉴权机制,这里使用的是Docker Engine, Registry和Auth Server协作完成。Auth Server由Registry开发者部署搭建,Registry完全信任Auth Server.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
+---------------+               +------------------------+
| +-------+ | |
| Registry | | | Authorization Service |
| +<--+ | | |
+-+--+----------+ | | +---------------+--+-----+
^ | | | ^ |
| | 5 | | 6 | |
| | | | | |
1 | | 2 | | 3 | | 4
| | +---+---v---------+ | |
| +--------->+ +-------------+ |
| | Docker Daemon | |
+-------------+ +<---------------+
+--------+--------+
^
|
+-------------+----------------+
| Docker Client |
| $docker pull busybox |
| |
+------------------------------+
  1. Docker Engine试图赋予HTTP请求一个鉴权的token,如果没有,Daemon会试图fetch/refresh一个新的token。

  2. 如果请求没有做过认证且不含token则Registry会返回401 Unauthorized状态

  3. 用户带着Registry返回的信息以及证书去访问Auth Server申请token (这里具体怎么操作?证书在哪里?

  4. Auth Server后端账户记录着用户名和密码,获取用户请求后,会将鉴权信息的token返回给用户

  5. 用户带着token再次访问Regisrty, HEADER中包含:

    1
    Authorization: Bearer <token content>
  6. Registry检验token,如通过则开始工作

构建私有仓库

In general, we can simply run a private docker registry:

1
2
3
4
5
6
docker run -d \
--hostname localhost \
--name registry-v2 \
-v /opt/data:/var/lib/registry \
-p 5000:5000 \
registry:2.0

这里将本地目录/opt/data挂载到容器镜像存储目录/var/lib/registry,方便查看和管理镜像数据,在DataStage Installer中也是如此。这时的registry是不安全的,能访问本机5000端口的人都可以上传和下载镜像。

需要为其加上HTTPS反向代理,这里以Nginx来实现。然后代理服务器会接受HTTPS请求,然后将请求转发给内部网络上的registry服务器,并将registry访问结果返回给用户。

可以参考我的这篇blog关于如何搭建Secure Docker Registry.

Chapter 5 Docker网络

0%