docker 反向工程


今天参加了一个meetup,演讲者介绍了一个可以模拟docker 命令的工具,可以在不安装docker 的情况下,体验下载镜像,启动容器的功能。

这个工具使用python写的,如果有兴趣花些时间去理解一下,对docker 的深层次理解会有很大的帮助。

运行环境

你需要一台linux 系统,本文用centos 7 , 暂时不支持windows 或者 mac os

卸载 docker engine

确保docker 命令 不存在。

准备环境

yum install -y gcc python-devel net-tools lsof 


mocker工具的环境安装

$ git clone https://github.com/tonybaloney/mocker.git
$ cd mocker
$ pip install virtualenv
$ virtualenv ENV
$ source ENV/bin/activate
$ pip install -r requirements.txt
$ ./mocker.py help
Usage:
mocker pull <name>[<tag>]
mocker run <name>
mocker images
mocker (-h | --help)
mocker --version


体验 pull 命令

$ ./mocker.py pull nginx
Starting new HTTPS connection (1): auth.docker.io
"GET /token?service=registry.docker.io&scope=repository:library/nginx:pull HTTP/1.1" 200 1442
Fetching manifest for nginx:latest...
Starting new HTTPS connection (1): registry-1.docker.io
"GET /v2/library/nginx/manifests/latest HTTP/1.1" 200 6938
Fetching layer sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4..
Starting new HTTPS connection (1): registry-1.docker.io
"GET /v2/library/nginx/blobs/sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4 HTTP/1.1" 307 432
Starting new HTTPS connection (1): dseasb33srnrn.cloudfront.net
"GET /registry-v2/docker/registry/v2/blobs/sha256/a3/a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4/data?Expires=1476787299&Signature=P0typ2UZrgFdGd4SrfBvKdKefSC8JkkNWxTExzZYTE6luS8R0ZbjCWWBHbwEj5v-q668Vf-y11WBULC7O~SWcYycly7ek0Eemlmr4eGphP-zdEJqCn9Nol~YSqrI4BX~MHFoWgIc9uXUJ1HM8VnTaMXIVELt5lNT9wDRz7OuzU8_&Key-Pair-Id=APKAJECH5M7VWIS5YZ6Q HTTP/1.1" 200 32
...
Fetching layer sha256:6a5a5368e0c2d3e5909184fa28ddfd56072e7ff3ee9a945876f7eee5896ef5bb..
Starting new HTTPS connection (1): registry-1.docker.io
"GET /v2/library/nginx/blobs/sha256:6a5a5368e0c2d3e5909184fa28ddfd56072e7ff3ee9a945876f7eee5896ef5bb HTTP/1.1" 307 432
Starting new HTTPS connection (1): dseasb33srnrn.cloudfront.net
"GET /registry-v2/docker/registry/v2/blobs/sha256/6a/6a5a5368e0c2d3e5909184fa28ddfd56072e7ff3ee9a945876f7eee5896ef5bb/data?Expires=1476787301&Signature=d1jSz7Z9Syjlk9OPjzYgFk37f-g9d1OK--2fi4FdotZwbmFTLDrj~TyRFx9WZA10W7DUJ7vL-GFb5WjOIoHWe1CR2dm9NewjvzI-k7gI6CmPeG0F0ZRseaYzanmoYYSIUSPbn2hsbq57pl43i3pJ2NLKbGb2eGuL~YBgjUFsEq0_&Key-Pair-Id=APKAJECH5M7VWIS5YZ6Q HTTP/1.1" 200 51354364
- bin
- bin/bash
- bin/cat
- bin/chacl
- bin/chgrp
- bin/chmod
- bin/chown
- bin/cp
- bin/dash
- bin/date
...
Fetching layer sha256:2fbd37c8684bca3df2090b8b8acce020837d560ec8917f25714e45e7d1f4611e..
Starting new HTTPS connection (1): registry-1.docker.io
"GET /v2/library/nginx/blobs/sha256:2fbd37c8684bca3df2090b8b8acce020837d560ec8917f25714e45e7d1f4611e HTTP/1.1" 307 432
Starting new HTTPS connection (1): dseasb33srnrn.cloudfront.net
"GET /registry-v2/docker/registry/v2/blobs/sha256/2f/2fbd37c8684bca3df2090b8b8acce020837d560ec8917f25714e45e7d1f4611e/data?Expires=1476787399&Signature=DNXOXyA9an018bG25GtQMaErpQwOtZUgMVW2Czur1DbwqJLe-w-5ETapnDVlz7WksCXNZ9JaO-hMBv~UjOOwQD1cjnpm3-QVMWGsnS4TBHLA9YZGx8wUMlUyQonSvHRTZKI2vr-SMlPDe91WgUzA-OrywSNvAXEqdIm-sn5qvPE_&Key-Pair-Id=APKAJECH5M7VWIS5YZ6Q HTTP/1.1" 200 195
- var
- var/log
- var/log/nginx
- var/log/nginx/access.log
- var/log/nginx/error.log
...
Fetching layer sha256:20a0fbbae14864e06e14f89126551d004555d9e2c13591105862ca1f9a418e9d..
Starting new HTTPS connection (1): registry-1.docker.io
"GET /v2/library/nginx/blobs/sha256:20a0fbbae14864e06e14f89126551d004555d9e2c13591105862ca1f9a418e9d HTTP/1.1" 307 432
Starting new HTTPS connection (1): dseasb33srnrn.cloudfront.net
"GET /registry-v2/docker/registry/v2/blobs/sha256/20/20a0fbbae14864e06e14f89126551d004555d9e2c13591105862ca1f9a418e9d/data?Expires=1476787401&Signature=H-52MjpIcEpNWHyikqDB50rrv1nj-4wPON6jW0gK5OeLlguxAv2iSUZpnQ1ImL-ixTxhD0iLdCpzMNDLsZ2lagJOVM6Susd1Jn-l7N8EgXUBkwQWAejbsJTjV89O6cI7T60OzaWsBPQCbM2jPYyFsfMPCjb8jLahSGuu95Wy2iw_&Key-Pair-Id=APKAJECH5M7VWIS5YZ6Q HTTP/1.1" 200 20134306
- etc
- etc/alternatives
- etc/alternatives/rename
- etc/alternatives/rename.1.gz
- etc/apt
- etc/apt/sources.list
- etc/apt/trusted.gpg
- etc/apt/trusted.gpg.d
- etc/apt/trusted.gpg~
- etc/ca-certificates
...


可以看到,其进程是: 授权,获得镜像清单 ($HOME/mocker/library_nginx.json),获取每层镜像。我们也可以看到docker 镜像服务器使用了aws 的 CDN 服务来加速下载。

在pull 镜像的时候,该作者给出很多有用的信息。 给出具体的api 命令及链接,每个docker 层的sha256码,每层的文件列表,等等

下载的镜像层文件(tar 包)被存放在 $HOME/mocker 目录下了。 并且里面的文件全部展开。
tree $HOME/mocker/library_nginx


列出镜像

$ ./mocker.py images
+---------------------+---------+---------+--------------------------+
| name                | version | size    | file                     |
+---------------------+---------+---------+--------------------------+
| library/hello-world | latest  | 1006.0B | library_hello-world.json |
| library/nginx       | latest  | 68.2MiB | library_nginx.json       |
+---------------------+---------+---------+--------------------------+


运行 容器

$ python mocker.py run library/nginx
Creating cgroups sub-directories for user vagrant
Hierarchies availables: ['hugetlb', 'perf_event', 'freezer', 'cpuset', 'net_cls', 'memory', 'blkio', 'cpuacct', 'cpu', 'cpu,cpuacct', 'devices', 'systemd']
cgroups sub-directories created for user vagrant
Creating cgroups sub-directories for user root
Hierarchies availables: ['hugetlb', 'perf_event', 'freezer', 'cpuset', 'net_cls', 'memory', 'blkio', 'cpuacct', 'cpu', 'cpu,cpuacct', 'devices', 'systemd']
cgroups sub-directories created for user root
Running "nginx -g "daemon off;""
Creating cgroups sub-directories for user root
Hierarchies availables: ['hugetlb', 'perf_event', 'freezer', 'cpuset', 'net_cls', 'memory', 'blkio', 'cpuacct', 'cpu', 'cpu,cpuacct', 'devices', 'systemd']
cgroups sub-directories created for user root
Setting ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Setting ENV NGINX_VERSION=1.11.5-1~jessie 


启动网络

另开一个窗口:
$ ip netns
netns_c_9052 (id: 0)

$ ip netns exec netns_c_9052 ifconfig
lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
    inet 127.0.0.1  netmask 255.0.0.0
    inet6 ::1  prefixlen 128  scopeid 0x10<host>
    loop  txqueuelen 0  (Local Loopback)
    RX packets 0  bytes 0 (0.0 B)
    RX errors 0  dropped 0  overruns 0  frame 0
    TX packets 0  bytes 0 (0.0 B)
    TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

veth1_c_9052: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
    inet 10.0.0.103  netmask 255.255.255.0  broadcast 0.0.0.0
    inet6 fe80::42:acff:fe11:90  prefixlen 64  scopeid 0x20<link>
    ether 02:42:ac:11:00:90  txqueuelen 1000  (Ethernet)
    RX packets 8  bytes 648 (648.0 B)
    RX errors 0  dropped 0  overruns 0  frame 0
    TX packets 8  bytes 648 (648.0 B)
    TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

$ ip netns exec netns_c_9052 lsof -naP -i tcp:80
lsof: no pwd entry for UID 104
COMMAND   PID     USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
nginx   12006     root   26u  IPv4  34170      0t0  TCP *:80 (LISTEN)
lsof: no pwd entry for UID 104
nginx   12007      104   26u  IPv4  34170      0t0  TCP *:80 (LISTEN)


到这一步,可以看到,80 端口已经启用。

确认容器里的web服务运行

$ ip netns exec netns_c_9052 curl localhost:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
    width: 35em;
    margin: 0 auto;
    font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>


参考

repo: https://github.com/tonybaloney/mocker

ip-netns 命令参考 : http://man7.org/linux/man-page ... .html

2 个评论

./mocker.py help
Traceback (most recent call last):
File "./mocker.py", line 2, in <module>
from docopt import docopt
ImportError: No module named docopt

但是 pip install docopt
Requirement already satisfied (use --upgrade to upgrade): docopt in ./ENV/lib/python2.7/site-packages
是这样的,作者写死了python 的路径了,在virtualenv 环境里,可能不是 /usr/bin/python. 所以,要修复这个问题的话, 你可以将第一行改成 #! /usr/bin/env python , 或者加python 运行: python ./mocker.py help

要回复文章请先登录注册