🍂落页
登 录

《Docker 实战》笔记

  • 速查表
  • 欢迎来到 Docker 的世界
  • 在容器中运行软件
  • 使用 Docker 安装软件
  • 使用存储和卷
  • 单主机网络
  • 通过资源控制来限制风险
  • 将软件打包到镜像中
  • 用 Dockerfile 构建镜像
🍂落页
TALAXY
通过资源控制来限制风险
🍂落页
TALAXY

通过资源控制来限制风险

通过资源控制来限制风险
  • 设置资源分配
  • 共享内存
  • 用户权限
  • 系统功能权限管理
  • 增强工具

管控风险可以防止由于软件缺陷而导致的错误问题,也可以防止由于消耗过量资源而导致计算机无响应的攻击类行为。

Docker 使用来了如下命名空间和相应功能来构建容器:

  • MNT - 隔离各个进程间的文件系统挂载点;
  • NET - 隔离网络接口,每个网络命名空间都有自己的路由表、防火墙、网络设备等;
  • UTS - 隔离两个系统标识符:主机名和域名;
  • PID - 隔离进程 ID ;
  • IPC - 隔离各种 IPC 资源,如信号量、消息队列、共享内存等;
  • USR - 隔离用户名和标识符;
  • chroot() - 控制进程所看到的文件系统根目录;
  • Cgroups - 资源保护。

设置资源分配

默认情况下,容器可以不受限制地使用计算机的物理资源。而如果资源消耗过度则会引发性能问题甚至进程停止运行。

Docker 中可以控制容器的内存、CPU、设备I/O等的资源分配,这在创建容器时可以进行设置。

内存

可以用 --memory 或 -m 来控制容器所能够使用的最大内存:

# 启动一个 MariaDB 服务
docker run -d --name mariadb \
    --memory 256m \
    --cpu-shares 1024 \
    --cap-drop net_raw \
    -e MYSQL_ROOT_PASSWORD=test \
    mariadb:5.5

参数的格式为 <数量><单位> ,其中单位可以是 b k m g 。

在具有交换空间(扩展到磁盘的虚拟内存)的主机上,容器的内存分配可以大于可用的物理内存。

CPU

可以通过 --cpu-shares 为容器指定 CPU(相比于其他容器的)权重,Linux 会根据权重信息来确定每个容器所能占用的 CPU 资源百分比:

## 启动一个 WordPress 服务
docker run -d -P --name wordpress \
    --memory 512m \
    --cpu-shares 512 \
    --cap-drop net_raw \
    --link mariadb:mysql \
    -e WORD_PRESS_DB_PASSWORD=test \
    wordpress:5.0.0-php7.2-apache

假设当前还有另一个容器,并且权重设为 1024 ,那么 wordpress 容器将会获得 33% 的可用 CPU 资源。

与内存分配不同的是,仅当进程之间出现 CPU 资源争抢时才会进行资源分配,即容器可以占用空闲 CPU 资源,即便是超出了分配限制。


可以通过 --cpus 限制容器可用的 CPU 核心数,它通过配置 Linux 的完全公平调度(CFS)来给容器分配相应的 CPU 资源:

docker run -d -P --name wordpress \
    --memory 512m \
    --cpus 0.75 \
    ...

Docker 还支持将容器分配给特定的 CPU 集合。CPU 在工作时会涉及进程的上下文切换,上下文切换是指从执行一个进程变为执行另一个,这一过程非常消耗系统资源。因此必要的话可以将容器限定在一个 CPU 集合中,可以通过 --cpuset-cpus 设置:

# 限制容器运行在 CPU 集合 0 上
docker run -d --cpuset-cpus 0 ...

访问设备

Linux 系统可以连接各种设备,比如硬盘驱动器、USB 驱动器、鼠标、网络摄像头等。默认情况下容器可以访问某些主机设备,而不能默认访问的设备可以通过 --device 来将设备挂载到容器中:

docker run -it --rm \
    --device /dev/video0:/dev/video0 \
    ubuntu:16.04 ls -al /dev

--device 可以被设置多次,以对不同设备进行访问授权。

共享内存

Linux 提供了共享内存工具,它能够让进程间通信(InterProcess Communication, IPC)以内存级速度进行。一些科学计算和流行的数据库技术(如 PostgreSQL)就使用了共享内存技术。

Docker 默认为每个容器创建唯一的 IPC 命名空间,防止一个容器访问主机或其他容器的内存。Linux IPC 命名空间把共享内存基本单元划分为共享内存块、信号量和消息队列。

可以用 --ipc 选项实现容器之间共享 IPC 基本单元:

docker run -d -u nobody --name ipc_producer \
    --ipc shareable \
    dockerinaction/ch6_ipc -producer

docker run -d --name ipc_consumer \
    --ipc container:ipc_producer \
    dockerinaction/ch6_ipc -consumer
  • --ipc shareable 用于告知 Docker 其 IPC 命名空间可共享给别的容器;
  • --ipc container:<容器> 应用目标容器的 IPC 命名空间。

可用 --ipc=host 使用主机的 IPC 命名空间。

用户权限

Docker 默认以镜像元数据指定的用户身份启动容器,通常是 root 用户。而 root 用户对容器几乎拥有完全的访问权限,因此尽量不使用 root 用户启动容器。

可以用 -u 或 --user 设置用户相关配置,如 -u nobody 代表以普通用户身份启动容器。

更多介绍见书中 P144 。

系统功能权限管理

Linux 上通过能力机制(capabilities)来管控 root 权限,它将 root 权限分割为不同的能力,每种能力都代表一定的特权操作,比如有:

  • SYS_MODULE - 插入/删除核心模块
  • CAP_NET_RAW - 进程与网络交互

当进程在尝试系统调用时,系统会先检查进程的能力集中是否包含此调用所涉及的能力,如果不包含则调用失败。

创建新容器时,Docker 几乎会删除能力集中的所有能力,只保留对于大多数程序必需且安全的能力。如果要进一步增加会减去能力,可以用 --cap-add 或 --cap-drop :

docker run --rm -u nobody \
    -cap-drop net_raw \
    ...

也可以用 --privileged 选项授予容器完整的系统功能。

增强工具

Docker 设置了默认的 seccomp 配置文件,用来阻止大多数程序不需要的内核系统调用(syscall)。还可以用自定义的 seccomp 配置文件、AppArmer、SELinux 等工具来增强容器。具体见书 P124 。

TALAXY 落于 2024年6月3日 。