如何让容器长期运行?

容器的生命周期依赖于启动时执行的命令,只要该命令不结束,容器也就不会退出。

进入容器的方法:

@通过docker attach可以attach到容器启动命令的终端

注意:可以通过ctrl+p然后ctrl+q组合键退出attach终端

@通过docker exec进入到相同的容器

docker exec -it docker_name bash

attach vs exec

1.attach 直接进入容器启动命令的终端,不会启动新的进程

2.exec 则是在容器中打开新的终端,并且可以启动新的进程

3.如果想直接在终端中查看启动命令的输出,用attach;其他情况使用exec

如果查看启动命令的输出也可以用docker logs -f <container>

容器的运行:

按用途容器大致可分为两类:服务类容器和工具类容器‘

常用的操作比如:run,stop,restart,pause,rm

常用命令:

docker stop 

docker start

docker restart

docker kill

docker run --restart=always

docker pause(不占用cpu资源)

docker rm

docker rm -v $(docker ps -aq)

容器资源限制:

一个docker host上会运行若干容器,每个容器都需要cpu,内存和io资源。对于kvm,vmware等虚拟化技术,用户可以控制分配多少cpu,内存资源给每个虚拟机。对于容器,Docker也提供类似的机制避免某个容器因占用太多资源而影响其他容器乃至整个host的性能。

内存限制:

与操作系统类似,容器可以使用的内存包括两部分:物理内存和swap。Docker通过下面两个参数来控制容器的使用量。

@-m或者--memory :设置内存的使用配额,例如:100M,2G

@--memory-swap:设置内存+swap的使用限制

实例:

docker run -it -m 200M --memory-swap=400M --name vm9 docker.io/progrium/stress --vm 1 --vm-bytes 300M

其含义是允许该容器最多使用200M内存和200M的swap。默认情况下,上面两组参数为-1,即对容器的内存和swap的使用没有限制。

--vm 1 :启动1个内存工作协程

--vm-bytes 300M :每个线程分配300M内存

如果让工作线程分配的内存超过400M,则会stress线程报错,容器退出。

如果在启动容器时只指定-m,不指定--memory-swap,那么--memory-swap默认为-m的两倍

比如:

docker run -it -m 200M centos

解释为容器最多使用200M物理内存和200M swap

cpu限制:

默认情况下,所有容器可以平等的使用host cpu资源并且没有限制。

Docker可以通过-c或者--cpu-shares设置容器使用cpu权重,如果不指定,默认值为1024.

与内存配额不同,通过-c设置的cpu shares并不是cpu资源的绝对数量,而是一个相对的权重值。某个容器最终能分配到的cpu资源取决于它的cpu share中所有cpushare总和的比例。

说白了,就是通过cpu share可以设置容器使用cpu的优先级。

需要注意的是,这种按权重分配cpu只会发生在cpu资源紧张的情况下。

实验对比:(实验机为2核cpu)

1.docker  run  -it --name vm13 -c 2048 docker.io/progrium/stress --cpu 2

2.docker  run  -it --name vm14 -c 1024 docker.io/progrium/stress --cpu 2

top查看结果:

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                               

64.5

64.5

35.2

35.2 

如果停止掉权重大的容器压测实验,则2号实验也能满额cpu。

Block IO限制:

Block IO是另一种限制容器使用的资源。Block IO 指的是磁盘的读写,docker也可以通过设置权重,限制bps和iops的方式控制容器的读写磁盘的带宽。

注:目前Block IO限额只对direct io(不使用文件缓存)有效

Block IO权重

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

--blkio-weight 与--cpu-weight类似,设置的是相对权重值,默认为500。

限制 bps 和 iops:

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

可通过以下参数控制容器的 bps 和 iops: --device-read-bps,限制读某个设备的 bps。 --device-write-bps,限制写某个设备的 bps。 --device-read-iops,限制读某个设备的 iops。 --device-write-iops,限制写某个设备的 iops。

下面这个例子限制容器写 /dev/sda 的速率为 30 MB/s

docker run -it --device-write-bps /dev/sda:30MB centos

限制资源的底层技术:

cgroup和namespace是最重要的两种技术。cgroup实现资源限制,namespace实现资源隔离。

cgroup:

cgroup全程control cgroup。linux操作系统通过设置进程使用cpu,内存和IO资源的限额,前面配置--cpu--shares,-m,--device-write-bps实际上是在配置cgroup。

cgroup可以在/sys/fs/cgroup/中找到它。

注释:docker version 1.12.6  目录为/sys/fs/cgroup/xxx/system.slice

namespace:

每个容器中,我们都可以看到文件系统,网卡等资源。linux实现这种方式的技术是namespace,namespace实现了容器间资源的隔离。

linux使用了六种namespace,分别对应:mount,UTS,IPC,PID,NETWORK和USER.

Mount namespace

Mount namespace 让容器看上去拥有整个文件系统。

容器有自己的 / 目录,可以执行 mount 和 umount 命令。当然我们知道这些操作只在当前容器中生效,不会影响到 host 和其他容器。

UTS namespace

简单的说,UTS namespace 让容器有自己的 hostname。 默认情况下,容器的 hostname 是它的短ID,可以通过 -h 或 --hostname 参数设置。

IPC namespace

IPC namespace 让容器拥有自己的共享内存和信号量(semaphore)来实现进程间通信,而不会与 host 和其他容器的 IPC 混在一起。

PID namespace

我们前面提到过,容器在 host 中以进程的形式运行。通过 ps axf 可以查看容器进程。

Network namespace

Network namespace 让容器拥有自己独立的网卡、IP、路由等资源。我们会在后面网络章节详细讨论。

User namespace

User namespace 让容器能够管理自己的用户,host 不能看到容器中创建的用户。