如何运行容器
有三种方式可以指定容器启动时的命令
- CMD指令
- ENTRYPOINT 指令
- 在
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
- attach直接进入启动命令的终端
- exec在容器中打开新的进程
- attach会直接显示启动命令的输出,使用
docker logs -f
也可以查看启动命令的输出 - attach进入容器后退出会终止容器,exec则不会
容器功能划分
按照用途划分,容器分为:
- 服务类容器: 以deamon形式运行,外提供服务。比容 web server,数据等,通过-d以后台方式运行,要排查问题时,通过exec -it进入容器。
- 工具类容器: 能够给我们提供一个临时的工作环境,通常以
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
容器的生命周期
限制容器对资源的使用
一个docker host上会运行若干个容器,每个容器都要消耗cpu、内存以及磁盘IO资源,为避免某个容器因为占中过多资源而影响其他容器乃至整个host的性能,我们必须要对容器资源使用进行限制。
内存限额
容器的内存包括两部分:物理内容和swap内存
-
-m
或者--memory
:设置内存的使用限额,如100M、2G; -
--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.