xiufeigo™
Home
运维
Docker 生命周期管理

运行容器

docker run 是启动容器的方法,容器启动后返回的是 “长 ID”,我们可以通过这个长 ID 去访问这个容器,也可以通过启动时指定的名字访问这个容器。docker ps 能够看到容器的 “短 ID”,通过短 ID 同样可以访问这个容器,甚至只要能够唯一标识这个容器也可使用更短的 ID。

docker run 中的 —name 指定了镜像的 NAMES
文中示例的“长 id ”就是:
d019223e9f72ded7ac037235f766b0314db99de21905111b97491ba9cebb5571
文中示例的“短 id ”则是:
d019223e9f72
如需使用“更短 id ”,则可截取“短 id ”的前 4 位

💡
  • -d 指定容器以后台方式运行;

  • --restart 指定容器的重启策略,默认值 no,容器退出时不要重启。

  • on-failure [:max-retries] 只在容器以非 0 状态码退出时重启。max-retries 可以指定尝试重启容器的次数;always 不管退出状态码是什么始终重启容器。当指定容器退出后,docker daemon 将无限次数地重启容器。例:「—restart=on-failure:3」

  • --name 指定容器的名称。

容器的生命周期依赖于启动时执行的命令,只要该命令不结束,容器也就不会退出。理解了这个原理,我们就可以通过执行一个长期运行的命令来保持容器的运行状态。


进入容器

我们经常需要进到容器里去做一些工作,比如查看日志、调试、启动其他进程等。有两种方法进入容器:attach 和 exec。

docker attach

通过 docker attach 可以 attach 到容器启动命令的终端,可通过 Ctrl+p 然后 Ctrl+q 组合键退出 attach 终端。

用法:docker attach [容器名 | 容器 ID]
例如:docker attach 7c38

💡

docker exec

通过 docker exec 进入相同的容器。docker exec -ti [容器名 | 容器 ID] bash 是执行 exec 最常用的方式。-ti 以交互模式打开 pseudo-TTY,执行 bash,其结果就是打开了一个 bash 终端。

用法:docker exec -it [容器名 | 容器 ID] bash
例如:docker exec -it 7c38 bash

💡

attach VS exec

attach 与 exec 主要区别如下:

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

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


容器的常用操作

stop/start/restart/kill 容器

启动、停止、重启、杀死容器:

docker start|stop|restart|kill [容器名|容器ID]

stop

start

restart

kill

pause/unpause 容器

有时我们只是希望暂时让容器暂停工作一段时间,比如要对容器的文件系统打个快照,这时可以执行 docker pause,打完之后就可以唤醒容器。

挂起、唤醒容器:

docker pause/unpause [容器名|容器ID]

pause

unpause

删除容器

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 的复合命令

💡


容器资源限制

开始之前

在开始之前,我们先制作一个 stress 的 docker 镜像,用于后面的压测

$ mkdir $(date +%F)
$ cd $(date +%F)
$ cat > Dockerfile << 'EOF'
# 使用官方的 Ubuntu 镜像作为基础镜像
FROM ubuntu

# 设置环境变量,避免交互式配置提示
ENV DEBIAN_FRONTEND=noninteractive

# 更新包列表并安装 stress
RUN apt-get update && \
    apt-get install -y --no-install-recommends \
    stress && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

# 设置默认的工作目录
WORKDIR /stress

# 默认命令:显示帮助信息
CMD ["stress", "--help"]

EOF

$ docker build -t my-stress:latest .

查看镜像

$ docker images

限制内存资源

与操作系统类似,容器可使用的内存包括两部分:物理内存和 swap。

Docker 通过下面两组参数来控制容器内存的使用量。

  • -m 或 --memory:设置内存的使用限额,例如 100M, 2G。

  • --memory-swap:设置 内存 + swap 的使用限额。

当我们执行下面命令:

docker run -m 200M --memory-swap=300M centos

其含义是允许该容器最多使用 200M 的内存和 100M 的 swap。默认情况下,上面两组参数为 -1,即对容器内存和 swap 的使用没有限制。如果在启动容器时只指定 -m 而不指定 --memory-swap,那么 --memory-swap 默认为 -m 的两倍。

内存限额测试:

docker run --name stress -it -m 300M my-stress stress --vm 1 --vm-bytes 280M --timeout 30

未超过限额,容器启动成功

docker run --name stress -it -m 300M my-stress stress --vm 1 --vm-bytes 1G --timeout 30

超过限额,容器失败退出

限制 CPU 资源

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

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

CPU 限额测试:

# 启动cpu_a,--cpu-shares为1024
# --cpu 用来设置工作线程的数量,宿主机是 16 核 CPU,设置为 16 表示使用所有 CPU
docker run --name cpu_a -it -c 1024 -d my-stress stress --cpu 16
# 启动cpu_b,cpu-shares为512
# --cpu 用来设置工作线程的数量,宿主机是 16 核 CPU,设置为 16 表示使用所有 CPU
docker run --name cpu_b -it -c 512 -d my-stress stress --cpu 16

查看容器资源的使用情况

docker stats

可以看到,当 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 的两倍。

docker run -it --name blockio_a --blkio-weight 600 ubuntu
docker run -it --name blockio_b --blkio-weight 300 ubuntu

限制 bps 和 iops

可通过以下参数控制容器的 bps 和 iops:

  • --device-read-bps,限制读某个设备的 bps

  • --device-write-bps,限制写某个设备的 bps

  • --device-read-iops,限制读某个设备的 iops

  • --device-write-iops,限制写某个设备的 iops

磁盘 IO 限额测试:

失败了,具体原因不明⋯⋯


容器底层实现

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 让容器有自己的用户

粤ICP备2022009857号-1