本文介绍docker中的contanier,基于操作系统介绍什么是container。
进程(Processes)
Container是具有指定配置的Linux进程(processes)。我们进行如下操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
➜ ~ docker run -d --name=db redis:alpine
➜ ~ docker top db PID USER TIME COMMAND 2288 999 0:00 redis-server
➜ ~ ps aux | grep redis-server donggang 10761 0.0 0.0 4258876 200 s007 R+ 6:57下午 0:00.00 grep --color=auto --exclude-dir=.bzr --exclude-dir=CVS --exclude-dir=.git --exclude-dir=.hg --exclude-dir=.svn redis-server
➜ ~ pstree -c -p -A $(pgrep dockerd)
|
在linux系统中,一个container对应一个标准的进程。所有的container进程都是dockerd进程生成的。Linux是基于文件系统的,进程的信息都存储在/proc
目录中。
每个进程对应一个目录,可以通过进程ID获得对应的目录位置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
➜ ~ DBPID=$(pgrep redis-server) ➜ ~ echo Redis is $DBPID Redis is 6950
➜ ~ ls /proc/$DBPID attr cmdline environ io mem ns pagemap sched stack task autogroup comm exe limits mountinfo numa_maps patch_state schedstat stat timers auxv coredump_filter fd loginuid mounts oom_adj personality sessionid statm uid_map cgroup cpuset fdinfo map_files mountstats oom_score projid_map setgroups status wchan clear_refs cwd gid_map maps net oom_score_adj root smaps syscall
➜ ~ cat /proc/$DBPID/environ HOSTNAME=a1f8a38c84d4SHLVL=2REDIS_DOWNLOAD_SHA=6624841267e142c5d5d5be292d705f8fb6070677687c5aad1645421a936d22b3HOME=/home/redisPATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binREDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-5.0.6.tar.gzREDIS_VERSION=5.0.6PWD=/data
➜ ~ docker exec -it db env PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin HOSTNAME=a1f8a38c84d4 TERM=xterm REDIS_VERSION=5.0.6 REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-5.0.6.tar.gz REDIS_DOWNLOAD_SHA=6624841267e142c5d5d5be292d705f8fb6070677687c5aad1645421a936d22b3 HOME=/root
|
命名空间(namespace)
容器的一个基础部分就是namespace,namespace限制某个进程只能获取系统的某些部分,比如网络接口或这进程。
当一个容器开始运行时,容器运行时(container runtime)比如docker将会创建namespace,容器对应的进程将在这个namespace中运行,
有以下种类的namespace: Mount(mnt)、Process ID(pid)、Network(net)、Interprocess Communication(ipc)、UTC(hostnames)
、UserId(user)、Control group(cgroup)。有关Linux的namspace介绍移步于https://en.wikipedia.org/wiki/Linux_namespaces
我们可以通过工具unshare
创建一个隔离沙箱。使其中执行的进程不共享父进程的Pid等namespace。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| ➜ ~ sudo unshare --fork --pid --mount-proc bash
[root@master ~] PID TTY TIME CMD 1 pts/0 00:00:00 bash 12 pts/0 00:00:00 ps [root@master ~]
exit
➜ ~ ps PID TTY TIME CMD 4673 pts/0 00:00:00 zsh 9088 pts/0 00:00:00 ps 16860 pts/0 00:00:00 zsh 18119 pts/0 00:00:00 zsh
|
Namespace本质上仍然是文件,它存储在磁盘中,所以Namespace是可以共享的。工具nsenter可以在指定的namespace运行一个程序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| ➜ ~ ls -lha /proc/$DBPID/ns 总用量 0 dr-x--x--x 2 polkitd 1000 0 10月 30 19:17 . dr-xr-xr-x 9 polkitd 1000 0 10月 30 19:17 .. lrwxrwxrwx 1 polkitd 1000 0 10月 30 19:18 ipc -> ipc:[4026533033] lrwxrwxrwx 1 polkitd 1000 0 10月 30 19:18 mnt -> mnt:[4026533031] lrwxrwxrwx 1 polkitd 1000 0 10月 30 19:17 net -> net:[4026533036] lrwxrwxrwx 1 polkitd 1000 0 10月 30 19:18 pid -> pid:[4026533034] lrwxrwxrwx 1 polkitd 1000 0 10月 30 19:18 user -> user:[4026531837] lrwxrwxrwx 1 polkitd 1000 0 10月 30 19:18 uts -> uts:[4026533032]
➜ ns nsenter --target $DBPID -m -u -i -p /bin/ps aux PID USER TIME COMMAND 1 redis 1:03 redis-server 37 root 0:00 /bin/ps aux
|
docker可以通过语法container:<container-name>
共享namespace,下面的例子中我们创建一个web容器,该容器网络共享db container的网络namespace。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| ➜ ns docker run -d --name=web --net=container:db nginx:alpine Unable to find image 'nginx:alpine' locally alpine: Pulling from library/nginx 89d9c30c1d48: Already exists 110ad692b782: Pull complete Digest: sha256:085e84650dbe56f27ca3ed00063a12d5b486e40c3d16d83c4e6c2aad1e4045ab Status: Downloaded newer image for nginx:alpine 4f982d745f346a7087c42c55e455448d21794641df7005c4d76299f781ba474f ➜ ns WEBPID=$(pgrep nginx | tail -n1) ➜ ns echo nginx is $WEBPID nginx is 21499 ➜ ns ls -alh /proc/$WEBPID/ns | grep net lrwxrwxrwx 1 101 101 0 10月 31 09:19 net -> net:[4026533036] ➜ ns ls -alh /proc/$DBPID/ns | grep net lrwxrwxrwx 1 polkitd 1000 0 10月 30 19:17 net -> net:[4026533036]
|
Chroot
Chroot能够是容器进程拥有独立的根目录(root directory/
),chroot --help
能够更改当前
运行的进程及其子进程的根目录。 chroot不能够起到隔离的作用,仍然可以通过相对路径访问新根以外的地址
Cgroups(Control Groups)
CGroups技术限制进程消耗资源,
Secomp/AppArmor
AppArmor描述了进程可以访问系统中哪些部分。Seccomp提供了限制可以进行哪些系统调用,阻止安装内核模块或更改文件权限等方面的功能。
参考
- Docker容器技术详解