同样,由于项目的发展、功能的拆分以及各种奇怪的改名 PR,让我们再次理解 Docker 的的整体架构变得更加困难。
在这种情况下,一旦服务器上的某一个服务被入侵,那么入侵者就能够访问当前机器上的所有服务和文件,这也是我们不想看到的,而 Docker 其实就通过 Linux 的 Namespaces 对不同的容器实现了隔离。
进程是 Linux 以及现在操作系统中非常重要的概念,它表示一个正在执行的程序,也是在现代分时系统中的一个任务单元。在每一个 *nix 的操作系统上,我们都能够通过 ps 命令打印出当前操作系统中正在执行的进程,比如在 Ubuntu 上,使用该命令就能得到以下的结果:
$ ps -ef<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"><span class="hljs-built_in" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">UID</span> PID PPID C STIME TTY TIME <span class="hljs-built_in" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">CMD</span><br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">root <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">1</span> <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span> <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span> Apr08 ? <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">00</span>:<span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">00</span>:<span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">09</span> /sbin/init<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">root <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">2</span> <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span> <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span> Apr08 ? <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">00</span>:<span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">00</span>:<span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">00</span> [kthreadd]<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">root <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">3</span> <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">2</span> <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span> Apr08 ? <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">00</span>:<span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">00</span>:<span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">05</span> [ksoftirqd/<span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span>]<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">root <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">5</span> <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">2</span> <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span> Apr08 ? <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">00</span>:<span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">00</span>:<span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">00</span> [kworker/<span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span>:<span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span>H]<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">root <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">7</span> <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">2</span> <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span> Apr08 ? <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">00</span>:<span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">07</span>:<span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">10</span> [rcu_sched]<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">root <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">39</span> <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">2</span> <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span> Apr08 ? <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">00</span>:<span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">00</span>:<span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">00</span> [migration/<span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span>]<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">root <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">40</span> <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">2</span> <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span> Apr08 ? <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">00</span>:<span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">01</span>:<span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">54</span> [watchdog/<span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span>]<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">...<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"></code></pre><section class="mpa-template" data-mpa-category="body" data-mpa-color="#ffffff" data-mpa-template-id="167209"><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">当前机器上有很多的进程正在执行,在上述进程中有两个非常特殊,一个是 pid 为 1 的 /sbin/init 进程,另一个是 pid 为 2 的 kthreadd 进程,这两个进程都是被 Linux 中的上帝进程 idle 创建出来的,其中前者负责执行内核的一部分初始化工作和系统配置,也会创建一些类似 getty 的注册进程,而后者负责管理和调度其他的内核进程。</p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><p style="text-align: center;"><img class="" data-copyright="0" data-ratio="0.5666666666666667" data-s="300,640" data-type="png" data-w="1200" src="http://img.chuansong.me/mmbiz_png/A1HKVXsfHNkwgchq0radWas6oSFP7WTaGDhjQia7VysNxkJGNv6rT13sRqeTxgYzRQSLe6kkViaC5GTnI0icu7vEA/?" style=""></p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">如果我们在当前的 Linux 操作系统下运行一个新的 Docker 容器,并通过 exec 进入其内部的 bash 并打印其中的全部进程,我们会得到以下的结果:</p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p></section><pre style="margin-top: 0px;margin-bottom: 0px;padding: 0px;font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;background-color: rgb(255, 255, 255);"><code class="hljs ruby" style="padding: 0.5em;font-size: 14px;color: rgb(169, 183, 198);line-height: 18px;font-family: Consolas, Inconsolata, Courier, monospace;display: block;overflow-x: auto;letter-spacing: 0px;background: rgb(40, 43, 46);word-wrap: normal !important;overflow-y: auto !important;">root@iZ255w13cy6Z<span class="hljs-symbol" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">:~</span><span class="hljs-comment" style="font-size: inherit;color: rgb(128, 128, 128);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"># docker run -it -d ubuntu</span><br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">b809a2eb3630e64c581561b08ac46154878ff1c61c6519848b4a29d412215e79<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">root@iZ255w13cy6Z<span class="hljs-symbol" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">:~</span><span class="hljs-comment" style="font-size: inherit;color: rgb(128, 128, 128);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"># docker exec -it b809a2eb3630 /bin/bash</span><br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">root@b809a2eb3630<span class="hljs-symbol" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">:/</span><span class="hljs-comment" style="font-size: inherit;color: rgb(128, 128, 128);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"># ps -ef</span><br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">UID PID PPID C STIME TTY TIME CMD<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">root <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">1</span> <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span> <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span> <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">15</span><span class="hljs-symbol" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">:</span><span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">42</span> pts/<span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span> <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">00</span><span class="hljs-symbol" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">:</span><span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">00</span><span class="hljs-symbol" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">:</span><span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">00</span> /bin/bash<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">root <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">9</span> <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span> <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span> <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">15</span><span class="hljs-symbol" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">:</span><span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">42</span> pts/<span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">1</span> <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">00</span><span class="hljs-symbol" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">:</span><span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">00</span><span class="hljs-symbol" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">:</span><span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">00</span> /bin/bash<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">root <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">17</span> <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">9</span> <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span> <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">15</span><span class="hljs-symbol" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">:</span><span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">43</span> pts/<span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">1</span> <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">00</span><span class="hljs-symbol" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">:</span><span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">00</span><span class="hljs-symbol" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">:</span><span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">00</span> ps -ef<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"></code></pre><section class="mpa-template" data-mpa-category="body" data-mpa-color="#ffffff" data-mpa-template-id="167209"><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">在新的容器内部执行 ps 命令打印出了非常干净的进程列表,只有包含当前 ps -ef 在内的三个进程,在宿主机器上的几十个进程都已经消失不见了。</p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">当前的 Docker 容器成功将容器内的进程与宿主机器中的进程隔离,如果我们在宿主机器上打印当前的全部进程时,会得到下面三条与 Docker 相关的结果:</p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p></section><pre style="margin-top: 0px;margin-bottom: 0px;padding: 0px;font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;background-color: rgb(255, 255, 255);"><code class="hljs objectivec" style="padding: 0.5em;font-size: 14px;color: rgb(169, 183, 198);line-height: 18px;font-family: Consolas, Inconsolata, Courier, monospace;display: block;overflow-x: auto;letter-spacing: 0px;background: rgb(40, 43, 46);word-wrap: normal !important;overflow-y: auto !important;"><span class="hljs-built_in" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">UID</span> PID PPID C STIME TTY TIME <span class="hljs-built_in" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">CMD</span><br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">root <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">29407</span> <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">1</span> <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span> Nov16 ? <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">00</span>:<span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">08</span>:<span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">38</span> /usr/bin/dockerd --raw-logs<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">root <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">1554</span> <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">29407</span> <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span> Nov19 ? <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">00</span>:<span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">03</span>:<span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">28</span> docker-containerd -l unix:<span class="hljs-comment" style="font-size: inherit;color: rgb(128, 128, 128);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">///var/run/docker/libcontainerd/docker-containerd.sock --metrics-interval=0 --start-timeout 2m --state-dir /var/run/docker/libcontainerd/containerd --shim docker-containerd-shim --runtime docker-runc</span><br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">root <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">5006</span> <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">1554</span> <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span> <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">08</span>:<span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">38</span> ? <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">00</span>:<span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">00</span>:<span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">00</span> docker-containerd-shim b809a2eb3630e64c581561b08ac46154878ff1c61c6519848b4a29d412215e79 /var/run/docker/libcontainerd/b809a2eb3630e64c581561b08ac46154878ff1c61c6519848b4a29d412215e79 docker-runc<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"></code></pre><section class="mpa-template" data-mpa-category="body" data-mpa-color="#ffffff" data-mpa-template-id="167209"><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">在当前的宿主机器上,可能就存在由上述的不同进程构成的进程树:</p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><p style="text-align: center;"><img class="" data-copyright="0" data-ratio="0.43333333333333335" data-s="300,640" data-type="png" data-w="1200" src="http://img.chuansong.me/mmbiz_png/A1HKVXsfHNkwgchq0radWas6oSFP7WTa9mFXsiau4zCcdXPE84HXrC9fQTe9ibicMW1gRE90STnbYMhKQRO1bMErg/?" style=""></p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">这就是在使用 clone(2) 创建新进程时传入 CLONE_NEWPID 实现的,也就是使用 Linux 的命名空间实现进程的隔离,Docker 容器内部的任意进程都对宿主机器的进程一无所知。</p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p></section><pre style="margin-top: 0px;margin-bottom: 0px;padding: 0px;font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;background-color: rgb(255, 255, 255);"><code class="hljs css" style="padding: 0.5em;font-size: 14px;color: rgb(169, 183, 198);line-height: 18px;font-family: Consolas, Inconsolata, Courier, monospace;display: block;overflow-x: auto;letter-spacing: 0px;background: rgb(40, 43, 46);word-wrap: normal !important;overflow-y: auto !important;"><span class="hljs-selector-tag" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">containerRouter</span><span class="hljs-selector-class" style="font-size: inherit;color: rgb(165, 218, 45);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">.postContainersStart</span><br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">└── <span class="hljs-selector-tag" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">daemon</span><span class="hljs-selector-class" style="font-size: inherit;color: rgb(165, 218, 45);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">.ContainerStart</span><br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"> └── <span class="hljs-selector-tag" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">daemon</span><span class="hljs-selector-class" style="font-size: inherit;color: rgb(165, 218, 45);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">.createSpec</span><br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"> └── <span class="hljs-selector-tag" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">setNamespaces</span><br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"> └── <span class="hljs-selector-tag" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">setNamespace</span><br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"></code></pre><section class="mpa-template" data-mpa-category="body" data-mpa-color="#ffffff" data-mpa-template-id="167209"><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">Docker 的容器就是使用上述技术实现与宿主机器的进程隔离,当我们每次运行 docker run 或者 docker start 时,都会在下面的方法中创建一个用于设置进程间隔离的 Spec:</p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p></section><pre style="margin-top: 0px;margin-bottom: 0px;padding: 0px;font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;background-color: rgb(255, 255, 255);"><code class="hljs objectivec" style="padding: 0.5em;font-size: 14px;color: rgb(169, 183, 198);line-height: 18px;font-family: Consolas, Inconsolata, Courier, monospace;display: block;overflow-x: auto;letter-spacing: 0px;background: rgb(40, 43, 46);word-wrap: normal !important;overflow-y: auto !important;">func (daemon *Daemon) createSpec(c *container.Container) (*specs.Spec, error) {<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"> s := oci.DefaultSpec()<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"> <span class="hljs-comment" style="font-size: inherit;color: rgb(128, 128, 128);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">// ...</span><br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"> <span class="hljs-keyword" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">if</span> err := setNamespaces(daemon, &s;, c); err != <span class="hljs-literal" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">nil</span> {<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"> <span class="hljs-keyword" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">return</span> <span class="hljs-literal" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">nil</span>, fmt.Errorf(<span class="hljs-string" style="font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">"linux spec namespaces: %v"</span>, err)<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"> }<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"> <span class="hljs-keyword" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">return</span> &s;, <span class="hljs-literal" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">nil</span><br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">}<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"></code></pre><section class="mpa-template" data-mpa-category="body" data-mpa-color="#ffffff" data-mpa-template-id="167209"><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">在 setNamespaces 方法中不仅会设置进程相关的命名空间,还会设置与用户、网络、IPC 以及 UTS 相关的命名空间:</p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p></section><pre style="margin-top: 0px;margin-bottom: 0px;padding: 0px;font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;background-color: rgb(255, 255, 255);"><code class="hljs objectivec" style="padding: 0.5em;font-size: 14px;color: rgb(169, 183, 198);line-height: 18px;font-family: Consolas, Inconsolata, Courier, monospace;display: block;overflow-x: auto;letter-spacing: 0px;background: rgb(40, 43, 46);word-wrap: normal !important;overflow-y: auto !important;">func setNamespaces(daemon *Daemon, s *specs.Spec, c *container.Container) error {<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"> <span class="hljs-comment" style="font-size: inherit;color: rgb(128, 128, 128);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">// user</span><br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"> <span class="hljs-comment" style="font-size: inherit;color: rgb(128, 128, 128);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">// network</span><br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"> <span class="hljs-comment" style="font-size: inherit;color: rgb(128, 128, 128);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">// ipc</span><br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"> <span class="hljs-comment" style="font-size: inherit;color: rgb(128, 128, 128);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">// uts</span><br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"> <span class="hljs-comment" style="font-size: inherit;color: rgb(128, 128, 128);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">// pid</span><br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"> <span class="hljs-keyword" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">if</span> c.HostConfig.PidMode.IsContainer() {<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"> ns := specs.LinuxNamespace{Type: <span class="hljs-string" style="font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">"pid"</span>}<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"> pc, err := daemon.getPidContainer(c)<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"> <span class="hljs-keyword" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">if</span> err != <span class="hljs-literal" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">nil</span> {<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"> <span class="hljs-keyword" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">return</span> err<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"> }<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"> ns.Path = fmt.Sprintf(<span class="hljs-string" style="font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">"/proc/%d/ns/pid"</span>, pc.State.GetPID())<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"> setNamespace(s, ns)<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"> } <span class="hljs-keyword" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">else</span> <span class="hljs-keyword" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">if</span> c.HostConfig.PidMode.IsHost() {<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"> oci.RemoveNamespace(s, specs.LinuxNamespaceType(<span class="hljs-string" style="font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">"pid"</span>))<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"> } <span class="hljs-keyword" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">else</span> {<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"> ns := specs.LinuxNamespace{Type: <span class="hljs-string" style="font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">"pid"</span>}<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"> setNamespace(s, ns)<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"> }<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"> <span class="hljs-keyword" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">return</span> <span class="hljs-literal" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">nil</span><br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">}<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"></code></pre><section class="mpa-template" data-mpa-category="body" data-mpa-color="#ffffff" data-mpa-template-id="167209"><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">所有命名空间相关的设置 Spec 最后都会作为 Create 函数的入参在创建新的容器时进行设置:</p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p></section><pre style="margin-top: 0px;margin-bottom: 0px;padding: 0px;font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;background-color: rgb(255, 255, 255);"><code class="hljs css" style="padding: 0.5em;font-size: 14px;color: rgb(169, 183, 198);line-height: 18px;font-family: Consolas, Inconsolata, Courier, monospace;display: block;overflow-x: auto;letter-spacing: 0px;background: rgb(40, 43, 46);word-wrap: normal !important;overflow-y: auto !important;"><span class="hljs-selector-tag" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">daemon</span><span class="hljs-selector-class" style="font-size: inherit;color: rgb(165, 218, 45);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">.containerd</span><span class="hljs-selector-class" style="font-size: inherit;color: rgb(165, 218, 45);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">.Create</span>(<span class="hljs-selector-tag" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">context</span><span class="hljs-selector-class" style="font-size: inherit;color: rgb(165, 218, 45);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">.Background</span>(), <span class="hljs-selector-tag" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">container</span><span class="hljs-selector-class" style="font-size: inherit;color: rgb(165, 218, 45);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">.ID</span>, <span class="hljs-selector-tag" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">spec</span>, <span class="hljs-selector-tag" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">createOptions</span>)<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"></code></pre><section class="mpa-template" data-mpa-category="body" data-mpa-color="#ffffff" data-mpa-template-id="167209"><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">所有与命名空间的相关的设置都是在上述的两个函数中完成的,Docker 通过命名空间成功完成了与宿主机进程和网络的隔离。</p></section><section class="mpa-template" data-mpa-category="title" data-mpa-color="#ffffff" data-mpa-template-id="167215"><p style="margin: 0px;padding: 0px 10px 0px 9px;color: rgb(60, 60, 60);font-size: 16px;font-weight: bold;letter-spacing: 1px;text-align: center;white-space: normal;line-height: 1.8;background: rgb(255, 255, 255);z-index: 10000;"><br></p><p style="margin: 0px;padding: 0px 10px 0px 9px;color: rgb(60, 60, 60);font-size: 16px;font-weight: bold;letter-spacing: 1px;text-align: center;white-space: normal;line-height: 1.8;background: rgb(255, 255, 255);z-index: 10000;">网络</p><p><img class="" data-ratio="0.053125" data-type="png" data-w="640" src="https://i-blog.csdnimg.cn/blog_migrate/9a57787dc097b688f8ec4e62d638bca0.png" style="margin-right: 0px;margin-bottom: 0px;margin-left: 0px;padding: 0px;color: rgb(60, 60, 60);font-weight: bold;letter-spacing: 1px;text-align: center;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;display: inline-block;left: 0px;transform: rotateX(60deg);margin-top: 5px !important;height: auto !important;width: 632px !important;visibility: visible !important;" width="632px"></p><p><br></p></section><section class="mpa-template" data-mpa-category="body" data-mpa-color="#ffffff" data-mpa-template-id="167209"><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">如果 Docker 的容器通过 Linux 的命名空间完成了与宿主机进程的网络隔离,但是却有没有办法通过宿主机的网络与整个互联网相连,就会产生很多限制,所以 Docker 虽然可以通过命名空间创建一个隔离的网络环境,但是 Docker 中的服务仍然需要与外界相连才能发挥作用。</p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><section mpa-is-content="t" style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">每一个使用 docker run 启动的容器其实都具有单独的网络命名空间,Docker 为我们提供了四种不同的网络模式,Host、Container、None 和 Bridge 模式。</section><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><p style="text-align: center;"><img class="" data-copyright="0" data-ratio="0.26666666666666666" data-s="300,640" data-type="png" data-w="1200" src="http://img.chuansong.me/mmbiz_png/A1HKVXsfHNkwgchq0radWas6oSFP7WTaeJzfHAqJUykQRUbnqicjhPa2pJAicBv5RgISDGFkrGIqT3cp2OwlVtDA/?" style=""></p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><section mpa-is-content="t" style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">在这一部分,我们将介绍 Docker 默认的网络设置模式:网桥模式。在这种模式下,除了分配隔离的网络命名空间之外,Docker 还会为所有的容器设置 IP 地址。当 Docker 服务器在主机上启动之后会创建新的虚拟网桥 docker0,随后在该主机上启动的全部服务在默认情况下都与该网桥相连。</section><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><p style="text-align: center;"><img class="" data-copyright="0" data-ratio="0.5916666666666667" data-s="300,640" data-type="png" data-w="1200" src="http://img.chuansong.me/mmbiz_png/A1HKVXsfHNkwgchq0radWas6oSFP7WTappb7oIB25AIHBAoeGPGFz5CGDGv1KiaLAn5uHz74NBiasicHmriaVB8hibw/?" style=""></p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">在默认情况下,每一个容器在创建时都会创建一对虚拟网卡,两个虚拟网卡组成了数据的通道,其中一个会放在创建的容器中,会加入到名为 docker0 网桥中。我们可以使用如下的命令来查看当前网桥的接口:</p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p></section><pre style="margin-top: 0px;margin-bottom: 0px;padding: 0px;font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;background-color: rgb(255, 255, 255);"><code class="hljs sql" style="padding: 0.5em;font-size: 14px;color: rgb(169, 183, 198);line-height: 18px;font-family: Consolas, Inconsolata, Courier, monospace;display: block;overflow-x: auto;letter-spacing: 0px;background: rgb(40, 43, 46);word-wrap: normal !important;overflow-y: auto !important;">$ brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.0242a6654980 no veth3e84d4f
veth9953b75
docker0 会为每一个容器分配一个新的 IP 地址并将 docker0 的 IP 地址设置为默认的网关。网桥 docker0 通过 iptables 中的配置与宿主机器上的网卡相连,所有符合条件的请求都会通过 iptables 转发到 docker0 并由网桥分发给对应的机器。
$ iptables -t nat -L<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">Chain PREROUTING (policy ACCEPT)<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">target prot opt <span class="hljs-built_in" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">source</span> destination<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">DOCKER all -- anywhere anywhere ADDRTYPE match dst-type LOCAL<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">Chain DOCKER (2 references)<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">target prot opt <span class="hljs-built_in" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">source</span> destination<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">RETURN all -- anywhere anywhere<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"></code></pre><section class="mpa-template" data-mpa-category="body" data-mpa-color="#ffffff" data-mpa-template-id="167209"><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">我们在当前的机器上使用 docker run -d -p 6379:6379 redis 命令启动了一个新的 Redis 容器,在这之后我们再查看当前 iptables 的 NAT 配置就会看到在 DOCKER 的链中出现了一条新的规则:</p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p></section><pre style="margin-top: 0px;margin-bottom: 0px;padding: 0px;font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;background-color: rgb(255, 255, 255);"><code class="hljs css" style="padding: 0.5em;font-size: 14px;color: rgb(169, 183, 198);line-height: 18px;font-family: Consolas, Inconsolata, Courier, monospace;display: block;overflow-x: auto;letter-spacing: 0px;background: rgb(40, 43, 46);word-wrap: normal !important;overflow-y: auto !important;"><span class="hljs-selector-tag" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">DNAT</span> <span class="hljs-selector-tag" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">tcp</span> <span class="hljs-selector-tag" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">--</span> <span class="hljs-selector-tag" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">anywhere</span> <span class="hljs-selector-tag" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">anywhere</span> <span class="hljs-selector-tag" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">tcp</span> <span class="hljs-selector-tag" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">dpt</span><span class="hljs-selector-pseudo" style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">:6379</span> <span class="hljs-selector-tag" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">to</span><span class="hljs-selector-pseudo" style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">:192.168.0.4</span><span class="hljs-selector-pseudo" style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">:6379</span><br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"></code></pre><section class="mpa-template" data-mpa-category="body" data-mpa-color="#ffffff" data-mpa-template-id="167209"><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">上述规则会将从任意源发送到当前机器 6379 端口的 TCP 包转发到 192.168.0.4:6379 所在的地址上。</p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">这个地址其实也是 Docker 为 Redis 服务分配的 IP 地址,如果我们在当前机器上直接 ping 这个 IP 地址就会发现它是可以访问到的:</p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p></section><pre style="margin-top: 0px;margin-bottom: 0px;padding: 0px;font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;background-color: rgb(255, 255, 255);"><code class="hljs coffeescript" style="padding: 0.5em;font-size: 14px;color: rgb(169, 183, 198);line-height: 18px;font-family: Consolas, Inconsolata, Courier, monospace;display: block;overflow-x: auto;letter-spacing: 0px;background: rgb(40, 43, 46);word-wrap: normal !important;overflow-y: auto !important;">$ ping 192.168.0.4
PING 192.168.0.4 (192.168.0.4) 56(84) bytes of data.
64 bytes from 192.168.0.4: icmp_seq=1 ttl=64 time=0.069 ms
64 bytes from 192.168.0.4: icmp_seq=2 ttl=64 time=0.043 ms
^C
--- 192.168.0.4 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.043/0.056/0.069/0.013 ms
从上述的一系列现象,我们就可以推测出 Docker 是如何将容器的内部的端口暴露出来并对数据包进行转发的了;当有 Docker 的容器需要将服务暴露给宿主机器,就会为容器分配一个 IP 地址,同时向 iptables 中追加一条新的规则。
当我们使用 redis-cli 在宿主机器的命令行中访问 127.0.0.1:6379 的地址时,经过 iptables 的 NAT PREROUTING 将 ip 地址定向到了 192.168.0.4,重定向过的数据包就可以通过 iptables 中的 FILTER 配置,最终在 NAT POSTROUTING 阶段将 ip 地址伪装成 127.0.0.1,到这里虽然从外面看起来我们请求的是 127.0.0.1:6379,但是实际上请求的已经是 Docker 容器暴露出的端口了。
$ redis-cli -h <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">127.0</span>.<span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span>.<span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">1</span> -p <span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">6379</span> ping<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">PONG<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"></code></pre><section class="mpa-template" data-mpa-category="body" data-mpa-color="#ffffff" data-mpa-template-id="167209"><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">Docker 通过 Linux 的命名空间实现了网络的隔离,又通过 iptables 进行数据包转发,让 Docker 容器能够优雅地为宿主机器或者其他容器提供服务。</p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p></section><section class="mpa-template" data-mpa-category="title" data-mpa-color="#ffffff" data-mpa-template-id="167215"><section class="" mpa-is-content="t" style="margin: 0px;padding: 0px 10px 0px 9px;color: rgb(60, 60, 60);font-size: 16px;font-weight: bold;letter-spacing: 1px;text-align: center;white-space: normal;line-height: 1.8;background: rgb(255, 255, 255);z-index: 10000;">Libnetwork</section><p><img class="" data-ratio="0.053125" data-type="png" data-w="640" src="https://i-blog.csdnimg.cn/blog_migrate/9a57787dc097b688f8ec4e62d638bca0.png" style="margin-right: 0px;margin-bottom: 0px;margin-left: 0px;padding: 0px;color: rgb(60, 60, 60);font-weight: bold;letter-spacing: 1px;text-align: center;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;display: inline-block;left: 0px;transform: rotateX(60deg);margin-top: 5px !important;height: auto !important;width: 632px !important;visibility: visible !important;" width="632px"></p><p><br></p></section><section class="mpa-template" data-mpa-category="body" data-mpa-color="#ffffff" data-mpa-template-id="167209"><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">整个网络部分的功能都是通过 Docker 拆分出来的 libnetwork 实现的,它提供了一个连接不同容器的实现,同时也能够为应用给出一个能够提供一致的编程接口和网络层抽象的容器网络模型。</p><section class="mpa-template" data-mpa-category="quote" data-mpa-color="#ffffff" data-mpa-template-id="90"><section style="margin:30px auto;background-color:#f7f7f7;padding:25px 20px;"><section data-preserve-color="t" mpa-is-content="t" style="font-size:14px;color:#4f4f4f;">The goal of libnetwork is to deliver a robust Container Network Model that provides a consistent programming interface and the required network abstractions for applications.</section></section></section><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">libnetwork 中最重要的概念,容器网络模型由以下的几个主要组件组成,分别是 Sandbox、Endpoint 和 Network:</p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><p style="text-align: center;"><img class="" data-copyright="0" data-ratio="0.375" data-s="300,640" data-type="png" data-w="1200" src="http://img.chuansong.me/mmbiz_png/A1HKVXsfHNkwgchq0radWas6oSFP7WTaibN6Ncco84e73fFT65icZHPzic9ayHeLh7ASQ7DLX4zbANUWn7atoJnQQ/?" style=""></p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">在容器网络模型中,每一个容器内部都包含一个 Sandbox,其中存储着当前容器的网络栈配置,包括容器的接口、路由表和 DNS 设置,Linux 使用网络命名空间实现这个 Sandbox,每一个 Sandbox 中都可能会有一个或多个 Endpoint,在 Linux 上就是一个虚拟的网卡 veth,Sandbox 通过 Endpoint 加入到对应的网络中,这里的网络可能就是我们在上面提到的 Linux 网桥或者 VLAN。</p><section class="mpa-template" data-mpa-category="quote" data-mpa-color="#ffffff" data-mpa-template-id="90"><section style="margin:30px auto;background-color:#f7f7f7;padding:25px 20px;"><section data-preserve-color="t" mpa-is-content="t" style="font-size:14px;color:#4f4f4f;">想要获得更多与 libnetwork 或者容器网络模型相关的信息,可以阅读 Design · libnetwork[1] 了解更多信息,当然也可以阅读源代码了解不同 OS 对容器网络模型的不同实现。</section></section></section></section><h4 style="margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.2em;color: rgb(62, 62, 62);line-height: inherit;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: inherit;color: inherit;line-height: inherit;"></span></h4><section class="mpa-template" data-mpa-category="title" data-mpa-color="#ffffff" data-mpa-template-id="167215"><section class="" mpa-is-content="t" style="margin: 0px;padding: 0px 10px 0px 9px;color: rgb(60, 60, 60);font-size: 16px;font-weight: bold;letter-spacing: 1px;text-align: center;white-space: normal;line-height: 1.8;background: rgb(255, 255, 255);z-index: 10000;">挂载点</section><p><img class="" data-ratio="0.053125" data-type="png" data-w="640" src="https://i-blog.csdnimg.cn/blog_migrate/9a57787dc097b688f8ec4e62d638bca0.png" style="margin-right: 0px;margin-bottom: 0px;margin-left: 0px;padding: 0px;color: rgb(60, 60, 60);font-weight: bold;letter-spacing: 1px;text-align: center;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;display: inline-block;left: 0px;transform: rotateX(60deg);margin-top: 5px !important;height: auto !important;width: 632px !important;visibility: visible !important;" width="632px"></p><p><br></p></section><section class="mpa-template" data-mpa-category="body" data-mpa-color="#ffffff" data-mpa-template-id="167209"><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">虽然我们已经通过 Linux 的命名空间解决了进程和网络隔离的问题,在 Docker 进程中我们已经没有办法访问宿主机器上的其他进程并且限制了网络的访问,但是 Docker 容器中的进程仍然能够访问或者修改宿主机器上的其他目录,这是我们不希望看到的。</p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">在新的进程中创建隔离的挂载点命名空间需要在 clone 函数中传入 CLONE_NEWNS,这样子进程就能得到父进程挂载点的拷贝,如果不传入这个参数子进程对文件系统的读写都会同步回父进程以及整个主机的文件系统。</p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><section mpa-is-content="t" style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">如果一个容器需要启动,那么它一定需要提供一个根文件系统(rootfs),容器需要使用这个文件系统来创建一个新的进程,所有二进制的执行都必须在这个根文件系统中。</section><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><p style="text-align: center;"><img class="" data-copyright="0" data-ratio="0.39166666666666666" data-s="300,640" data-type="png" data-w="1200" src="http://img.chuansong.me/mmbiz_png/A1HKVXsfHNkwgchq0radWas6oSFP7WTaJUZfsMQ3PjYxxsSera57wNYNvJRb7LjAyjO7TTOCk3peprvzWJgd7g/?" style=""></p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><section mpa-is-content="t" style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">想要正常启动一个容器就需要在 rootfs 中挂载以上的几个特定的目录,除了上述的几个目录需要挂载之外我们还需要建立一些符号链接保证系统 IO 不会出现问题。</section><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><p style="text-align: center;"><img class="" data-copyright="0" data-ratio="0.425" data-s="300,640" data-type="png" data-w="1200" src="http://img.chuansong.me/mmbiz_png/A1HKVXsfHNkwgchq0radWas6oSFP7WTa2pOiabkRdYHW1EYKqHBbauwgibCXib4HiblgLhhB2owxxTo0fggvibjVllA/?" style=""></p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">为了保证当前的容器进程没有办法访问宿主机器上其他目录,我们在这里还需要通过 libcotainer 提供的 pivor_root 或者 chroot 函数改变进程能够访问个文件目录的根节点。</p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p></section><pre style="margin-top: 0px;margin-bottom: 0px;padding: 0px;font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;background-color: rgb(255, 255, 255);"><code class="hljs perl" style="padding: 0.5em;font-size: 14px;color: rgb(169, 183, 198);line-height: 18px;font-family: Consolas, Inconsolata, Courier, monospace;display: block;overflow-x: auto;letter-spacing: 0px;background: rgb(40, 43, 46);word-wrap: normal !important;overflow-y: auto !important;">// pivor_root<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">put_old = <span class="hljs-keyword" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">mkdir</span>(...);<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">pivot_root(rootfs, put_old);<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"><span class="hljs-keyword" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">chdir</span>(<span class="hljs-string" style="font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">"/"</span>);<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">unmount(put_old, MS_DETACH);<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"><span class="hljs-keyword" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">rmdir</span>(put_old);<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"><span class="hljs-regexp" style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">//</span> <span class="hljs-keyword" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">chroot</span><br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">mount(rootfs, <span class="hljs-string" style="font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">"/"</span>, NULL, MS_MOVE, NULL);<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"><span class="hljs-keyword" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">chroot</span>(<span class="hljs-string" style="font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">"."</span>);<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"><span class="hljs-keyword" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">chdir</span>(<span class="hljs-string" style="font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">"/"</span>);<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"></code></pre><section class="mpa-template" data-mpa-category="body" data-mpa-color="#ffffff" data-mpa-template-id="167209"><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">到这里我们就将容器需要的目录挂载到了容器中,同时也禁止当前的容器进程访问宿主机器上的其他目录,保证了不同文件系统的隔离。</p><section class="mpa-template" data-mpa-category="quote" data-mpa-color="#ffffff" data-mpa-template-id="90"><section style="margin:30px auto;background-color:#f7f7f7;padding:25px 20px;"><section data-preserve-color="t" mpa-is-content="t" style="font-size:14px;color:#4f4f4f;">这一部分的内容是作者在 libcontainer 中的 SPEC.md[2] 文件中找到的,其中包含了 Docker 使用的文件系统的说明,对于 Docker 是否真的使用 chroot 来确保当前的进程无法访问宿主机器的目录,作者其实也没有确切的答案,一是 Docker 项目的代码太多庞大,不知道该从何入手,作者尝试通过 Google 查找相关的结果,但是既找到了无人回答的问题[3],也得到了与 SPEC 中的描述有冲突的答案[4],如果各位读者有明确的答案可以在博客下面留言,非常感谢。</section></section></section></section><section class="mpa-template" data-mpa-category="title" data-mpa-color="#ffffff" data-mpa-template-id="167215"><section class="" mpa-is-content="t" style="margin: 0px;padding: 0px 10px 0px 9px;color: rgb(60, 60, 60);font-size: 16px;font-weight: bold;letter-spacing: 1px;text-align: center;white-space: normal;line-height: 1.8;background: rgb(255, 255, 255);z-index: 10000;">Chroot</section><p><img class="" data-ratio="0.053125" data-type="png" data-w="640" src="https://i-blog.csdnimg.cn/blog_migrate/9a57787dc097b688f8ec4e62d638bca0.png" style="margin-right: 0px;margin-bottom: 0px;margin-left: 0px;padding: 0px;color: rgb(60, 60, 60);font-weight: bold;letter-spacing: 1px;text-align: center;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;display: inline-block;left: 0px;transform: rotateX(60deg);margin-top: 5px !important;height: auto !important;width: 632px !important;visibility: visible !important;" width="632px"></p><p><br></p></section><section class="mpa-template" data-mpa-category="body" data-mpa-color="#ffffff" data-mpa-template-id="167209"><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">在这里不得不简单介绍一下 chroot(change root),在 Linux 系统中,系统默认的目录就都是以 / 也就是根目录开头的,chroot 的使用能够改变当前的系统根目录结构,通过改变当前系统的根目录,我们能够限制用户的权利,在新的根目录下并不能够访问旧系统根目录的结构个文件,也就建立了一个与原系统完全隔离的目录结构。</p><section class="mpa-template" data-mpa-category="quote" data-mpa-color="#ffffff" data-mpa-template-id="90"><section style="margin:30px auto;background-color:#f7f7f7;padding:25px 20px;"><section data-preserve-color="t" mpa-is-content="t" style="font-size:14px;color:#4f4f4f;">与 chroot 的相关内容部分来自《理解 chroot[5]》一文,各位读者可以阅读这篇文章获得更详细的信息。</section></section></section></section><h4 style="margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.2em;color: rgb(62, 62, 62);line-height: inherit;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: inherit;color: inherit;line-height: inherit;"></span></h4><section class="mpa-template" data-mpa-category="title" data-mpa-color="#ffffff" data-mpa-template-id="167215"><section class="" mpa-is-content="t" style="margin: 0px;padding: 0px 10px 0px 9px;color: rgb(60, 60, 60);font-size: 16px;font-weight: bold;letter-spacing: 1px;text-align: center;white-space: normal;line-height: 1.8;background: rgb(255, 255, 255);z-index: 10000;">CGroups</section><p><img class="" data-ratio="0.053125" data-type="png" data-w="640" src="https://i-blog.csdnimg.cn/blog_migrate/9a57787dc097b688f8ec4e62d638bca0.png" style="margin-right: 0px;margin-bottom: 0px;margin-left: 0px;padding: 0px;color: rgb(60, 60, 60);font-weight: bold;letter-spacing: 1px;text-align: center;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;display: inline-block;left: 0px;transform: rotateX(60deg);margin-top: 5px !important;height: auto !important;width: 632px !important;visibility: visible !important;" width="632px"></p><p><br></p></section><section class="mpa-template" data-mpa-category="body" data-mpa-color="#ffffff" data-mpa-template-id="167209"><section mpa-is-content="t" style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">我们通过 Linux 的命名空间为新创建的进程隔离了文件系统、网络并与宿主机器之间的进程相互隔离,但是命名空间并不能够为我们提供物理资源上的隔离,比如 CPU 或者内存,如果在同一台机器上运行了多个对彼此以及宿主机器一无所知的『容器』,这些容器却共同占用了宿主机器的物理资源。</section><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><p style="text-align: center;"><img class="" data-copyright="0" data-ratio="0.4166666666666667" data-s="300,640" data-type="png" data-w="1200" src="http://img.chuansong.me/mmbiz_png/A1HKVXsfHNkwgchq0radWas6oSFP7WTaNvV5OMKMxIYyiaZrw7icCwK9AUxS8Hr6w2cDkKqgJ2I8TdIXyEkRdQ8A/?" style=""></p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">如果其中的某一个容器正在执行 CPU 密集型的任务,那么就会影响其他容器中任务的性能与执行效率,导致多个容器相互影响并且抢占资源。如何对多个容器的资源使用进行限制就成了解决进程虚拟资源隔离之后的主要问题,而 Control Groups(简称 CGroups)就是能够隔离宿主机器上的物理资源,例如 CPU、内存、磁盘 I/O 和网络带宽。</p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><section mpa-is-content="t" style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">每一个 CGroup 都是一组被相同的标准和参数限制的进程,不同的 CGroup 之间是有层级关系的,也就是说它们之间可以从父类继承一些用于限制资源使用的标准和参数。</section><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><p style="text-align: center;"><img class="" data-copyright="0" data-ratio="0.4083333333333333" data-s="300,640" data-type="png" data-w="1200" src="http://img.chuansong.me/mmbiz_png/A1HKVXsfHNkwgchq0radWas6oSFP7WTa7jicVG3ImcuXngEZMEBKbbubeAu4PIkZsguG9rQaxLAicKuU5ECJEl7A/?" style=""></p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><section mpa-is-content="t" style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">Linux 的 CGroup 能够为一组进程分配资源,也就是我们在上面提到的 CPU、内存、网络带宽等资源,通过对资源的分配,CGroup 能够提供以下的几种功能:</section><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><p style="text-align: center;"><img class="" data-copyright="0" data-ratio="0.26666666666666666" data-s="300,640" data-type="png" data-w="1200" src="http://img.chuansong.me/mmbiz_png/A1HKVXsfHNkwgchq0radWas6oSFP7WTakoII3tpRwsupZmCUZy8yMybmiczmxFXyfIKSibskTogMkAibH6kePPZmQ/?" style=""></p><section class="mpa-template" data-mpa-category="quote" data-mpa-color="#ffffff" data-mpa-template-id="90"><section style="margin:30px auto;background-color:#f7f7f7;padding:25px 20px;"><p style="font-size:14px;color:#4f4f4f;">在 CGroup 中,所有的任务就是一个系统的一个进程,而 CGroup 就是一组按照某种标准划分的进程,在 CGroup 这种机制中,所有的资源控制都是以 CGroup 作为单位实现的,每一个进程都可以随时加入一个 CGroup 也可以随时退出一个 CGroup。</p><p style="font-size:14px;color:#4f4f4f;"><br></p><section data-preserve-color="t" mpa-is-content="t" style="font-size: 14px;color: rgb(79, 79, 79);text-align: right;">——CGroup 介绍、应用实例及原理描述[6]</section></section></section><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">Linux 使用文件系统来实现 CGroup,我们可以直接使用下面的命令查看当前的 CGroup 中有哪些子系统:</p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p></section><pre style="margin-top: 0px;margin-bottom: 0px;padding: 0px;font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;background-color: rgb(255, 255, 255);"><code class="hljs ruby" style="padding: 0.5em;font-size: 14px;color: rgb(169, 183, 198);line-height: 18px;font-family: Consolas, Inconsolata, Courier, monospace;display: block;overflow-x: auto;letter-spacing: 0px;background: rgb(40, 43, 46);word-wrap: normal !important;overflow-y: auto !important;">$ lssubsys -m
cpuset /sys/fs/cgroup/cpuset
cpu /sys/fs/cgroup/cpu
cpuacct /sys/fs/cgroup/cpuacct
memory /sys/fs/cgroup/memory
devices /sys/fs/cgroup/devices
freezer /sys/fs/cgroup/freezer
blkio /sys/fs/cgroup/blkio
perf_event /sys/fs/cgroup/perf_event
hugetlb /sys/fs/cgroup/hugetlb
大多数 Linux 的发行版都有着非常相似的子系统,而之所以将上面的 cpuset、cpu 等东西称作子系统,是因为它们能够为对应的控制组分配资源并限制资源的使用。
如果我们想要创建一个新的 cgroup 只需要在想要分配或者限制资源的子系统下面创建一个新的文件夹,然后这个文件夹下就会自动出现很多的内容,如果你在 Linux 上安装了 Docker,你就会发现所有子系统的目录下都有一个名为 Docker 的文件夹:
$ ls cpu<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">cgroup.clone_children <br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">...<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">cpu.stat <br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">docker <br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">notify_on_release <br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">release_agent <br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">tasks<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">$ ls cpu/docker/
9c3057f1291b53fd54a3d12023d2644efe6a7db6ddf330436ae73ac92d401cf1
cgroup.clone_children
...
cpu.stat
notify_on_release
release_agent
tasks
9c3057xxx 其实就是我们运行的一个 Docker 容器,启动这个容器时,Docker 会为这个容器创建一个与容器标识符相同的 CGroup,在当前的主机上 CGroup 就会有以下的层级关系:
每一个 CGroup 下面都有一个 tasks 文件,其中存储着属于当前控制组的所有进程的 pid,作为负责 cpu 的子系统,cpu.cfsquotaus 文件中的内容能够对 CPU 的使用作出限制,如果当前文件的内容为 50000,那么当前控制组中的全部进程的 CPU 占用率不能超过 50%。
如果系统管理员想要控制 Docker 某个容器的资源使用率就可以在 Docker 这个父控制组下面找到对应的子控制组并且改变它们对应文件的内容,当然我们也可以直接在程序运行时就使用参数,让 Docker 进程去改变相应文件中的内容。
$</span><span class="bash" style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"> docker run -it -d --cpu-quota=50000 busybox</span><br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">53861305258ecdd7f5d2a3240af694aec9adb91cd4c7e210b757f71153cdd274<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"><span class="hljs-meta" style="font-size: inherit;color: rgb(91, 218, 237);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">$ cd 53861305258ecdd7f5d2a3240af694aec9adb91cd4c7e210b757f71153cdd274/
$</span><span class="bash" style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"> ls</span><br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">cgroup.clone_children cgroup.event_control cgroup.procs cpu.cfs_period_us cpu.cfs_quota_us cpu.shares cpu.stat notify_on_release tasks<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"><span class="hljs-meta" style="font-size: inherit;color: rgb(91, 218, 237);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">$ cat cpu.cfs_quota_us
50000
当我们使用 Docker 关闭掉正在运行的容器时,Docker 的子控制组对应的文件夹也会被 Docker 进程移除,Docker 在使用 CGroup 时其实也只是做了一些创建文件夹改变文件内容的文件操作,不过 CGroup 的使用也确实解决了我们限制子容器资源占用的问题,系统管理员能够为多个容器合理的分配资源并且不会出现多个容器互相抢占资源的问题。
Linux 的命名空间和控制组分别解决了不同资源隔离的问题,前者解决了进程、网络以及文件系统的隔离,后者实现了 CPU、内存等资源的隔离,但是在 Docker 中还有另一个非常重要的问题需要解决 - 也就是镜像。
镜像到底是什么,它又是如何组成和组织的是作者使用 Docker 以来的一段时间内一直比较让作者感到困惑的问题,我们可以使用 docker run 非常轻松地从远程下载 Docker 的镜像并在本地运行。
Docker 镜像其实本质就是一个压缩包,我们可以使用下面的命令将一个 Docker 镜像中的文件导出:
$ docker export $(docker create busybox) | tar -C rootfs -xvf -
$ ls<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"><span class="hljs-keyword" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">bin</span> dev etc home proc root <span class="hljs-keyword" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">sys</span> tmp usr <span class="hljs-keyword" style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">var</span><br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"></code></pre><section class="mpa-template" data-mpa-category="body" data-mpa-color="#ffffff" data-mpa-template-id="167209"><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">你可以看到这个 busybox 镜像中的目录结构与 Linux 操作系统的根目录中的内容并没有太多的区别,可以说 Docker 镜像就是一个文件。</p></section><h4 style="margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.2em;color: rgb(62, 62, 62);line-height: inherit;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: inherit;color: inherit;line-height: inherit;"></span></h4><section class="mpa-template" data-mpa-category="title" data-mpa-color="#ffffff" data-mpa-template-id="167215"><section class="" mpa-is-content="t" style="margin: 0px;padding: 0px 10px 0px 9px;color: rgb(60, 60, 60);font-size: 16px;font-weight: bold;letter-spacing: 1px;text-align: center;white-space: normal;line-height: 1.8;background: rgb(255, 255, 255);z-index: 10000;">存储驱动</section><p><img class="" data-ratio="0.053125" data-type="png" data-w="640" src="https://i-blog.csdnimg.cn/blog_migrate/9a57787dc097b688f8ec4e62d638bca0.png" style="margin-right: 0px;margin-bottom: 0px;margin-left: 0px;padding: 0px;color: rgb(60, 60, 60);font-weight: bold;letter-spacing: 1px;text-align: center;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;display: inline-block;left: 0px;transform: rotateX(60deg);margin-top: 5px !important;height: auto !important;width: 632px !important;visibility: visible !important;" width="632px"></p><p><br></p></section><section class="mpa-template" data-mpa-category="body" data-mpa-color="#ffffff" data-mpa-template-id="167209"><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">Docker 使用了一系列不同的存储驱动管理镜像内的文件系统并运行容器,这些存储驱动与 Docker 卷(volume)有些不同,存储引擎管理着能够在多个容器之间共享的存储。</p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">想要理解 Docker 使用的存储驱动,我们首先需要理解 Docker 是如何构建并且存储镜像的,也需要明白 Docker 的镜像是如何被每一个容器所使用的;Docker 中的每一个镜像都是由一系列只读的层组成的,Dockerfile 中的每一个命令都会在已有的只读层上创建一个新的层:</p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p></section><pre style="margin-top: 0px;margin-bottom: 0px;padding: 0px;font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;background-color: rgb(255, 255, 255);"><code class="hljs nginx" style="padding: 0.5em;font-size: 14px;color: rgb(169, 183, 198);line-height: 18px;font-family: Consolas, Inconsolata, Courier, monospace;display: block;overflow-x: auto;letter-spacing: 0px;background: rgb(40, 43, 46);word-wrap: normal !important;overflow-y: auto !important;"><span class="hljs-attribute" style="font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">FROM</span> ubuntu:<span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">15</span>.<span class="hljs-number" style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">04</span><br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">COPY . /app<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">RUN make /app<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">CMD python /app/app.py<br style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"></code></pre><section class="mpa-template" data-mpa-category="body" data-mpa-color="#ffffff" data-mpa-template-id="167209"><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">容器中的每一层都只对当前容器进行了非常小的修改,上述的 Dockerfile 文件会构建一个拥有四层 layer 的镜像:</p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><p style="text-align: center;"><img class="" data-copyright="0" data-ratio="0.6" data-s="300,640" data-type="png" data-w="1200" src="http://img.chuansong.me/mmbiz_png/A1HKVXsfHNkwgchq0radWas6oSFP7WTakwFr5jmeBtiaKPVVZKwB46m2nqiasARVHWJUvDOvbIGk1m14bYanWFjQ/?" style=""></p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">当镜像被 docker run 命令创建时就会在镜像的最上层添加一个可写的层,也就是容器层,所有对于运行时容器的修改其实都是对这个容器读写层的修改。</p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><section mpa-is-content="t" style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">容器和镜像的区别就在于,所有的镜像都是只读的,而每一个容器其实等于镜像加上一个可读写的层,也就是同一个镜像可以对应多个容器。</section><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><p style="text-align: center;"><img class="" data-copyright="0" data-ratio="0.4" data-s="300,640" data-type="png" data-w="1200" src="http://img.chuansong.me/mmbiz_png/A1HKVXsfHNkwgchq0radWas6oSFP7WTakPQypDVCHth6IuFK1TT1lLVk9zYnPwwILHK8qTQBico3oibJnguS5rkw/?" style=""></p></section><h4 style="margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.2em;color: rgb(62, 62, 62);line-height: inherit;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: inherit;color: inherit;line-height: inherit;"></span></h4><section class="mpa-template" data-mpa-category="title" data-mpa-color="#ffffff" data-mpa-template-id="167215"><section class="" mpa-is-content="t" style="margin: 0px;padding: 0px 10px 0px 9px;color: rgb(60, 60, 60);font-size: 16px;font-weight: bold;letter-spacing: 1px;text-align: center;white-space: normal;line-height: 1.8;background: rgb(255, 255, 255);z-index: 10000;">AUFS</section><p><img class="" data-ratio="0.053125" data-type="png" data-w="640" src="https://i-blog.csdnimg.cn/blog_migrate/9a57787dc097b688f8ec4e62d638bca0.png" style="margin-right: 0px;margin-bottom: 0px;margin-left: 0px;padding: 0px;color: rgb(60, 60, 60);font-weight: bold;letter-spacing: 1px;text-align: center;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;display: inline-block;left: 0px;transform: rotateX(60deg);margin-top: 5px !important;height: auto !important;width: 632px !important;visibility: visible !important;" width="632px"></p><p><br></p></section><section class="mpa-template" data-mpa-category="body" data-mpa-color="#ffffff" data-mpa-template-id="167209"><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">UnionFS 其实是一种为 Linux 操作系统设计的用于把多个文件系统『联合』到同一个挂载点的文件系统服务。而 AUFS 即 Advanced UnionFS 其实就是 UnionFS 的升级版,它能够提供更优秀的性能和效率。</p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><section mpa-is-content="t" style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">AUFS 作为联合文件系统,它能够将不同文件夹中的层联合(Union)到了同一个文件夹中,这些文件夹在 AUFS 中称作分支,整个『联合』的过程被称为联合挂载(Union Mount):</section><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><p style="text-align: center;"><img class="" data-copyright="0" data-ratio="0.6416666666666667" data-s="300,640" data-type="png" data-w="1200" src="http://img.chuansong.me/mmbiz_png/A1HKVXsfHNkwgchq0radWas6oSFP7WTaHDZM7w7xEYFl1QFqJgzXicIfresgoulptibNsRHPUbpvDeWXs928AofA/?" style=""></p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;">每一个镜像层或者容器层都是 /var/lib/docker/ 目录下的一个子文件夹;在 Docker 中,所有镜像层和容器层的内容都存储在 /var/lib/docker/aufs/diff/ 目录中:</p><p style="margin: 0px;padding: 0px 10px 0px 9px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);text-align: justify;"><br></p></section><pre style="margin-top: 0px;margin-bottom: 0px;padding: 0px;font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;background-color: rgb(255, 255, 255);"><code class="hljs cs" style="padding: 0.5em;font-size: 14px;color: rgb(169, 183, 198);line-height: 18px;font-family: Consolas, Inconsolata, Courier, monospace;display: block;overflow-x: auto;letter-spacing: 0px;background: rgb(40, 43, 46);word-wrap: normal !important;overflow-y: auto !important;">$ ls /var/lib/docker/aufs/diff/00adcccc1a55a36a610a6ebb3e07cc35577f2f5a3b671be3dbc0e74db9ca691c 93604f232a831b22aeb372d5b11af8c8779feb96590a6dc36a80140e38e764d8
00adcccc1a55a36a610a6ebb3e07cc35577f2f5a3b671be3dbc0e74db9ca691c-init 93604f232a831b22aeb372d5b11af8c8779feb96590a6dc36a80140e38e764d8-init
019a8283e2ff6fca8d0a07884c78b41662979f848190f0658813bb6a9a464a90 93b06191602b7934fafc984fbacae02911b579769d0debd89cf2a032e7f35cfa
...
而 /var/lib/docker/aufs/layers/ 中存储着镜像层的元数据,每一个文件都保存着镜像层的元数据,最后的 /var/lib/docker/aufs/mnt/ 包含镜像或者容器层的挂载点,最终会被 Docker 通过联合的方式进行组装。
不同的存储驱动在存储镜像和容器文件时也有着完全不同的实现,有兴趣的读者可以在 Docker 的官方文档 Select a storage driver 中找到相应的内容。
想要查看当前系统的 Docker 上使用了哪种存储驱动只需要使用以下的命令就能得到相对应的信息:
$ docker info | grep Storage
Storage Driver: aufs
作者的这台 Ubuntu 上由于没有 overlay2 存储驱动,所以使用 aufs 作为 Docker 的默认存储驱动。
Docker 目前已经成为了非常主流的技术,已经在很多成熟公司的生产环境中使用,但是 Docker 的核心技术其实已经有很多年的历史了,Linux 命名空间、控制组和 UnionFS 三大技术支撑了目前 Docker 的实现,也是 Docker 能够出现的最重要原因。
相关链接:
https://github.com/docker/libnetwork/blob/master/docs/design.md
https://github.com/opencontainers/runc/blob/master/libcontainer/SPEC.md
https://forums.docker.com/t/does-the-docker-engine-use-chroot/25429
https://www.quora.com/Do-Docker-containers-use-a-chroot-environment
https://www.ibm.com/developerworks/cn/linux/l-cn-chroot/index.html
https://www.ibm.com/developerworks/cn/linux/1506_cgroup/index.html
原文链接:https://draveness.me/docker