首页私人日誌Docker-container详解

Docker-container详解

admin 10-15 15:07 333次浏览

本文介绍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 /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   39;nginx:alpine  39; 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-container详解
SSM如何搭建项目 kubernetes-api-conventions
相关内容