资讯专栏INFORMATION COLUMN

Docker-container详解

社区管理员 / 856人阅读

本文介绍docker中的contanier,基于操作系统介绍什么是container。

进程(Processes)

Container是具有指定配置的Linux进程(processes)。我们进行如下操作:

## 启动一个redis进程
➜  ~ docker run -d --name=db redis:alpine

## 显示容器运行的进程
➜  ~ docker top db
PID                 USER                TIME                COMMAND
2288                999                 0:00                redis-server

## 查看系统是否存在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

## 查看dockerd的进程树
➜  ~ pstree -c -p -A $(pgrep dockerd)

在linux系统中,一个container对应一个标准的进程。所有的container进程都是dockerd进程生成的。Linux是基于文件系统的,进程的信息都存储在/proc目录中。 每个进程对应一个目录,可以通过进程ID获得对应的目录位置。

## 设置DBPID变量,方便后续测试
➜  ~ 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

## 通过文件获取容器db的目录
➜  ~ 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 api获取,
➜  ~ 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

## bash运行在"沙箱中"
➜  ~ sudo unshare --fork --pid --mount-proc bash

## 打印进程信息
[root@master ~]# ps
  PID TTY          TIME CMD
    1 pts/0    00:00:00 bash
   12 pts/0    00:00:00 ps
[root@master ~]# exit
## 退出沙箱
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

我们可以通过工具unshare创建一个隔离沙箱。使其中执行的进程不共享父进程的Pid等namespace。

Namespace本质上仍然是文件,它存储在磁盘中,所以Namespace是可以共享的。工具nsenter可以在指定的namespace运行一个程序。

## 获取容器db的namespace资源
➜  ~ 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]

## 在container db中执行ps程序
➜  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。

➜  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提供了限制可以进行哪些系统调用,阻止安装内核模块或更改文件权限等方面的功能。


文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/127926.html

相关文章

  • 图表君聊Docker-Container

    摘要:利用镜像创建并启动一个容器分配一个文件系统,并在只读的镜像层外层挂接一个写读写层。容器的启动过程,对于理解容器至关重要,需要深入的理解。同时,对于终止状态的容器,我们可以采用来启动。欢迎订阅我的公众号,第一时间获取图表君的新文章。 上篇文章我们介绍了Docker三大概念中的Image,这篇我们来介绍Container,上篇文章中我们了解到了Image是运行在Container中的,实际...

    paney129 评论0 收藏0
  • 阿里 2021 版最全 Java 并发编程笔记,看完我才懂了“内卷”的真正意义

    摘要:纯分享直接上干货操作系统并发支持进程管理内存管理文件系统系统进程间通信网络通信阻塞队列数组有界队列链表无界队列优先级有限无界队列延时无界队列同步队列队列内存模型线程通信机制内存共享消息传递内存模型顺序一致性指令重排序原则内存语义线程 纯分享 , 直接上干货! 操作系统并发支持 进程管理内存管...

    不知名网友 评论0 收藏0

发表评论

0条评论

社区管理员

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<