运行容器
docker run 是启动容器的方法,容器启动后返回的是 “长ID”,我们可以通过这个长ID去访问这个容器,也可以通过启动时指定的名字访问这个容器。docker ps 能够看到容器的“短ID”,通过短ID同样可以访问这个容器,甚至只要能够唯一标识这个容器也可使用更短的ID。
-d 指定容器以后台方式运行;–restart 指定容器的重启策略,默认值no,容器退出时不要重启,on-failure[:max-retries] 只在容器以非0状态码退出时重启。max-retries可以指定尝试重启容器的次数;always 不管退出状态码是什么始终重启容器。当指定容器退出后,docker daemon将无限次数地重启容器。–name 指定容器的名称。
容器的生命周期依赖于启动时执行的命令,只要该命令不结束,容器也就不会退出。理解了这个原理,我们就可以通过执行一个长期运行的命令来保持容器的运行状态。
进入容器
我们经常需要进到容器里去做一些工作,比如查看日志、调试、启动其他进程等。有两种方法进入容器:attach 和 exec。
docker attach
通过 docker attach 可以 attach 到容器启动命令的终端,可通过 Ctrl+p 然后 Ctrl+q 组合键退出 attach 终端。
docker exec
通过 docker exec 进入相同的容器。docker exec -ti
attach VS exec
attach 与 exec 主要区别如下:
- attach 直接进入容器 启动命令 的终端,不会启动新的进程。
- exec 则是在容器中打开新的终端,并且可以启动新的进程。
容器的常用操作
stop/start/restart|kill 容器
启动、停止、重启、杀死容器:
1 | docker start|stop|restart|kill [容器名|容器ID] |
pause/unpause 容器
有时我们只是希望暂时让容器暂停工作一段时间,比如要对容器的文件系统打个快照,这时可以执行 docker pause。
挂起、唤醒容器:
1 | docker pause/unpause [容器名|容器ID] |
删除容器
1 | docker rm -f [容器名|容器ID] |
-f 参数可以强制删除运行中的容器。
可以用如下命令删除所有已退出的容器:
1 | docker rm $(docker ps -a -q -f status=exited) |
可以用如下命令强制删除所有容器:
1 | docker rm -f $(docker ps -a -q) |
注意:docker rm 是删除容器,而 docker rmi 是删除镜像。
容器的生命周期
对容器的生命周期有了大致的理解,下面这张状态机很好地总结了容器各种状态之间是如何转换的。容器有五种状态:已创建、运行中、已挂起、已停止、已销毁,我们可以通过执行命令让docker在这五种状态间转换。
docker run 是docker pull(如果镜像不存在)、docker create、docker start的复合命令。
容器资源限制
限制内存资源
与操作系统类似,容器可使用的内存包括两部分:物理内存和 swap。 Docker 通过下面两组参数来控制容器内存的使用量。
- -m 或 –memory:设置内存的使用限额,例如 100M, 2G。
- –memory-swap:设置 内存+swap 的使用限额。
当我们执行如下命令:
1 | docker run -m 200M --memory-swap=300M ubuntu |
其含义是允许该容器最多使用 200M 的内存和 100M 的 swap。默认情况下,上面两组参数为 -1,即对容器内存和 swap 的使用没有限制。如果在启动容器时只指定 -m 而不指定 –memory-swap,那么 –memory-swap 默认为 -m 的两倍。
内存限额测试:
docker run -it -m 300M progrium/stress –vm 1 –vm-bytes 280M 未超过限额,容器启动成功
docker run -it -m 300M progrium/stress –vm 1 –vm-bytes 320M 超过限额,容器失败退出
限制CPU资源
Docker 可以通过 -c 或 –cpu-shares 设置容器使用 CPU 的权重。如果不指定,默认值为 1024。
与内存限额不同,通过 -c 设置的 cpu share 并不是 CPU 资源的绝对数量,而是一个相对的权重值。某个容器最终能分配到的 CPU 资源取决于它的 cpu share 占所有容器 cpu share 总和的比例。
CPU限额测试:
1 | # 启动cpu_a,--cpu-shares为1024 |
CPU资源使用对比:
当CPU资源紧张时,–cpu-shares设置为1024的容器占用CPU的时间大约是设置为512的容器的两倍。
限制磁盘IO
Block IO 是另一种可以限制容器使用的资源。Block IO 指的是磁盘的读写,docker 可通过设置权重、限制 bps 和 iops 的方式控制容器读写磁盘的带宽。
注意:目前 Block IO 限额只对 direct IO(不使用文件缓存)有效。
block IO 权重
默认情况下,所有容器能平等地读写磁盘,可以通过设置 –blkio-weight 参数来改变容器 block IO 的优先级。
–blkio-weight 与 –cpu-shares 类似,设置的是相对权重值,默认为 500。在下面的例子中,blockio_a 读写磁盘的带宽是 blockio_b 的两倍。
1 | docker run -it --name blockio_a --blkio-weight 600 ubuntu |
限制 bps 和 iops
可通过以下参数控制容器的 bps 和 iops:
- –device-read-bps,限制读某个设备的 bps
- –device-write-bps,限制写某个设备的 bps
- –device-read-iops,限制读某个设备的 iops
- –device-write-iops,限制写某个设备的 iops
磁盘IO限额测试:
限制容器写 /dev/vda 的速率为 30 MB/s,通过 dd 测试在容器中写磁盘的速度。因为容器的文件系统是在 host /dev/vda 上的,在容器中写文件相当于对 host /dev/vda 进行写操作。另外,oflag=direct 指定用 direct IO 方式写文件,这样 –device-write-bps 才能生效。当去掉oflag=direct后–device-write-bps设置并没有生效,磁盘写入速度达到了 1.4 GB/s。
容器底层实现
cgroup实现资源限额:
- 通过 cgroup 可以设置进程使用 CPU、内存 和 IO 资源的限额
- –cpu-shares、-m、–device-write-bps 实际上就是在配置 cgroup
- cgroup配置目录:/sys/fs/cgroup/cpu|memory|blkio/docker
namespace实现资源隔离:
- Mount 让容器看上去拥有整个文件系统
- UTS 让容器有自己hostname
- IPC 让容器有自己的共享内存和信号量
- PID 让容器有自己的进程空间
- Network 让容器有自己的网络空间
- User 让容器有自己的用户