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 可以 attach 到容器启动命令的终端,可通过 Ctrl+p 然后 Ctrl+q 组合键退出 attach 终端。
通过 docker exec 进入相同的容器。docker exec -ti <container id> bash|sh 是执行 exec 最常用的方式。-ti 以交互模式打开 pseudo-TTY,执行 bash,其结果就是打开了一个 bash 终端。
attach 与 exec 主要区别如下:
- attach 直接进入容器 启动命令 的终端,不会启动新的进程。
- exec 则是在容器中打开新的终端,并且可以启动新的进程。
启动、停止、重启、杀死容器:
docker start|stop|restart|kill [容器名|容器ID]
有时我们只是希望暂时让容器暂停工作一段时间,比如要对容器的文件系统打个快照,这时可以执行 docker pause。
挂起、唤醒容器:
docker pause/unpause [容器名|容器ID]
docker rm -f [容器名|容器ID]
-f 参数可以强制删除运行中的容器。
可以用如下命令删除所有已退出的容器:
docker rm $(docker ps -a -q -f status=exited)
可以用如下命令强制删除所有容器:
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 的使用限额。
当我们执行如下命令:
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 超过限额,容器失败退出
Docker 可以通过 -c 或 --cpu-shares 设置容器使用 CPU 的权重。如果不指定,默认值为 1024。
与内存限额不同,通过 -c 设置的 cpu share 并不是 CPU 资源的绝对数量,而是一个相对的权重值。某个容器最终能分配到的 CPU 资源取决于它的 cpu share 占所有容器 cpu share 总和的比例。
CPU限额测试:
# 启动cpu_a,--cpu-shares为1024
# --cpu 用来设置工作线程的数量,宿主机是4核CPU,设置为4表示使用所有CPU
docker run --name cpu_a -it -c 1024 -d progrium/stress --cpu 4
# 启动cpu_b,cpu-shares为512
# --cpu 用来设置工作线程的数量,宿主机是4核CPU,设置为4表示使用所有CPU
docker run --name cpu_b -it -c 512 -d progrium/stress --cpu 4
当CPU资源紧张时,--cpu-shares设置为1024的容器占用CPU的时间大约是设置为512的容器的两倍。
Block IO 是另一种可以限制容器使用的资源。Block IO 指的是磁盘的读写,docker 可通过设置权重、限制 bps 和 iops 的方式控制容器读写磁盘的带宽。
注意:目前 Block IO 限额只对 direct IO(不使用文件缓存)有效。
默认情况下,所有容器能平等地读写磁盘,可以通过设置 --blkio-weight 参数来改变容器 block IO 的优先级。
--blkio-weight 与 --cpu-shares 类似,设置的是相对权重值,默认为 500。在下面的例子中,blockio_a 读写磁盘的带宽是 blockio_b 的两倍。
docker run -it --name blockio_a --blkio-weight 600 ubuntu
docker run -it --name blockio_b --blkio-weight 300 ubuntu
可通过以下参数控制容器的 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 让容器有自己的用户