Learning Docker Part 003 Dokcer容器实战

如何运行容器

有三种方式可以指定容器启动时的命令

  1. CMD指令
  2. ENTRYPOINT 指令
  3. docker run命令行中指定
root@fbo-virtual-machine:~# docker run ubuntu pwd
/
root@fbo-virtual-machine:~# docker ps -a
CONTAINER ID        IMAGE               COMMAND              CREATED             STATUS                      PORTS                   NAMES
9cad7521bf55        ubuntu              "pwd"                11 seconds ago      Exited (0) 10 seconds ago    
root@fbo-virtual-machine:~# docker run --name "my_http_server" -d httpd
231a01fe0dc5322836d25437f38ddd518814b70f4386b801cf6d256c5f72131d
root@fbo-virtual-machine:~# docker ps
CONTAINER ID        IMAGE               COMMAND              CREATED             STATUS              PORTS               NAMES
231a01fe0dc5        httpd               "httpd-foreground"   6 seconds ago       Up 5 seconds        80/tcp              my_http_server

如何进入容器

有两种方式可以进入到docker容器中

  • docker attch
  • docker exec -it

docker attach

root@fbo-virtual-machine:~# docker run -d ubuntu /bin/bash -c "while true;do sleep 1;echo I_am_incontainer;done"
51479e20192cf9765a954ea21a0e9c4b3015dc1c0e03e37458f6353d79b3fd24
root@fbo-virtual-machine:~# docker ps 
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
51479e20192c        ubuntu              "/bin/bash -c 'whi..."   4 seconds ago       Up 3 seconds                            nervous_clarke
231a01fe0dc5        httpd               "httpd-foreground"       5 minutes ago       Up 5 minutes        80/tcp              my_http_server
root@fbo-virtual-machine:~# docker attach 51479
I_am_incontainer
I_am_incontainer
I_am_incontainer
I_am_incontainer

docker exec

root@fbo-virtual-machine:~# docker run -d ubuntu /bin/bash -c "while true;do sleep 1;echo I_am_incontainer;done"
60db0f40851dfe5af74095724f917f231ccdc13d526cd5265d88c43a9156db42
root@fbo-virtual-machine:~# docker exec -it 60db /bin/bash
root@60db0f40851d:/# ps -aux
USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root          1  0.0  0.0  18028  2836 ?        Ss   01:56   0:00 /bin/bash -c while true;do sleep 1;echo I_am_incontainer;
root         45  0.2  0.0  18244  3208 pts/0    Ss   01:56   0:00 /bin/bash
root         61  0.0  0.0   4380   796 ?        S    01:56   0:00 sleep 1
root         62  0.0  0.0  34424  2784 pts/0    R+   01:56   0:00 ps -aux
root@60db0f40851d:/# exit
exit

attach vs exec

  1. attach直接进入启动命令的终端
  2. exec在容器中打开新的进程
  3. attach会直接显示启动命令的输出,使用docker logs -f也可以查看启动命令的输出
  4. attach进入容器后退出会终止容器,exec则不会

容器功能划分

按照用途划分,容器分为:

  1. 服务类容器: 以deamon形式运行,外提供服务。比容 web server,数据等,通过-d以后台方式运行,要排查问题时,通过exec -it进入容器。
  2. 工具类容器: 能够给我们提供一个临时的工作环境,通常以run -it方式运行,工具类容器多用基础镜像,如busybox、ubuntu、debain等

容器的常用操作

start、stop、restart

## 1. 停止容器
root@fbo-virtual-machine:~# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
a2cf56b541b9        ubuntu              "/bin/bash -c 'whi..."   38 seconds ago      Up 36 seconds                           romantic_curran
root@fbo-virtual-machine:~# docker stop romantic_curran 
romantic_curran
root@fbo-virtual-machine:~# docker run -d --name http-kill httpd
8db9c7bff6497a1f7701976fcde3fd27197e326e0ad8684269171bff13af9807
## 2. 杀掉容器
root@fbo-virtual-machine:~# docker ps
CONTAINER ID        IMAGE               COMMAND              CREATED             STATUS              PORTS               NAMES
8db9c7bff649        httpd               "httpd-foreground"   8 seconds ago       Up 6 seconds        80/tcp              http-kill
root@fbo-virtual-machine:~# docker kill http-kill
http-kill
root@fbo-virtual-machine:~# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
## 3. 启动关闭的容器
root@fbo-virtual-machine:~# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                       PORTS               NAMES
8db9c7bff649        httpd               "httpd-foreground"       3 minutes ago       Exited (137) 2 minutes ago                       http-kill
a2cf56b541b9        ubuntu              "/bin/bash -c 'whi..."   9 minutes ago       Exited (137) 8 minutes ago                       romantic_curran
root@fbo-virtual-machine:~# docker start http-kill
http-kill
root@fbo-virtual-machine:~# docker ps
CONTAINER ID        IMAGE               COMMAND              CREATED             STATUS              PORTS               NAMES
8db9c7bff649        httpd               "httpd-foreground"   3 minutes ago       Up 2 seconds        80/tcp              http-kill
## 4. 重启容器
root@fbo-virtual-machine:~# docker restart http-kill
http-kill
## 5. 有时候容器会某种错误而终止,如果我们希望docker能够自动重启。在启动时设置--restart就可以达到这个效果 
##    --restart=always 意味着无论容器因何种原因退出(包括正常退出),就立即重启。该参数的形式还可以是 
##    --restart=on-failure:3,意思是如果启动进程退出代码非0,则重启容器,最多重启3次。
root@fbo-virtual-machine:~# docker run -d --restart=always --name http-restart httpd
3bf7b46f57f9f039409f9d4f29983c2af4e1379a80d42102226982be8cfaa949
root@fbo-virtual-machine:~# docker ps 
CONTAINER ID        IMAGE               COMMAND              CREATED             STATUS              PORTS               NAMES
3bf7b46f57f9        httpd               "httpd-foreground"   2 seconds ago       Up 2 seconds        80/tcp              http-restart
8db9c7bff649        httpd               "httpd-foreground"   18 minutes ago      Up 13 minutes       80/tcp              http-kill
root@fbo-virtual-machine:~# docker exec -it http-restart /bin/bash
root@3bf7b46f57f9:/usr/local/apache2# ps -aux | grep httpd | grep -v grep | awk '{print $2}' | xargs -I {} kill -9 {}
root@3bf7b46f57f9:/usr/local/apache2# ps -aux
USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root          1  0.0  0.1  77212  4436 ?        Ss   02:44   0:00 httpd -DFOREGROUND
root         90  0.0  0.0  20252  3224 pts/0    Ss   02:45   0:00 /bin/bash
daemon      208  0.0  0.1 366392  5472 ?        Sl   02:47   0:00 httpd -DFOREGROUND
root        236  0.0  0.0  17500  2092 pts/0    R+   02:47   0:00 ps -aux
root@3bf7b46f57f9:/usr/local/apache2# exit
exit

pause\unpause 容器

root@fbo-virtual-machine:~# docker pause http-restart 
http-restart
root@fbo-virtual-machine:~# docker unpause http-restart
http-restart
root@fbo-virtual-machine:~# docker ps
CONTAINER ID        IMAGE               COMMAND              CREATED             STATUS              PORTS               NAMES
3bf7b46f57f9        httpd               "httpd-foreground"   21 minutes ago      Up 20 minutes       80/tcp              http-restart
8db9c7bff649        httpd               "httpd-foreground"   40 minutes ago      Up 34 minutes       80/tcp              http-kill

删除容器

## 删除多个容器
root@fbo-virtual-machine:~# docker rm 8db9c a2cf56
8db9c
a2cf56
## 删除所有已经退出的容器
root@fbo-virtual-machine:~# docker ps -aq -f status=exited | xargs docker rm
a5c033c850c3
8fb39e630f8f
0635f8a0c056
2b4b2f4ac0ed
cec27c3847c8
ccd36895e0e3
79b85cdb3e9a
e1fb45c8c949
1cf4c2e2629c
root@fbo-virtual-machine:~# for i in `seq 10`;do docker run busybox &> /dev/null;done 
root@fbo-virtual-machine:~# docker ps -a
CONTAINER ID        IMAGE               COMMAND              CREATED             STATUS                     PORTS               NAMES
d02035d85b45        busybox             "sh"                 4 seconds ago       Exited (0) 3 seconds ago                       wizardly_swartz
d528c3af182f        busybox             "sh"                 5 seconds ago       Exited (0) 4 seconds ago                       stupefied_boyd
63ceda326bf5        busybox             "sh"                 6 seconds ago       Exited (0) 5 seconds ago                       jovial_ramanujan
ab0e240a435a        busybox             "sh"                 6 seconds ago       Exited (0) 5 seconds ago                       nifty_mayer
6cc0355813f4        busybox             "sh"                 7 seconds ago       Exited (0) 6 seconds ago                       agitated_bhaskara
15b4bd171497        busybox             "sh"                 7 seconds ago       Exited (0) 6 seconds ago                       hardcore_allen
3be63fb9598a        busybox             "sh"                 8 seconds ago       Exited (0) 7 seconds ago                       quizzical_wozniak
6c9152cee5e2        busybox             "sh"                 8 seconds ago       Exited (0) 7 seconds ago                       sleepy_raman
7649ac28a45f        busybox             "sh"                 9 seconds ago       Exited (0) 8 seconds ago                       keen_pare
30d36cf4044c        busybox             "sh"                 9 seconds ago       Exited (0) 8 seconds ago                       kind_bardeen
3bf7b46f57f9        httpd               "httpd-foreground"   32 minutes ago      Up 31 minutes              80/tcp              http-restart
root@fbo-virtual-machine:~# docker rm -v $(docker ps -aq -f status=exited)
d02035d85b45
d528c3af182f
63ceda326bf5
ab0e240a435a
6cc0355813f4
15b4bd171497
3be63fb9598a
6c9152cee5e2
7649ac28a45f
30d36cf4044c

容器的生命周期

Learning Docker Part 003 Dokcer容器实战_第1张图片
容器生命周期

限制容器对资源的使用

一个docker host上会运行若干个容器,每个容器都要消耗cpu、内存以及磁盘IO资源,为避免某个容器因为占中过多资源而影响其他容器乃至整个host的性能,我们必须要对容器资源使用进行限制。

内存限额

容器的内存包括两部分:物理内容和swap内存

  1. -m或者--memory:设置内存的使用限额,如100M、2G;
  2. --memory-swap: 设置内存+swap的使用限额
## 1. 指定内存限额启动ubuntu
root@fbo-virtual-machine:~# docker run -m 200M --memory-swap 300M ubuntu
root@fbo-virtual-machine:~# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
root@fbo-virtual-machine:~# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
38f99d7e9cc5        ubuntu              "/bin/bash"         5 seconds ago       Exited (0) 4 seconds ago                       objective_khorana
## 2. 通过progrium/stress镜像来看容器的内存如何分配。该镜像可以用来对容
##    器执行压力测试。
##    --vm 1 : 启动一个内存工作线程
##    --vm-bytes 280M :每个线程分配280M 
root@fbo-virtual-machine:~# docker run -it -m 200M --memory-swap=300M progrium/stress --vm 1 --vm-bytes 280M
stress: info: [1] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd
stress: dbug: [1] using backoff sleep of 3000us
stress: dbug: [1] --> hogvm worker 1 [5] forked
stress: dbug: [5] allocating 293601280 bytes ...
stress: dbug: [5] touching bytes in strides of 4096 bytes ...
stress: dbug: [5] freed 293601280 bytes
stress: dbug: [5] allocating 293601280 bytes ...
stress: dbug: [5] touching bytes in strides of 4096 bytes ...
stress: dbug: [5] freed 293601280 bytes
stress: dbug: [5] allocating 293601280 bytes ...
stress: dbug: [5] touching bytes in strides of 4096 bytes ...
## 3. 让线程分配内存超过容器的配额,容器将会退出
root@fbo-virtual-machine:~# docker run -it -m 200M --memory-swap=300M progrium/stress --vm 1 --vm-bytes 310M
stress: info: [1] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd
stress: dbug: [1] using backoff sleep of 3000us
stress: dbug: [1] --> hogvm worker 1 [5] forked
stress: dbug: [5] allocating 325058560 bytes ...
stress: dbug: [5] touching bytes in strides of 4096 bytes ...
stress: FAIL: [1] (416) <-- worker 5 got signal 9
stress: WARN: [1] (418) now reaping child worker processes
stress: FAIL: [1] (422) kill error: No such process
stress: FAIL: [1] (452) failed run completed in 2s

CPU权重

默认情况下,容器对cpu的使用没有限制,可以使用-c或者--cpu-shares设置容器使用CPU的权重,如果不指定,默认权重为1024.

## 1. 启动container-a,cpu权重1024
root@fbo-virtual-machine:~# docker run -it --name container-a -c 1024 progrium/stress --cpu 1
stress: info: [1] dispatching hogs: 1 cpu, 0 io, 0 vm, 0 hdd
stress: dbug: [1] using backoff sleep of 3000us
stress: dbug: [1] --> hogcpu worker 1 [5] forked
## 2. 启动container-b,cpu权重512
root@fbo-virtual-machine:~# docker run -it --name container-b -c 512 progrium/stress --cpu 1
stress: info: [1] dispatching hogs: 1 cpu, 0 io, 0 vm, 0 hdd
stress: dbug: [1] using backoff sleep of 3000us
stress: dbug: [1] --> hogcpu worker 1 [5] forked
## 3. 在host使用top观察cpu消耗情况,container-a恰好是container-b的两倍
fbo@fbo-virtual-machine:~$ top
top - 14:34:18 up 43 min,  3 users,  load average: 1.96, 0.96, 0.38
Tasks: 214 total,   3 running, 211 sleeping,   0 stopped,   0 zombie
%Cpu(s):100.0 us,  0.0 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  4025468 total,  3194544 free,   379596 used,   451328 buff/cache
KiB Swap:  4191228 total,  4149236 free,    41992 used.  3343756 avail Mem 

   PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND                                                                                                
  3888 root      20   0    7312    100      0 R 66.4  0.0   2:52.13 stress                                                                                                 
  4008 root      20   0    7312     96      0 R 33.2  0.0   0:48.75 stress
## 4. 停掉container-a后container-b将会抢占cpu
fbo@fbo-virtual-machine:~$ sudo docker stop container-a
container-a
fbo@fbo-virtual-machine:~$ top
top - 14:40:27 up 50 min,  3 users,  load average: 1.72, 1.65, 0.91
Tasks: 212 total,   2 running, 210 sleeping,   0 stopped,   0 zombie
%Cpu(s): 20.3 us,  0.8 sy,  0.0 ni, 76.7 id,  2.1 wa,  0.0 hi,  0.1 si,  0.0 st
KiB Mem :  4025468 total,  3203672 free,   370764 used,   451032 buff/cache
KiB Swap:  4191228 total,  4149236 free,    41992 used.  3352948 avail Mem 

   PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND                                                                                                
  4008 root      20   0    7312     96      0 R 93.8  0.0   3:04.58 stress    

容器IO限制

docker可以通过设置block IO权重、限制bqs和iops的方式控制容器读写磁盘的带宽。

block IO 权重

默认情况下所有容器能够平等地读写磁盘,可以通过--blkio-weight参数来改变block IO的优先级。

## 启动container-a和container-b,同时写入磁盘,由于container-a的权重大于
## container-b,测试发现container-a的IO资源要优先于container-b  
root@fbo-virtual-machine:~# docker run -it --name container-a --blkio-weight 600 ubuntu
root@ca7eb3cf1b3f:/# time dd if=/dev/zero of=test.out bs=1M count=800 oflag=direct
800+0 records in
800+0 records out
838860800 bytes (839 MB, 800 MiB) copied, 15.1962 s, 55.2 MB/s

real    0m15.832s
user    0m0.012s
sys 0m1.428s
root@fbo-virtual-machine:~# docker run -it --name container-b --blkio-weight 300 ubuntu
root@b6d222694ca5:/# time dd if=/dev/zero of=test.out bs=1M count=800 oflag=direct
800+0 records in
800+0 records out
838860800 bytes (839 MB, 800 MiB) copied, 18.8524 s, 44.5 MB/s

real    0m19.487s
user    0m0.004s
sys 0m1.348s

限制bqs和iops

bps是bytes per second,每秒读写的数据量
iops是io per second,每秒IO次数

可以通过下列参数来控制bqs和iops
--device-read-bqs,限制读某个设备的bps
--device-write-bqs,限制写某个设备的bps
--device-read-iops,限制读某个设备的iops
--device-write-iops,限制写某个设备的iops

## 指定限制bps后,写速率不会超过限定值
root@fbo-virtual-machine:~# docker run -it --device-write-bps /dev/sda:30MB ubuntu
root@9e5f5ecfe864:/# time dd if=/dev/zero of=test.out bs=1M count=800 oflag=direct 
800+0 records in
800+0 records out
838860800 bytes (839 MB, 800 MiB) copied, 40.8922 s, 20.5 MB/s

real    0m40.894s
user    0m0.000s
sys 0m0.940s
## 我们来测试下本机的bps
root@fbo-virtual-machine:~# time dd if=/dev/zero of=test.out bs=1M count=800 oflag=direct
800+0 records in
800+0 records out
838860800 bytes (839 MB, 800 MiB) copied, 0.328587 s, 2.6 GB/s

real    0m0.759s
user    0m0.004s
sys 0m0.212s

容器配额的底层实现

cgroup实现资源配额,namespace实现资源隔离

cgroup

cgroup全称controller Group。linux操作系统通过cgroup可以设置进程使用CPU、内存和IO资源的限额。

## 1. 启动一个限定了cpu权重的容器
root@fbo-virtual-machine:~# docker run -it --cpu-shares 512 progrium/stress -c 1
stress: info: [1] dispatching hogs: 1 cpu, 0 io, 0 vm, 0 hdd
stress: dbug: [1] using backoff sleep of 3000us
stress: dbug: [1] --> hogcpu worker 1 [5] forked
## 2. 找到容器的id
root@fbo-virtual-machine:~# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
2a3aabf1e540        progrium/stress     "/usr/bin/stress -..."   12 seconds ago      Up 11 seconds                           epic_elion
## 3. 找到cgroup的配置文件
root@fbo-virtual-machine:~# cat /sys/fs/cgroup/cpu/docker/2a3aabf1e54019501932410bda550f1cf38393f9313a800a58d4b581878f680a/cpu.shares 
512

namespace

namespace 管理着 host 中全局唯一的资源,并可以让每个容器都觉得只有自己在使用它。换句话说,namespace 实现了容器间资源的隔离。

Linux 使用了六种 namespace,分别对应六种资源:Mount、UTS、IPC、PID、Network 和 User:

  • Mount namespace - 让容器看上去拥有整个文件系统,容器有自己的根目录,不会影响到host和其他容器
  • UTS namespace - 让容器有自己的hostname。
  • IPC namespace - 让容器拥有自己的共享内存和信号量(semaphore)来实现进程间通信,而不会与 host 和其他容器的 IPC 混在一起。
  • PID namespace - 容器拥有自己独立的一套 PID。
  • Network namespace - 让容器拥有自己独立的网卡、IP、路由等资源。
  • User namespace - 让容器能够管理自己的用户,host 不能看到容器中创建的用户。

使用--memory-swap限制内置配额时报错:
Your kernel does not support cgroup swap limit.
解决方法:
https://docs.docker.com/installation/ubuntulinux/

Edit the /etc/default/grub file.
Set the GRUB_CMDLINE_LINUX value as follows:
GRUB_CMDLINE_LINUX="cgroup_enable=memory swapaccount=1"
Save and close the file.
Update GRUB.
$ sudo update-grub
Reboot your system.

你可能感兴趣的:(Learning Docker Part 003 Dokcer容器实战)