🍂落页
登 录

《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日 。

Press space bar to start a drag. When dragging you can use the arrow keys to move the item around and escape to cancel. Some screen readers may require you to be in focus mode or to use your pass through key