一 docer运行应用
1.1 常见容器运行
1 root@docker:~# docker #查看docker相关命令 2 root@docker:~# docker run -d -p 80:80 httpd #从docker hub下载httpd镜像,启动httpd容器,并将容器的80端口映射到宿主机的80端口 3 root@docker:~# docker run centos:7 echo "hello world" 4 hello world
docker容器可以理解为在沙盒中运行的进程。这个沙盒包含了该进程运行所必须的资源,包括文件系统、系统类库、shell 环境等等。但这个沙盒默认是不会运行任何程序的。你需要在沙盒中运行一个进程来启动某一个容器。这个进程是该容器的唯一进程,所以当该进程结束的时候,容器也会完全的停止。
1 root@docker:~# docker ps #查看运行的容器情况
参数说明:
- CONTAINER ID:容器ID
- NAMES:自动分配的容器名称
1 root@docker:~# docker logs 634cf027ad85 #查看容器内的标准输出 2 root@docker:~# docker stop 634cf027ad85 #停止容器 3 root@docker:~# docker ps #再次查看
注意:
同一仓库源可以有多个 TAG,代表这个仓库源的不同个版本,如ubuntu仓库源里,有15.10、14.04等多个不同的版本,我们使用 REPOSTITORY:TAG 来定义不同的镜像。
若运行docker时不指定tag,则默认使用latest镜像。
1.2 交互式运行容器
1 root@docker:~# docker run -i -t centos:7 /bin/bash
各个参数解析:
- -t:在新容器内指定一个伪终端或终端。
- -i:允许你对容器内的标准输入 (STDIN) 进行交互。
二 运行Web应用及其他操作
2.1 容器后端运行
1 root@docker:~# docker pull training/webapp 2 root@docker:~# docker run -d -P training/webapp python app.py
参数说明:
- -d:让容器在后台运行。
- -P:将容器内部使用的网络端口映射到我们使用的主机上。
1 root@docker:~# docker ps
可知此docker开放了5000端口映射到主机端口32768上。
测试访问。
2.2 指定端口运行容器
1 root@docker:~# docker run -d -p 8080:5000 training/webapp python app.py #使用-p参数来绑定指定端口。 2 root@docker:~# docker run -d -p 9090:5000/tcp --name web training/webapp python app.py #使用--name标记可以为容器命名 3 root@docker:~# docker ps
注意:容器的名称是唯一的,若命名了一个叫web的容器,当再次使用web这个名称时,需要用docker rm删除之前创建的容器,也可以再执行docker run的时候加—rm标记来停止旧的容器,并删除,rm和-d参数是不兼容的。
测试新绑定的端口。
1 root@docker:~# docker port 25cbcff93d56 2 5000/tcp -> 0.0.0.0:8080 3 root@docker:~# docker port 95b731acd6b5 4 5000/tcp -> 0.0.0.0:32768
2.3 进入容器
1 root@docker:~# docker exec -it 5e7ad2db2304 /bin/bash 2 root@docker:~# docker exec -it web /bin/bash
2.4 容器其他操作
1 root@docker:~# docker logs -f 95b731acd6b5 #查看运行日志 2 root@docker:~# docker inspect web #查看Docker容器的配置和状态信息 3 root@docker:~# docker restart 5e7ad2db2304 #重启docker 4 root@docker:~# docker stop 95b731acd6b5 #停止docker 5 root@docker:~# docker kill 25cbcff93d56 #停止docker 6 root@docker:~# docker ps -a #查看所有容器情况 7 root@docker:~# docker start 95b731acd6b5 #运行已停止的docker 8 root@docker:~# docker rm 95b731acd6b5 #删除该docker
注意:删除容器时,容器必须是停止状态,查看容器详细信息可输入前部分ID,如docker inspect 6b52。
1 root@docker:~# docker pause 5e7ad2db2304 #暂停容器 2 root@docker:~# docker unpause 5e7ad2db2304 #恢复容器
三 容器生命周期管理
3.1 容器生命周期
四 docker资源限制
用户内存限制就是对容器能使用的内存和交换分区的大小作出限制。
4.1 资源限制意义
主机运行若干容器,每个容器都需要cpu、内存以及IO资源,为避免因为单个容器占用过多资源而影响到所有其他容器乃至整个宿主机的性能,需要对容器资源进行限制。
五 docker内存限制
5.1 内存限制
Docker 提供的内存限制功能有以下几点:
- 容器能使用的内存和交换分区大小。
- 容器的核心内存大小。
- 容器虚拟内存的交换行为。
- 容器内存的软性限制。
- 是否杀死占用过多内存的容器。
- 容器被杀死的优先级。
一般情况下,达到内存限制的容器过段时间后就会被系统杀死。
5.2 内存限制相关参数
执行docker run命令时能使用的和内存限制相关的所有选项如下。
选项
|
描述
|
-m,--memory
|
内存限制,格式是数字加单位,单位可以为 b,k,m,g。最小为4M
|
--memory-swap
|
内存+交换分区大小总限制,格式同上,必须比-m设置的值大
|
--memory-reservation
|
内存的软性限制,格式同上
|
--oom-kill-disable
|
是否阻止 OOM killer 杀死容器,默认没设置
|
--oom-score-adj
|
容器被 OOM killer 杀死的优先级,范围是[-1000, 1000],默认为 0
|
--memory-swappiness
|
用于设置容器的虚拟内存控制行为。值为 0~100 之间的整数
|
--kernel-memory
|
核心内存限制。格式同上,最小为 4M
|
提示:
-m,--memory选项的参数最小为 4 M;
--memory-swap不是交换分区,而是内存加交换分区的总大小,所以--memory-swap必须比-m,--memory大;
若不设置-m,--memory和--memory-swap,容器默认可用完宿主机所有内存和swap分区。但容器占宿主机所有内存和swap分区超过一段时间后,会被宿主机系统杀死(若没有设置--00m-kill-disable=true)。
5.3 内存设置方式
- 设置-m,--memory,不设置--memory-swap
1 root@docker:~# docker run -d --name ubuntu_01 -m 1G --memory-swap 0 ubuntu:16.04
#该容器能使用的内存大小为1G,能使用的 swap 分区大小也为1G,容器内的进程能申请到的总内存大小为2G。
作用:使用-m或--memory设置一个不小于 4M 的a值,不设置--memory-swap,或将--memory-swap设置为 0。则表示容器能使用的内存大小为 a,能使用的交换分区大小也为 a。因为 Docker 默认容器交换分区的大小和内存相同。若容器中运行一个一直不停申请内存的程序,则该程序最终能使用的内存大小为 2a。
- 设置-m,--memory=a,--memory-swap=b,且b > a
1 root@docker:~# docker run -d --name ubuntu_02 -m 1G --memory-swap 3G ubuntu:16.04
#该容器能使用的内存大小为 1G,能使用的 swap 分区大小为 2G。容器内的进程能申请到的总内存大小为 3G。
作用:使用-m或--memory设置一个不小于 4M 的a值,且b必须大于a,使用--memory-swap设置一个参数 b。则表示容器能使用的内存大小为 a,能使用的交换分区+内存大小为 b,b-a 即为容器能使用的 swap 分区大小。
- 设置-m,--memory=a,--memory-swap=-1
1 root@docker:~# docker run -d --name ubuntu_03 -m 1G --memory-swap -1 ubuntu:16.04
#该容器能使用的内存大小为 1G,且不限制容器使用swap分区大小,即1G+宿主机swap大小。
作用:使用-m或--memory设置一个不小于 4M 的a值,使用--memory-swap设置一个参数-1,则表示限制容器能使用的内存大小为 a,且不限制容器使用 swap 分区大小。
提示:若出现如下提示:
WARNING: Your kernel does not support swap limit capabilities or the cgroup is not mounted. Memory limited without swap.
可打开内核内存限制的操作:
1 root@docker:~# vi /etc/default/grub 2 GRUB_CMDLINE_LINUX="cgroup_enable=memory swapaccount=1" 3 root@docker:~# update-grub #重启系统
5.4 内存软性限制
设置--memory-reservation。
1 root@docker:~# docker run -d --name ubuntu_04 -m 2G --memory-reservation 1G ubuntu:16.04
#该容器能使用的内存大小为 2G,当宿主机内存资源紧张时,系统会回收1G内存,以便尝试将容器的内存锁紧到 1G 以下。
作用:Memory reservation是一种软性限制,用于节制容器内存使用。使用--memory-reservation设置一个比-m小的值后,虽然容器最多可以使用-m设置的内存大小,但在宿主机内存资源紧张时,在系统的下次内存回收时,系统会回收容器的部分内存页,强迫容器的内存占用回到--memory-reservation设置的值大小。没有设置时(默认情况下)--memory-reservation的值则--memory-reservation和-m的限定的值相同。将它设置为 0 或设置的比-m的参数大等同于没有设置。这种软性机制,它不保证任何时刻容器使用的内存不会超过--memory-reservation限定的值,它只是确保容器不会长时间占用超过--memory-reservation限制的内存大小。
5.5 OOM killer
1 root@docker:~# docker run -d --name ubuntu_05 -m 1G --oom-kill-disable ubuntu:16.04
#该容器能使用的内存大小为 1G,并禁止了 OOM killer。
作用:OOM killer机制指默认情况下,在出现 out-of-memory(OOM) 错误时,系统会杀死容器内的进程来获取更多空闲内存。通过设置--oom-kill-disable选项来禁止 OOM killer 杀死容器内进程。但请确保只有在使用了-m/--memory选项时才使用--oom-kill-disable禁用 OOM killer。如果没有设置-m选项,却禁用了 OOM-killer,可能会造成出现 out-of-memory 错误时,系统通过杀死宿主机进程或获取更改内存。
5.6 --memory-swappiness
1 root@docker:~# docker run -d --name ubuntu_06 --memory-swappiness=0 ubuntu:16.04
#该容器关闭了匿名页面交换,可以保持容器的工作集,避免交换代理的性能损失。
作用:默认情况下,容器的内核可以交换出一定比例的匿名页。--memory-swappiness可设置从 0 到 100这个比例。0 表示关闭匿名页面交换。100 表示所有的匿名页都可以交换。默认情况下,如果不使用--memory-swappiness,则该值从父进程继承而来。
注意:--memory-swappiness=0 表示禁用容器 swap 功能。
六 CPU限制
Docker 的资源限制和隔离完全基于 Linux cgroups。对 CPU 资源的限制方式也和 cgroups 相同。Docker 提供的 CPU 资源限制选项可以在多核系统上限制容器能利用哪些 vCPU。而对容器最多能使用的 CPU 时间有两种限制方式:
- 当多个 CPU 密集型的容器竞争 CPU 时,设置各个容器能使用的 CPU 时间相对比例。
- 以绝对的方式设置容器在每个调度周期内最多能使用的 CPU 时间。
6.1 CPU限制相关参数
执行docker run命令时能使用的和内存限制相关的所有选项如下。
选项
|
描述
|
--cpuset-cpus=""
|
允许使用的 CPU 集,值可以为 0-3,0,1
|
-c,--cpu-shares=0
|
CPU 共享权值(相对权重)
|
cpu-period=0
|
限制 CPU CFS 的周期,范围从 100ms~1s,即[1000, 1000000]
|
--cpu-quota=0
|
限制 CPU CFS 配额,必须不小于1ms,即 >= 1000
|
--cpuset-mems=""
|
允许在上执行的内存节点(MEMs),只对 NUMA 系统有效
|
其中--cpuset-cpus用于设置容器可以使用的 vCPU 核。-c,--cpu-shares用于设置多个容器竞争 CPU 时,各个容器相对能分配到的 CPU 时间比例。--cpu-period和--cpu-quata用于绝对设置容器能使用 CPU 时间。
6.2 CPU集
1 root@docker:~# docker run -d --name ubuntu_07 --cpuset-cpus="1,3" ubuntu:16.04
#表示容器中的进程可以在 cpu 1 和 cpu 3 上执行。
6.3 CPU 资源的相对限制
默认情况下,所有的容器得到同等比例的 CPU 周期。在有多个容器竞争 CPU 时可设置每个容器能使用的 CPU 时间比例。这个比例叫作共享权值,通过-c或--cpu-shares设置。Docker 默认每个容器的权值为 1024。不设置或将其设置为 0,都将使用这个默认值。系统会根据每个容器的共享权值和所有容器共享权值和比例来给容器分配 CPU 时间。
举例:
假设有三个正在运行的容器,这三个容器中的任务都是 CPU 密集型的。第一个容器的 cpu 共享权值是 1024,其它两个容器的 cpu 共享权值是 512。第一个容器将得到 50% 的 CPU 时间,而其它两个容器就只能各得到 25% 的 CPU 时间了。如果再添加第四个 cpu 共享值为 1024 的容器,每个容器得到的 CPU 时间将重新计算。第一个容器的CPU 时间变为 33%,其它容器分得的 CPU 时间分别为 16.5%、16.5%、33%。
注意:这个比例只有在 CPU 密集型的任务执行时才有用。在四核的系统上,假设有四个单进程的容器,它们都能各自使用一个核的 100% CPU 时间,不管它们的 cpu 共享权值是多少。
在多核系统上,CPU 时间权值是在所有 CPU 核上计算的。即使某个容器的 CPU 时间限制少于 100%,它也能使用各个 CPU 核的 100% 时间。
例如,假设有一个不止三核的系统。用-c=512的选项启动容器{C0},并且该容器只有一个进程,用-c=1024的启动选项为启动容器C1,并且该容器有两个进程。CPU 权值的分布可能是这样的:
1 PID container CPU CPU share 2 100 {C0} 0 100% of CPU0 3 101 {C1} 1 100% of CPU1 4 102 {C1} 2 100% of CPU2
6.4 CPU 资源的绝对限制
Linux 通过 CFS(Completely Fair Scheduler,完全公平调度器)来调度各个进程对 CPU 的使用。CFS 默认的调度周期是 100ms。
可设置每个容器进程的调度周期,以及在这个周期内各个容器最多能使用多少 CPU 时间。使用--cpu-period即可设置调度周期,使用--cpu-quota即可设置在每个周期内容器能使用的 CPU 时间。两者一般配合使用。
root@docker:~# docker run -d --name ubuntu_08 --cpu-period=50000 --cpu-quota=25000 ubuntu:16.04
#将 CFS 调度的周期设为 50000,将容器在每个周期内的 CPU 配额设置为 25000,表示该容器每 50ms 可以得到 50% 的 CPU 运行时间。
$ docker run -it --cpu-period=10000 --cpu-quota=20000 ubuntu:16.04 /bin/bash
root@docker:~# docker run -d --name ubuntu_09 --cpu-period=10000 --cpu-quota=20000 ubuntu:16.04
将容器的 CPU 配额设置为 CFS 周期的两倍,即容器分配两个 vCPU 就可以了。该配置表示容器可以在每个周期内使用两个 vCPU 的 100% 时间。
提示:CFS 周期的有效范围是 1ms~1s,对应的--cpu-period的数值范围是 1000~1000000。而容器的 CPU 配额必须不小于 1ms,即--cpu-quota的值必须 >= 1000。可以看出这两个选项的单位都是 us。
七 Block IO限制
Block IO 是另一种可以限制容器使用的资源。Block IO 指的是磁盘的读写,docker 可通过设置权重、限制 bps 和 iops 的方式控制容器读写磁盘的带宽。
选项
|
描述
|
--blkio-weight
|
设置的都是资源使用的权重
提示:该设置都是资源紧张的情况下才会起到权重的作用,正常情况下,都是平等的。
--blkio-weight-device 针对特定的设备设置权重
|
--device-read-bps
|
限制读某个设备的bps(数据量)
|
--device-write-bps
|
限制写入某个设备的bps(数据量)
|
--device-read-iops
|
限制读某个设备的iops(次数)
|
--device-write-iops
|
限制写入某个设备的iops(次数)
|
注意:目前 Block IO 限额只对 direct IO(不使用文件缓存)有效。
7.1 block IO 权重
1 root@docker:~# docker run -d --name ubuntu_10 --blkio-weight 600 ubuntu:16.04 2 root@docker:~# docker run -d --name ubuntu_11 --blkio-weight 300 ubuntu:16.04
#ubuntu_10容器的读写磁盘的带宽是ubuntu_11的两倍。
7.2 限制 bps 和 iops
bps:byte per second,每秒读写的数据量。
iops:io per second,每秒 IO 的次数。
1 root@docker:~# docker run -d --name ubuntu_12 --device-write-bps /dev/sda:30MB ubuntu:16.04
#ubuntu_12容器写 /dev/sda 的速率为 30 MB/s。