Docker原理11

Linux Namespace 11

AUFS文件系统17

重新理解Docker的各种命令18

Docker原理

Linux Namespace

docker是一个容器引擎,容器就要求对进程空间、用户空间、网络空间、硬盘空间等等做一些隔离,docker的底层是使用LXC实现的,LXC则使用Linux Namespace技术对各种技术做隔离。

Linux Namespace是Linux提供的一种内核级别环境隔离的方法, 隔离的资源包括:Mount、UTS、IPC、PID、Network、User。 篇幅限制,本文只介绍UTS、PID和Mount的隔离。

网上找来一段代码:

#define _GNU_SOURCE

#include <sys/types.h>

#include <sys/wait.h>

#include <stdio.h>

#include <sched.h>

#include <signal.h>

#include <unistd.h>

#include <errno.h>

/* 定义一个给 clone 用的栈,栈大小1M */

#define STACK_SIZE (1024 * 1024)

static char container_stack[STACK_SIZE];

char* const container_args[] = {

"/bin/bash",

NULL

};

int container_main(void* arg)

{

printf("Container - inside the container!\n");

/* 直接执行一个shell,以便我们观察这个进程空间里的资源是否被隔离了 */

execv(container_args[], container_args);

printf("Something's wrong!\n");

return ;

}

int main()

{

printf("Parent - start a container!\n");

/* 调用clone函数,其中传出一个函数,还有一个栈空间的(为什么传尾指针,因为栈是反着的) */

int container_pid = clone(container_main, container_stack+STACK_SIZE, SIGCHLD, NULL);

if (container_pid < )

{

fprintf(stderr, "clone failed WTF!!!! %s\n", strerror(errno));

return -;

}

/* 等待子进程结束 */

waitpid(container_pid, NULL, );

printf("Parent - container stopped!\n");

return ;

}

代码比较简单,就是用clone系统调用生成一个新的子进程,并运行container_main函数。

运行结果:

$./simple_clone

Parent - start a container!

Container - inside the container!

$ps aux |head

USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND

root  0.0 0.0   ? Ss : : /usr/lib/systemd/systemd --switched-root --system --deserialize

root  0.0 0.0   ? S : : [kthreadd]

root  0.0 0.0   ? S : : [ksoftirqd/]

root  0.0 0.0   ? S : : [kworker/u30:]

root  0.0 0.0   ? S : : [migration/]

root  0.0 0.0   ? S : : [rcu_bh]

root  0.0 0.0   ? S : : [rcuob/]

root  0.0 0.0   ? S : : [rcuob/]

root  0.0 0.0   ? S : : [rcuob/]

可以看到,在进入了子进程后看到的跟父进程完全一样。

我们往上段代码的clone函数中加入CLONE_NEWUTS flag, 并且在container_main函数中设置主机名:

#define _GNU_SOURCE

#include <sys/types.h>

#include <sys/wait.h>

#include <stdio.h>

#include <sched.h>

#include <signal.h>

/* 定义一个给 clone 用的栈,栈大小1M */

#define STACK_SIZE (1024 * 1024)

static char container_stack[STACK_SIZE];

char* const container_args[] = {

"/bin/bash",

NULL

};

int container_main(void* arg)

{

printf("Container - inside the container!\n");

sethostname("container",); /* 设置hostname */

/* 直接执行一个shell,以便我们观察这个进程空间里的资源是否被隔离了 */

execv(container_args[], container_args);

printf("Something's wrong!\n");

return ;

}

int main()

{

printf("Parent - start a container!\n");

/* 调用clone函数,其中传出一个函数,还有一个栈空间的(为什么传尾指针,因为栈是反着的) */

int container_pid = clone(container_main, container_stack+STACK_SIZE,

CLONE_NEWUTS | SIGCHLD, NULL); /*启用CLONE_NEWUTS Namespace隔离 */

if (container_pid < )

{

printf("%d clone failed WTF!!!! %s\n", container_pid, strerror(errno));

return -;

}

/* 等待子进程结束 */

waitpid(container_pid, NULL, );

printf("Parent - container stopped!\n");

return ;

}

运行:

$sudo ./uts

Parent - start a container!

Container - inside the container!

#hostname

container

#exit

exit

Parent - container stopped!

$

可以看到子进程中的hostname变成了container

我们接着在clone函数中加入CLONE_NEWPID flag, 并在主子进程中都打出pid:

#define _GNU_SOURCE

#include <sys/types.h>

#include <sys/wait.h>

#include <stdio.h>

#include <sched.h>

#include <signal.h>

#include <unistd.h>

#include <errno.h>

/* 定义一个给 clone 用的栈,栈大小1M */

#define STACK_SIZE (1024 * 1024)

static char container_stack[STACK_SIZE];

char* const container_args[] = {

"/bin/bash",

NULL

};

int container_main(void* arg)

{

printf("Container [%5d] - inside the container!\n", getpid());

sethostname("container",); /* 设置hostname */

/* 直接执行一个shell,以便我们观察这个进程空间里的资源是否被隔离了 */

execv(container_args[], container_args);

printf("Something's wrong!\n");

return ;

}

int main()

{

printf("Parent [%5d] - start a container!\n", getpid());

/* 调用clone函数,其中传出一个函数,还有一个栈空间的(为什么传尾指针,因为栈是反着的) */

int container_pid = clone(container_main, container_stack+STACK_SIZE,

CLONE_NEWUTS | CLONE_NEWPID | SIGCHLD, NULL); /*启用CLONE_NEWUTS Namespace隔离 */

if (container_pid < )

{

printf("%d clone failed WTF!!!! %s\n", container_pid, strerror(errno));

return -;

}

/* 等待子进程结束 */

waitpid(container_pid, NULL, );

printf("Parent - container stopped!\n");

return ;

}

运行:

$sudo ./pid

Parent [] - start a container!

Container [ ] - inside the container!

#ps aux |head

USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND

root  0.0 0.0   ? Ss : : /usr/lib/systemd/systemd --switched-root --system --deserialize

root  0.0 0.0   ? S : : [kthreadd]

root  0.0 0.0   ? S : : [ksoftirqd/]

root  0.0 0.0   ? S : : [kworker/u30:]

root  0.0 0.0   ? S : : [migration/]

root  0.0 0.0   ? S : : [rcu_bh]

root  0.0 0.0   ? S : : [rcuob/]

root  0.0 0.0   ? S : : [rcuob/]

root  0.0 0.0   ? S : : [rcuob/]

#

可以看到子进程的pid变成了1。 这个变化很重要,意味着子进程后面的所有进程,都是挂在这个PID为1的进程后面。看起来就像是一个新的系统,而该子进程就像是pid为1的init进程。

但是上面的ps结果也看到,子进程仍然可以看以父进程的所有进程,原因是主子进程中的ps命令都是去读的/proc文件系统,我们需要对子进程单独mount一个proc文件系统出来。

接着改代码,给clone函数加一个CLONE_NEWNS flag, 并在子进程中运行 mount -t /proc proc /proc命令:

#define _GNU_SOURCE

#include <sys/types.h>

#include <sys/wait.h>

#include <stdio.h>

#include <sched.h>

#include <signal.h>

#include <unistd.h>

#include <errno.h>

/* 定义一个给 clone 用的栈,栈大小1M */

#define STACK_SIZE (1024 * 1024)

static char container_stack[STACK_SIZE];

char* const container_args[] = {

"/bin/bash",

NULL

};

int container_main(void* arg)

{

printf("Container [%5d] - inside the container!\n", getpid());

sethostname("container",); /* 设置hostname */

/* 重新mount proc文件系统到 /proc下 */

system("mount -t proc proc /proc");

/* 直接执行一个shell,以便我们观察这个进程空间里的资源是否被隔离了 */

execv(container_args[], container_args);

printf("Something's wrong!\n");

return ;

}

int main()

{

printf("Parent [%5d] - start a container!\n", getpid());

/* 调用clone函数,其中传出一个函数,还有一个栈空间的(为什么传尾指针,因为栈是反着的) */

int container_pid = clone(container_main, container_stack+STACK_SIZE,

CLONE_NEWUTS | CLONE_NEWPID | CLONE_NEWNS | SIGCHLD, NULL); /*启用CLONE_NEWUTS Namespace隔离 */

if (container_pid < )

{

printf("%d clone failed WTF!!!! %s\n", container_pid, strerror(errno));

return -;

}

/* 等待子进程结束 */

waitpid(container_pid, NULL, );

printf("Parent - container stopped!\n");

return ;

}

运行:

$sudo ./mount

Parent [] - start a container!

Container [ ] - inside the container!

#ps aux

USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND

root  1.3 0.0   pts/ S : : /bin/bash

root  0.0 0.0   pts/ R+ : : ps aux

可以看到,ps也只能看到子进程中的进程了。
这个时候还可以看一下,父进程实际上可以看到子进程的进程,并且pid不为1,而子进程就像一只井底之蛙,只能看到自己被隔离出来的进程。

$ps aux |grep /bin/bash

root  0.0 0.0   pts/ S+ : : /bin/bash

lijun.s+  0.0 0.0   pts/ S+ : : grep --color=auto /bin/bash

AUFS文件系统

docker使用的文件系统有aufs、devicemapper等,aufs是docker的首选文件系统,但是可惜没有合到Linux主干代码中,不过主流的系统像ubuntu都是支持的。 而像centos这种系统不支持aufs, 就只能使用devicemapper了。 
由于aufs对理解docker的layer(层)的概念更容易一些,这里介绍下aufs文件系统。

闲话不多说,找个ubuntu
12.04版本的系统做如下测试:
建两个目录d1,d2
d1中有文件a和b,
d2中有文件b和c:

root@vultr:~/test_aufs/test1# ls -R

d1 d2

./d1:

a b

./d2:

b c

其中每个文件的值为: d1/a -> 'a', d1/b -> 'b1', d2/b -> 'b2', d2/c -> 'c'
用d1,
d2 mount一个aufs文件系统的目录:

root@vultr:~/test_aufs/test1# mount -t aufs -o dirs=./d1:./d2 none ./mnt

root@vultr:~/test_aufs/test1# ls mnt/

a b c

root@vultr:~/test_aufs/test1# cat mnt/b

b1

可以看到mnt/b中的值为d1/b中的值,而d2/b被丢掉了。 可见mnt多个目录同一个文件名的文件,只保留按顺序第一次出现的那个。

再尝试着更改文件内容:

root@vultr:~/test_aufs/test1/mnt# echo 'new_a' > a

root@vultr:~/test_aufs/test1/mnt# cat ../d1/a

new_a

root@vultr:~/test_aufs/test1/mnt# echo 'new_b' > b

root@vultr:~/test_aufs/test1/mnt# cat ../d1/b

new_b

root@vultr:~/test_aufs/test1/mnt# cat ../d2/b

b2

root@vultr:~/test_aufs/test1/mnt# echo 'new_c' > c

root@vultr:~/test_aufs/test1/mnt# cat ../d2/c

c

root@vultr:~/test_aufs/test1/mnt# cat ../d1/c

new_c

root@vultr:~/test_aufs/test1/mnt#

前几个都好理解,注意往mnt/c中写一段内容后,d2/c的内容并没有改变,反而在d1目录下面出现了一个c,内容为mnt/c的内容,好诡异,这是什么逻辑呢。

原来mount aufs文件系统的目录时,最前面的目录是可写的,而后面的都是只读的,往mnt下面的文件写内容时,会先找到第一个可写的目录,然后更新其内容, 如果文件不存在则会建一个。 d2/c被mnt成只读的了不会改变内容,而且d1目录是可写的,所以会在d1下面新生成一个c文件。

我们还可以试着mount aufs时在目录后面加上:rw, :ro来表示读写和只读,会有不同的结果,但是原理与上段描述的一样,可以猜猜结果会是怎样。

不知道大家有没有用过Ubuntu或Fedora的live系统盘,只要插上光盘就可以运行系统,而且还可以写数据,只不过系统退出后变更的文件就找不到了。当时觉得很神奇,现在想想也正是使用了aufs这种文件系统的特性,只要将光盘和硬盘mount在一起,就可以看上去在光盘上读写数据了。

回到docker,docker的镜像其实就是一些只读层,而容器是在docker镜像上加了一层读写层,这样就可以在不更改镜像的基础上还能像普通vm一样读写数据。 网上有张图比较好:

aaarticlea/jpeg;base64,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" alt="" name="Image1" width="547" height="184" align="bottom" border="0" />

重新理解Docker的各种命令

我们了解了docker的文件系统及namespace功能后,再试图重新理解一下docker的几个命令:

docker images : 列出所有顶层的只读镜像

docker run : 先是利用只读的镜像外加一层可读写的层,并且加了一个被隔离的进程空间来创建了一个容器,然后运行指定的程序。

docker stop : 保留可读写层,收回隔离的进程空间。

docker ps -a : 列出所有包含读写层的容器,包含stop(Exit)状态的。

docker commit : 将当前容器的只读层加可读写层一起产生一个新的只读层做为镜像。

参考:

1. Docker概述

2. docker的使用及原理 知乎

05-06 10:18