创建容器常用选项

选项 描述
-i, –interactive 交互式
-t, –tty 分配一个伪终端
-d, –detach 运行容器到后台
-e, –env 设置环境变量
-p, –publish list 发布容器端口到主机
-P, –publish-all 发布容器所有EXPOSE的端口到宿主机随机端口
–name string 指定容器名称
-h, –hostname 设置容器主机名
–ip string 指定容器IP,只能用于自定义网络
–network 连接容器到一个网络
–mount mount 将文件系统附加到容器
-v, –volume list 绑定挂载一个卷
–restart string 容器退出时重启策略,默认no,可选值:[always|on-failure]

创建容器示例

# 启动一个nginx容器,指定名字、映射端口、设置重启
# 如果不加-it分配一个交互式的伪终端,容器就会直接退出了,容器内的第一个程序必须一直处于前台运行(必须hang住)
docker container run -itd --name "nginx" -p 80:80 --restart always nginx:1.17

容器资源限制

选项 描述
-m,–memory 容器可以使用的最大内存量
–memory-swap 允许交换到磁盘的内存量
–memory-swappiness=<0-100> 容器使用SWAP分区交换的百分比(0-100,默认为-1)
–oom-kill-disable 禁用OOM Killer
–cpus 可以使用的CPU数量
–cpuset-cpus 限制容器使用特定的CPU核心,如(0-3, 0,1)
–cpu-shares CPU共享(相对权重)

内存限额示例

# 允许容器最多使用500M内存和600M的swap,并禁用OOM Killer
docker container run -d --name "nginx1" --memory="500M" --memory-swap="600M" --oom-kill-disable nginx:1.17

CPU限额示例

# 允许容器最多使用两个的CPU
docker container run -d --name "nginx2" --cpus="2" nginx:1.17
# 允许容器最多使用50%的CPU
docker container run -d --name "nginx3" --cpus=".5" nginx:1.17

容器资源配额扩容

# 容器资源可更新选项
docker update --help
Usage:    docker update [OPTIONS] CONTAINER [CONTAINER...]
Update configuration of one or more containers
Options:
      --blkio-weight uint16        Block IO (relative weight), between 10 and 1000, or 0 to disable (default 0)
      --cpu-period int             Limit CPU CFS (Completely Fair Scheduler) period
      --cpu-quota int              Limit CPU CFS (Completely Fair Scheduler) quota
      --cpu-rt-period int          Limit the CPU real-time period in microseconds
      --cpu-rt-runtime int         Limit the CPU real-time runtime in microseconds
  -c, --cpu-shares int             CPU shares (relative weight)
      --cpus decimal               Number of CPUs
      --cpuset-cpus string         CPUs in which to allow execution (0-3, 0,1)
      --cpuset-mems string         MEMs in which to allow execution (0-3, 0,1)
      --kernel-memory bytes        Kernel memory limit
  -m, --memory bytes               Memory limit
      --memory-reservation bytes   Memory soft limit
      --memory-swap bytes          Swap limit equal to memory plus swap: '-1' to enable unlimited swap
      --pids-limit int             Tune container pids limit (set -1 for unlimited)
      --restart string             Restart policy to apply when a container exits

# 更新正在运行中的容器内存限额
docker update --memory="400M" --memory-swap="500M" --restart="on-failure" 4e860294d239

管理容器常用命令

选项 描述
ls 列出容器
inspect 查看一个或多个容器详细信息
exec 在运行容器中执行命令
commit 创建一个新镜像来自一个容器
cp 拷贝文件/文件夹到一个容器
logs 获取一个容器日志
port 列出或指定容器端口映射
top 显示一个容器运行的进程
stats 显示容器资源使用统计
stop/start/restart 停止/启动一个或多个容器
rm 删除一个或多个容器
prune 移除已停止的容器

管理容器示例

# 列出真正运行的所有容器
docker container ls -a

# 获取一个容器日志
docker container logs --tail="5" nginx        # 仅列出最新N条容器log信息
docker container logs -f nginx        # 跟踪log信息输出
docker logs --since="2020-06-18" --tail="10" nginx      # 显示某个时间之后的最新十条log信息

# 进入正在运行的容器中执行命令
docker container exec -it nginx /bin/bash

# 显示一个容器运行的进程
docker container top nginx

# 删除一个或删除全部容器
docker container rm -f nginx
docker container rm -f $(docker container ls -q)

容器实现核心技术:Namespace

在容器化中,一台物理计算机可以运行多个不同操作系统(一个容器就类似于一个系统),那就需要解决 “隔离性”,让彼此感知不到对方的存在,出现问题也互不影响

Linux 内核从 2.4.19 版本开始引入了 namespace 概念,其目的是将特定的全局系统资源通过抽象方法使得 namespace 中的进程看起来拥有自己隔离的资源。Docker 就是借助这个机制实现了容器资源隔离

Linux 的 namespace 机制提供了6种不同的命名空间

IPC:隔离进程间通信

MOUNT:隔离文件系统挂载点

NET:隔离网络协议栈

PID:隔离进程号,容器命名空间对父进程空间可见

USER:隔离用户

UTS:隔离主机名和域名

容器实现核心技术:CGroups

Docker 利用 namespace 实现了容器之间资源隔离,但是 namespace 不能对容器资源限制,比如 CPU、内存。如果某一个容器属于 CPU 密集型任务,那么会影响其他容器使用 CPU,导致多个容器相互影响并且抢占资源。如何对多个容器的资源使用进行限制就成了容器化的主要问题。所以容器引入了 Control Groups(简称CGroups),限制容器资源

CGroups 以某种标准讲一组进程为目标进行资源分配和控制,例如 CPU、内存、带宽等,并且可以动态配置

限制进程组使用的资源数量(Resource limitation ):可以为进程组设定资源使用上限,例如内存

进程组优先级控制(Prioritization):可以为进程组分配特定 CPU、磁盘 IO 吞吐量

记录进程组使用的资源数量(Accounting):例如使用记录某个进程组使用的 CPU 时间

进程组控制(Control):可以将进程组挂起和恢复

查看cgroups可控制的资源

资源 描述
blkio 对块设备的IO进行限制
cpu 限制CPU时间片的分配,与cpuacct挂载同一目录
cpuacct 生成cgroup中的任务占用CPU资源的报告,与cpu挂载同一目录
cpuset 给cgroup中的任务分配独立的CPU(多核处理器)和内存节点
devices 允许或者拒绝 cgroup 中的任务访问设备
freezer 暂停/恢复 cgroup 中的任务
hugetlb 限制使用的内存页数量
memory 对cgroup中任务的可用内存进行限制,并自动生成资源占用报告
net_cls 使用等级识别符(classid)标记网络数据包,这让 Linux 流量控制程序(tc)可以识别来自特定从cgroup任务的数据包,并进行网络限制
net_prio 允许基于cgroup设置网络流量的优先级
perf_event 允许使用perf工具来监控cgroup
pids 限制任务的数量

资源控制在容器中的实际位置

ll /sys/fs/cgroup/"资源名"/docker/"容器ID"/

Docker 核心组件之间关系

我们使用 Docker client 运行一个容器,其实容器运行时底层是需要依赖一系列组件的,我们完全可以通过调用这些组件去启动一个容器,而不使用 Docker 引擎的方式去启动。主要的组件有 docker client、docker daemon、containerd、container-shim、runC

docker client

docker 客户端程序,负责发送用户的请求给 docker daemon

docker daemon

docker daemon守护进程,也称 docker engine,负责处理 docker client 的请求,并返回处理结果

containerd

containerd 是一个工业级标准的容器运行时,它强调简单性、健壮性和可移植性。Containerd 可以在宿主机中管理完整的容器生命周期:容器镜像的传输和存储、容器的执行和管理、存储和网络等。为 docker daemon 提供接口去管理容器,Docker 对容器的管理和操作基本都是通过 containerd 完成的。但是要注意的是:containerd 被设计成嵌入到一个更大的系统中,而不是直接由开发人员或终端用户使用

container-shim

container-shim 是 containerd 的组件,是容器的运行时载体,我们在 Docker 宿主机上看到的 shim 也正是代表着一个个通过调用containerd 启动的 Docker 容器

ps axf | grep docker -A 1
10191 ?        Sl     0:01  \_ containerd-shim -namespace moby -workdir /var/lib/containerd/io.containerd.runtime.v1.linux/moby/4dffa5d5861899400770d6470618e4e051c5f1bf0c53034999b13821fc3fe93f -address /run/containerd/containerd.sock -containerd-binary /usr/bin/containerd -runtime-root /var/run/docker/runtime-runc
10208 ?        Ss     0:00      \_ nginx: master process nginx -g daemon off;
--
4215 ?        Ssl    2:06 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

runC

RunC 是一个轻量级的工具,它是用来运行容器的。我们可以认为它就是个命令行小工具,可以不用通过 Docker 引擎,直接运行容器。事实上 runC 是标准化的产物,它根据 OCI 标准来创建和运行容器。而 OCI(Open Container Initiative) 组织,旨在围绕容器格式和运行时制定一个开放的工业化标准