Docker运行参考

Docker在隔离的容器中运行进程。容器是在主机上运行的进程。主机可以是本地主机,也可以是远程主机。当操作员执行时docker run,运行的容器进程是独立的,因为它具有自己的文件系统,自己的网络以及独立于主机的独立的进程树。

该页面详细说明了如何docker run在运行时使用命令定义容器的资源。

一般形式

基本docker run命令采用以下形式:

$ docker run [OPTIONS] IMAGE[:TAG|@DIGEST] [COMMAND] [ARG...]

docker run命令必须指定 要从中派生容器的IMAGE。图像开发人员可以定义与以下内容有关的图像默认值:

  • 分离运行或前台运行
  • 容器识别
  • 网络设置
  • CPU和内存的运行时限制

使用,docker run [OPTIONS]操作员可以添加或覆盖开发人员设置的图像默认设置。而且,操作员可以覆盖Docker运行时本身设置的几乎所有默认值。操作员具有覆盖映像和Docker运行时默认值的能力,这就是为什么run具有比其他任何docker命令更多的选项的原因 。

要了解如何解释的类型[OPTIONS],请参阅 选项类型

笔记

根据您的Docker系统配置,您可能需要在docker run命令前加上sudo。为避免使用sudodocker命令,系统管理员可以创建一个Unix组docker,并将其添加用户。有关此配置的更多信息,请参阅您操作系统的Docker安装文档。

运营商专有选项

只有操作员(执行的人员docker run)可以设置以下选项。

独立式vs前景式

启动Docker容器时,必须首先确定要在后台以“分离”模式还是默认的前台模式运行该容器:

-d=false: Detached mode: Run container in the background, print new container id

分离(-d)

要以分离模式启动容器,请使用-d=true或just-d选项。按照设计,以脱机模式启动的容器会在用于运行容器的根进程退出时退出,除非您也指定该--rm选项。如果-d与配合使用 --rm,则在容器退出守护程序退出时(以先发生的为准)将容器删除。

不要将service x start命令传递给分离的容器。例如,此命令尝试启动nginx服务。

$ docker run -d -p 80:80 my_image service nginx start

这成功启动nginx了容器内部的服务。但是,它失败了分离容器范例,因为根进程(service nginx start)返回并且分离容器按设计停止。结果,该 nginx服务已启动但无法使用。相反,要启动诸如nginxWeb服务器之类的进程,请执行以下操作:

$ docker run -d -p 80:80 my_image nginx -g 'daemon off;'

要使用分离的容器进行输入/输出,请使用网络连接或共享卷。这些是必需的,因为容器不再侦听docker run运行所在的命令行。

要重新附加到分离的容器,请使用docker attach命令。

前景

在前台模式下(-d未指定默认值),docker run可以在容器中启动进程并将控制台附加到进程的标准输入,输出和标准错误。它甚至可以假装为TTY(这是大多数命令行可执行文件所期望的)并传递信号。所有这些都是可配置的:

-a=[]           : Attach to `STDIN`, `STDOUT` and/or `STDERR`
-t              : Allocate a pseudo-tty
--sig-proxy=true: Proxy all received signals to the process (non-TTY mode only)
-i              : Keep STDIN open even if not attached

如果您未指定,-a则Docker将同时附加到stdout和stderr 。您可以指定其中三个标准流(STDINSTDOUTSTDERR)你想,而不是连接,如:

$ docker run -a stdin -a stdout -i -t ubuntu /bin/bash

对于交互式进程(如shell),必须-i -t一起使用才能为容器进程分配tty。-i -t通常是-it 在后面的示例中看到的。-t当客户端从管道接收其标准输入时,禁止指定,如:

$ echo test | docker run -i busybox cat

笔记

Linux会特别处理在容器内以PID 1运行的进程:它会忽略具有默认操作的任何信号。结果,该过程将不会终止,SIGINT或者SIGTERM除非被编码为终止该过程。

货柜识别

名称(--name)

操作员可以通过三种方式识别容器:

标识符类型 示例值
UUID长标识符 “ f78375b1c487e03c9438c729345e54db9d20cfa2ac1fc3494b6eb60872e74778”
UUID短标识符 “ f78375b1c487”
名称 “ evil_ptolemy”

UUID标识符来自Docker守护程序。如果未使用该--name选项分配容器名称,则守护程序将为您生成一个随机字符串名称。定义aname是向容器添加含义的便捷方法。如果指定name,则可以在Docker网络中引用容器时使用它。这适用于后台Docker容器和前台Docker容器。

笔记

必须将默认网桥网络上的容器链接起来,以按名称进行通信。

PID当量

最后,为了帮助实现自动化,您可以让Docker将容器ID写出到您选择的文件中。这类似于某些程序将其进程ID写入文件(您已将它们视为PID文件)的方式类似:

--cidfile="": Write the container ID to the file

图片[:tag]

虽然不是严格地标识容器的一种方法,但是您可以通过添加image[:tag]命令来指定要用于运行容器的映像的版本。例如,docker run ubuntu:14.04

图片[@digest]

使用v2或更高版本图像格式的图像具有称为摘要的内容可寻址标识符。只要用于生成图像的输入不变,摘要值就可以预测和参考。

以下示例从alpine带有sha256:9cacb71397b640eca97488cf08582ae4e4068513101088e9f96c9814bfda95e0摘要的图像 运行容器:

$ docker run alpine@sha256:9cacb71397b640eca97488cf08582ae4e4068513101088e9f96c9814bfda95e0 date

PID设置(--pid)

--pid=""  : Set the PID (Process) Namespace mode for the container,
             'container:<name|id>': joins another container's PID namespace
             'host': use the host's PID namespace inside the container

默认情况下,所有容器都启用了PID名称空间。

PID名称空间提供了流程分离。PID命名空间可删除系统进程的视图,并允许重用进程ID,包括pid 1。

在某些情况下,您希望容器共享主机的进程名称空间,基本上允许容器内的进程查看系统上的所有进程。例如,您可以使用诸如strace或的调试工具来构建容器gdb,但是要在调试容器中的进程时使用这些工具。

示例:在容器中运行htop

创建此Dockerfile:

FROM alpine:latest
RUN apk add --update htop && rm -rf /var/cache/apk/*
CMD ["htop"]

构建Dockerfile并将映像标记为myhtop

$ docker build -t myhtop .

使用以下命令htop在容器内运行:

$ docker run -it --rm --pid=host myhtop

加入另一个容器的pid名称空间可用于调试该容器。

例子

启动运行Redis服务器的容器:

$ docker run --name my-redis -d redis

通过运行另一个包含strace的容器来调试redis容器:

$ docker run -it --pid=container:my-redis my_strace_docker_image bash
$ strace -p 1

UTS设置(--uts)

--uts=""  : Set the UTS namespace mode for the container,
       'host': use the host's UTS namespace inside the container

UTS名称空间用于设置主机名和对该名称空间中正在运行的进程可见的域。默认情况下,所有容器(包括带有的容器)--network=host都具有自己的UTS命名空间。该host设置将导致容器使用与主机相同的UTS命名空间。请注意, --hostname--domainnamehostUTS模式下无效。

如果希望容器的主机名随着主机的主机名更改而更改,则可能希望与主机共享UTS命名空间。一个更高级的用例是从容器更改主机的主机名。

IPC设置(--ipc)

--ipc="MODE"  : Set the IPC mode for the container

接受以下值:

价值 描述
”” 使用守护程序的默认值。
“没有任何” 自己的私有IPC名称空间,未安装/ dev / shm。
“私人的” 自己的专用IPC名称空间。
“可共享” 自己的私有IPC名称空间,可以与其他容器共享。
“容器:<_name-or-ID_>” 加入另一个(“可共享”)容器的IPC名称空间。
“主持人” 使用主机系统的IPC名称空间。

如果未指定,则使用守护程序默认值,它可以是"private""shareable",具体取决于守护程序的版本和配置。

IPC(POSIX / SysV IPC)名称空间提供了命名共享内存段,信号量和消息队列的分离。

共享内存段用于以内存速度加速进程间通信,而不是通过管道或网络堆栈。数据库和科学计算和金融服务行业的定制应用程序(通常是C / OpenMPI,C ++ /使用Boost库)通常使用共享内存。如果将这些类型的应用程序分为多个容器,则可能需要共享容器的IPC机制,并使用"shareable"主(即“捐赠者”)容器和"container:<donor-name-or-ID>"其他容器的模式。

网络设置

--dns=[]           : Set custom dns servers for the container
--network="bridge" : Connect a container to a network
                      'bridge': create a network stack on the default Docker bridge
                      'none': no networking
                      'container:<name|id>': reuse another container's network stack
                      'host': use the Docker host network stack
                      '<network-name>|<network-id>': connect to a user-defined network
--network-alias=[] : Add network-scoped alias for the container
--add-host=""      : Add a line to /etc/hosts (host:IP)
--mac-address=""   : Sets the container's Ethernet device's MAC address
--ip=""            : Sets the container's Ethernet device's IPv4 address
--ip6=""           : Sets the container's Ethernet device's IPv6 address
--link-local-ip=[] : Sets one or more container's Ethernet device's link local IPv4/IPv6 addresses

默认情况下,所有容器都启用了联网功能,并且它们可以建立任何传出连接。操作员可以完全禁用网络,docker run --network none从而禁用所有传入和传出网络。在这样的情况下,您将通过文件或执行I / O STDINSTDOUT唯一的。

发布端口和链接到其他容器仅适用于默认端口(桥)。链接功能是旧版功能。与链接相比,您应该始终偏爱使用Docker网络驱动程序。

默认情况下,您的容器将使用与主机相同的DNS服务器,但是您可以使用来覆盖它--dns

默认情况下,MAC地址是使用分配给容器的IP地址生成的。您可以通过使用--mac-address参数(格式12:34:56:78:9a:bc:)提供MAC地址来显式设置容器的MAC地址。请注意,Docker不会检查手动指定的MAC地址是否唯一。

支持的网络:

网络 描述
没有任何 容器中没有网络。
网桥(默认) 通过veth接口将容器连接到桥。
主持人 在容器内使用主机的网络堆栈。
容器:<名称| id> 使用通过其名称id指定的另一个容器的网络堆栈。
网络 将容器连接到用户创建的网络(使用docker network create命令)

网络:无

有了网络,none容器将无法访问任何外部路由。容器仍将 loopback在容器中启用接口,但它没有通往外部流量的任何路由。

网桥

将网络设置为bridge容器后,将使用docker的默认网络设置。在主机上设置了一个网桥,俗称 docker0,并veth为该容器创建了一对接口。该veth对的一侧将保留在连接到网桥的主机上,而该对的另一侧将除了loopback接口之外,还将被放置在容器的命名空间内。将为网桥的网络上的容器分配一个IP地址,流量将通过该网桥路由到容器。

默认情况下,容器可以通过其IP地址进行通信。要通过名称进行通信,必须将它们链接起来。

网络:主机

将网络设置为host容器后,容器将共享主机的网络堆栈,并且来自主机的所有接口将对容器可用。容器的主机名将与主机系统上的主机名匹配。请注意,--mac-addresshostnetmode中无效。即使在host 网络模式下,默认情况下,容器也有其自己的UTS名称空间。这样 --hostname--domainnamehost网络模式下是允许的,并且只会更改容器内的主机名和域名。类似--hostname--add-host--dns--dns-search,和 --dns-option选项可以在使用host网络模式。这些选项将更新 /etc/hosts/etc/resolv.conf在容器内部。没有变化的,以制作 /etc/hosts,并/etc/resolv.conf在主机上。

与默认bridge模式相比,该host模式提供了明显 更好的网络性能,因为它使用了主机的本机网络堆栈,而网桥则必须通过docker守护程序进行一级虚拟化。当容器的网络性能至关重要时,建议以这种模式运行容器,例如生产负载平衡器或高性能Web服务器。

笔记

--network="host" 使容器可以完全访问本地系统服务(例如D-bus),因此被认为是不安全的。

网络:容器

将网络设置为container一个容器后,将共享另一个容器的网络堆栈。另一个容器的名称必须以的格式提供--network container:<name|id>。请注意,--add-host --hostname --dns --dns-search --dns-option--mac-addresscontainer网络模式下无效,并且--publish --publish-all --exposecontainer网络模式下也无效。

使用Redis绑定运行Redis容器,localhost然后运行redis-cli命令并通过localhost接口连接到Redis服务器的 示例。

$ docker run -d --name redis example/redis --bind 127.0.0.1
$ # use the redis container's network stack to access localhost
$ docker run --rm -it --network container:redis example/redis-cli -h 127.0.0.1

用户定义的网络

您可以使用Docker网络驱动程序或外部网络驱动程序插件创建网络。您可以将多个容器连接到同一网络。一旦连接到用户定义的网络,这些容器就可以仅使用另一个容器的IP地址或名称轻松进行通信。

对于overlay支持多主机连接的网络或自定义插件,连接到同一多主机网络但从不同引擎启动的容器也可以这种方式进行通信。

以下示例使用内置bridge网络驱动程序并在创建的网络中运行容器来创建网络

$ docker network create -d bridge my-net
$ docker run --network=my-net -itd --name=container3 busybox

管理/ etc / hosts

您的容器将包含/etc/hosts定义容器本身的主机名以及localhost其他一些常见内容的行。该 --add-host标志可用于向添加其他行/etc/hosts

$ docker run -it --add-host db-static:86.75.30.9 ubuntu cat /etc/hosts

172.17.0.22     09d03f76bf2c
fe00::0         ip6-localnet
ff00::0         ip6-mcastprefix
ff02::1         ip6-allnodes
ff02::2         ip6-allrouters
127.0.0.1       localhost
::1	            localhost ip6-localhost ip6-loopback
86.75.30.9      db-static

如果某个容器已连接到默认网桥网络并linked 与其他容器连接,则该容器的/etc/hosts文件将使用链接的容器的名称进行更新。

笔记

由于Docker可以实时更新容器的/etc/hosts文件,因此在某些情况下,容器内的进程最终可能会读取空/etc/hosts文件或不完整的文件。在大多数情况下,重试读取应该可以解决该问题。

重新启动策略(-重新启动)

使用--restartDocker run上的标志,您可以指定重启策略,以指定如何在退出时重启容器。

当重新启动策略是活性的容器上,它将被显示为任一UpRestartingdocker psdocker events查看生效的重启策略也很有用。

Docker支持以下重启策略:

政策 结果
退出时不要自动重启容器。这是默认值。
失败[:max-retries] 仅当容器以非零退出状态退出时,才重新启动。(可选)限制Docker守护进程尝试重新启动的重试次数。
总是 无论退出状态如何,请始终重新启动容器。当您始终指定时,Docker守护程序将尝试无限期重启容器。无论容器的当前状态如何,该容器还将始终在守护程序启动时启动。
除非停止 无论退出状态如何(包括守护程序启动时),无论退出状态如何,都应始终重新启动容器,除非容器在停止Docker守护程序之前已处于停止状态。

在每次重新启动之前,添加一个不断增加的延迟(从100毫秒开始,是以前的延迟的两倍),以防止服务器泛滥。这意味着守护程序将等待100毫秒,然后等待200毫秒,400、800、1600等,直到达到on-failure限制,或者您docker stop 或您docker rm -f的容器处于等待状态。

如果容器成功重新启动(容器已启动并运行至少10秒钟),则延迟将重置为其默认值100毫秒。

您可以指定使用失败模式时Docker尝试重新启动容器的最大次数。默认是Docker将永远尝试重新启动容器。可以通过获取容器的(尝试的)重新启动次数docker inspect。例如,获取容器“ my-container”的重新启动次数;


$ docker inspect -f "{{ .RestartCount }}" my-container
# 2

或者,获取上一次(重新)启动容器的时间;


$ docker inspect -f "{{ .State.StartedAt }}" my-container
# 2015-03-04T23:47:07.691840179Z

--restart(重新启动策略)与--rm(清除)标志结合使用会导致错误。容器重新启动时,连接的客户端将断开连接。请参阅本页后面有关使用--rm(清除)标志的示例。

例子

$ docker run --restart=always redis

这将以始终redis为重启策略的方式运行该容器, 以便如果该容器退出,则Docker将重新启动它。

$ docker run --restart=on-failure:10 redis

这将以失败时redis重启策略运行容器, 最大重启次数为10。如果容器连续以非零退出状态退出超过10次,则Docker将中止尝试重启容器的操作。提供最大重启限制仅对失败策略有效 。redis

退出状态

的退出代码docker run提供有关为何容器无法运行或为何退出的信息。当docker run使用非零代码退出时,退出代码遵循chroot标准,请参见以下内容:

125(如果错误是由Docker守护程序本身造成的)

$ docker run --foo busybox; echo $?

flag provided but not defined: --foo
See 'docker run --help'.
125

126如果无法调用所包含的命令

$ docker run busybox /etc; echo $?

docker: Error response from daemon: Container command '/etc' could not be invoked.
126

127如果找不到所包含的命令

$ docker run busybox foo; echo $?

docker: Error response from daemon: Container command 'foo' not found or does not exist.
127

否则退出包含命令的代码

$ docker run busybox /bin/sh -c 'exit 3'; echo $?

3

清理(​​--rm)

默认情况下,即使容器退出后,容器的文件系统也会保留。这使调试容易得多(因为您可以检查最终状态),并且默认情况下保留所有数据。但是,如果您正在运行短期前台进程,那么这些容器文件系统确实会堆积起来。相反,如果您希望Docker 在容器退出时自动清理容器并删除文件系统,则可以添加--rm标志:

--rm=false: Automatically remove the container when it exits

笔记

如果设置了该--rm标志,则在删除容器时,Docker也将删除与该容器关联的匿名卷。这类似于运行docker rm -v my-container。仅删除没有名称的指定卷。例如,运行时:

docker run --rm -v /foo -v awesome:/bar busybox top

的音量/foo将被删除,但的音量不会被移除/bar--volumes-from将通过相同的逻辑删除通过继承的卷:如果使用名称指定了原始卷,则不会删除该卷。

安全配置

选项 描述
--security-opt="label=user:USER" 设置容器的标签用户
--security-opt="label=role:ROLE" 设置容器的标签角色
--security-opt="label=type:TYPE" 设置容器的标签类型
--security-opt="label=level:LEVEL" 设置容器的标签级别
--security-opt="label=disable" 关闭容器的标签限制
--security-opt="apparmor=PROFILE" 设置要应用于容器的apparmor配置文件
--security-opt="no-new-privileges:true" 禁止容器进程获取新特权
--security-opt="seccomp=unconfined" 关闭容器的seccomp限制
--security-opt="seccomp=profile.json" 白名单中的syscalls seccomp Json文件用作seccomp筛选器

您可以通过指定--security-opt标志来覆盖每个容器的默认标签方案。在以下命令中指定级别允许您在容器之间共享相同的内容。

$ docker run --security-opt label=level:s0:c100,c200 -it fedora bash

笔记

当前不支持MLS标签的自动翻译。

要禁用此容器的安全标签而不是使用该--privileged标志运行 ,请使用以下命令:

$ docker run --security-opt label=disable -it fedora bash

如果要对容器内的进程采用更严格的安全策略,则可以为容器指定其他类型。您可以通过执行以下命令来运行仅允许在Apache端口上侦听的容器:

$ docker run --security-opt label=type:svirt_apache_t -it centos bash

笔记

您将必须编写定义svirt_apache_t类型的策略。

如果要阻止容器进程获得其他特权,可以执行以下命令:

$ docker run --security-opt no-new-privileges -it centos bash

这意味着发出诸如su或的特权的命令sudo将不再起作用。它还会导致在删除特权后,稍后再应用任何seccomp过滤器,这可能意味着您可以使用一组限制性更强的过滤器。有关更多详细信息,请参见内核文档

指定一个初始化过程

您可以使用该--init标志指示应将初始化进程用作容器中的PID 1。指定初始化过程可确保在创建的容器内执行初始化系统的通常职责,例如获取僵尸进程。

使用的默认初始化进程是docker-init在Docker守护进程的系统路径中找到的第一个可执行文件。docker-init默认安装中包含的此二进制文件由tini支持。

指定自定义cgroup

使用该--cgroup-parent标志,您可以传递特定的cgroup来运行容器。这允许您自己创建和管理cgroup。您可以为这些cgroup定义自定义资源,并将容器放在公共父组下。

资源的运行时限制

操作员还可以调整容器的性能参数:

选项 描述
-m--memory="" 内存限制(格式:)<number>[<unit>]。数字是一个正整数。单位可以是一个bkm,或g。最小为4M。
--memory-swap="" 总内存限制(内存+交换,格式:)<number>[<unit>]。数字是一个正整数。单位可以是一个bkm,或g
--memory-reservation="" 内存软限制(格式:)<number>[<unit>]。数字是一个正整数。单位可以是一个bkm,或g
--kernel-memory="" 内核内存限制(格式:)<number>[<unit>]。数字是一个正整数。单位可以是一个bkm,或g。最小为4M。
-c--cpu-shares=0 CPU份额(相对重量)
--cpus=0.000 CPU数量。数字是小数。0.000表示没有限制。
--cpu-period=0 限制CPU CFS(完全公平的调度程序)期限
--cpuset-cpus="" 允许执行的CPU(0-3,0,1)
--cpuset-mems="" 允许执行的内存节点(MEM)(0-3,0,1)。仅在NUMA系统上有效。
--cpu-quota=0 限制CPU CFS(完全公平的调度程序)配额
--cpu-rt-period=0 限制CPU的实时时间。以微秒为单位。需要设置父级cgroup,并且不能高于父级cgroup。还要检查rtprio ulimits。
--cpu-rt-runtime=0 限制CPU实时运行时间。以微秒为单位。需要设置父级cgroup,并且不能高于父级cgroup。还要检查rtprio ulimits。
--blkio-weight=0 块IO权重(相对权重)接受10到1000之间的权重值。
--blkio-weight-device="" 块IO重量(相对设备重量,格式:DEVICE_NAME:WEIGHT
--device-read-bps="" 限制从设备读取的速率(格式:)<device-path>:<number>[<unit>]。数字是一个正整数。单位可以是一个kbmbgb
--device-write-bps="" 将写入速率限制为设备(格式:)<device-path>:<number>[<unit>]。数字是一个正整数。单位可以是一个kbmbgb
--device-read-iops="" 限制从设备(格式:)的读取速率(每秒IO <device-path>:<number>)。数字是一个正整数。
--device-write-iops="" 将写入速率(每秒的IO)限制为设备(格式:)<device-path>:<number>。数字是一个正整数。
--oom-kill-disable=false 是否为容器禁用OOM Killer。
--oom-score-adj=0 调整容器的OOM首选项(-1000到1000)
--memory-swappiness="" 调整容器的内存交换行为。接受0到100之间的整数。
--shm-size="" 的大小/dev/shm。格式为<number><unit>number必须大于0。单位是可选的,可以是b(字节),k(千字节),m(兆字节)或g(千兆字节)。如果省略单位,则系统使用字节。如果您完全省略尺寸,系统将使用64m

用户内存限制

我们有四种设置用户内存使用率的方法:

选项 结果
memory = inf,memory-swap = inf(默认) 容器没有内存限制。该容器可以根据需要使用尽可能多的内存。
内存= L <inf,内存交换= inf (指定内存,并将memory-swap设置为-1)容器不允许使用超过L个字节的内存,但是可以根据需要使用尽可能多的交换空间(如果主机支持交换内存)。
内存= L <inf,内存交换= 2 * L (请指定无内存交换的内存)容器不得使用超过L个字节的内存,而交换内存使用量则是该字节的两倍。
内存= L <inf,内存交换= S <inf,L <= S (同时指定内存和内存交换)容器不允许使用超过L个字节的内存,交换内存使用量受S限制。

例子:

$ docker run -it ubuntu:14.04 /bin/bash

我们没有对内存进行任何设置,这意味着容器中的进程可以使用所需的内存并交换所需的内存。

$ docker run -it -m 300M --memory-swap -1 ubuntu:14.04 /bin/bash

我们设置了内存限制和禁用了交换内存限制,这意味着容器中的进程可以使用300M内存,并根据需要使用尽可能多的交换内存(如果主机支持交换内存)。

$ docker run -it -m 300M ubuntu:14.04 /bin/bash

我们仅设置内存限制,这意味着容器中的进程可以使用300M内存和300M交换内存,默认情况下,总虚拟内存大小(--memory-swap)将设置为内存的两倍,在这种情况下,内存+ swap将为2 * 300M,因此进程也可以使用300M交换内存。

$ docker run -it -m 300M --memory-swap 1G ubuntu:14.04 /bin/bash

我们同时设置了内存和交换内存,因此容器中的进程可以使用300M内存和700M交换内存。

内存预留是一种内存软限制,它可以实现更大的内存共享。在正常情况下,容器可以根据需要使用尽可能多的内存,并且仅受-m/--memory选项设置的硬性限制 。设置内存预留后,Docker会检测到内存争用或内存不足,并强制容器将其使用限制为预留限制。

始终将内存保留值设置为硬限制以下,否则硬限制优先。保留为0等于不设置保留。默认情况下(未设置保留),内存保留与硬盘限制相同。

内存保留是一项软限制功能,不能保证不会超出限制。取而代之的是,该功能试图确保在内存竞争激烈时,根据预留提示/设置分配内存。

以下示例将内存(-m)限制为500M,并将内存预留设置为200M。

$ docker run -it -m 500M --memory-reservation 200M ubuntu:14.04 /bin/bash

在这种配置下,当容器消耗的内存大于200M且小于500M时,下一个系统内存回收将尝试将容器内存缩小到200M以下。

下面的示例将内存保留设置为1G,没有硬盘限制。

$ docker run -it --memory-reservation 1G ubuntu:14.04 /bin/bash

容器可以使用所需的内存。内存预留设置可确保容器长时间不占用过多内存,因为每次回收内存都会将容器的消耗减少到预留空间。

默认情况下,如果发生内存不足(OOM)错误,内核将终止容器中的进程。要更改此行为,请使用该--oom-kill-disable选项。仅在还设置了该-m/--memory选项的容器上禁用OOM杀手 。如果-m未设置该标志,则可能导致主机内存不足,并要求终止主机的系统进程以释放内存。

以下示例将内存限制为100M,并为此容器禁用OOM杀手:

$ docker run -it -m 100M --oom-kill-disable ubuntu:14.04 /bin/bash

下面的示例说明了使用标志的一种危险方式:

$ docker run -it --oom-kill-disable ubuntu:14.04 /bin/bash

容器具有无限的内存,这可能导致主机内存用完,并需要终止系统进程来释放内存。--oom-score-adj 可以更改该参数以选择当系统内存不足时将杀死哪些容器的优先级,负分数使它们被杀死的可能性较小,而正分数则更有可能被杀死。

内核内存限制

内核内存与用户内存在根本上是不同的,因为不能交换内核内存。无法交换使得容器有可能通过消耗过多的内核内存来阻止系统服务。内核内存包括:

  • 堆叠页面
  • 平板页面
  • 插槽内存压力
  • tcp内存压力

您可以设置内核内存限制来限制这些类型的内存。例如,每个进程都消耗一些堆栈页面。通过限制内核内存,可以防止内核内存使用率过高时创建新进程。

内核内存永远不会完全独立于用户内存。而是在用户内存限制的范围内限制内核内存。假设“ U”是用户内存限制,“ K”是内核限制。可以使用三种方法来设置限制:

选项 结果
U!= 0,K = inf(默认) 这是使用内核内存之前已经存在的标准内存限制机制。内核内存被完全忽略。
U!= 0,K <U 内核内存是用户内存的子集。此设置在每个cgroup的内存总量被过量使用的部署中很有用。绝对不建议过度使用内核内存限制,因为此框仍然会耗尽不可回收的内存。在这种情况下,您可以配置K,以使所有组的总和永远不大于总内存。然后,以系统的服务质量为代价自由设置U。
U!= 0,K> U 由于内核内存费用也被馈送到用户计数器,并且针对两种内存的容器都将触发回收。此配置为管理员提供了内存的统一视图。对于只想跟踪内核内存使用情况的人来说,它也很有用。

例子:

$ docker run -it -m 500M --kernel-memory 50M ubuntu:14.04 /bin/bash

我们设置了内存和内核内存,因此容器中的进程总共可以使用500M内存,在这500M内存中,它可以是50M内核内存的顶部。

$ docker run -it --kernel-memory 50M ubuntu:14.04 /bin/bash

我们在不使用-m的情况下设置了内核内存,因此容器中的进程可以使用所需数量的内存,但是它们只能使用50M内核内存。

Swappiness约束

默认情况下,容器的内核可以换出一定比例的匿名页面。要为容器设置此百分比,请指定--memory-swappiness0到100之间的值。0值将关闭匿名页面交换。值100会将所有匿名页面设置为可交换。默认情况下,如果不使用 --memory-swappiness,则将从父级继承内存交换值。

例如,您可以设置:

$ docker run -it --memory-swappiness=0 ubuntu:14.04 /bin/bash

--memory-swappiness当您想要保留容器的工作集并避免交换性能损失时,设置该选项将很有帮助。

CPU份额限制

默认情况下,所有容器获得相同比例的CPU周期。可以通过更改容器的CPU份额权重(相对于所有其他正在运行的容器的权重)来修改此比例。

要从默认值1024修改比例,请使用-c--cpu-shares 标志将权重设置为2或更高。如果设置为0,则系统将忽略该值,并使用默认值1024。

该比例仅在运行CPU密集型进程时适用。当一个容器中的任务处于空闲状态时,其他容器可以使用剩余的CPU时间。实际的CPU时间量将根据系统上运行的容器数而有所不同。

例如,考虑三个容器,一个容器的cpu份额为1024,另外两个容器的cpu份额设置为512。当所有三个容器中的进程尝试使用100%的CPU时,第一个容器将获得50%的CPU。总CPU时间。如果添加第四个容器的cpu份额为1024,则第一个容器仅获得33%的CPU。剩余的容器接收CPU的16.5%,16.5%和33%。

在多核系统上,CPU时间的份额分配在所有CPU核上。即使容器限制为少于100%的CPU时间,它也可以使用每个CPU核心的100%。

例如,考虑具有三个以上的系统