运行容器
Docker 在隔离的容器中运行进程。容器是一个进程
,它在主机上运行。主机可以是本地的,也可以是远程的。当您
执行docker run
,则运行的容器进程被隔离在
它有自己的文件系统、自己的网络和自己的
与主机分开的隔离进程树。
本页详细介绍了如何使用docker run
命令运行容器。
一般形式
一个docker run
command 采用以下形式:
$ docker run [OPTIONS] IMAGE[:TAG|@DIGEST] [COMMAND] [ARG...]
这docker run
命令必须指定要从中创建容器的镜像引用。
图片引用
镜像引用是镜像的名称和版本。您可以使用该镜像 引用创建或运行基于镜像的容器。
docker run IMAGE[:TAG][@DIGEST]
docker create IMAGE[:TAG][@DIGEST]
image 标签是 image 版本,默认为latest
当省略时。用
用于从特定版本的镜像运行容器的标签。例如,到
运行版本24.04
的ubuntu
镜像:docker run ubuntu:24.04
.
镜像摘要
使用 v2 或更高版本镜像格式的镜像具有内容可寻址标识符 称为摘要。只要用于生成镜像的输入保持不变, Digest 值是可预测的。
以下示例从alpine
image 替换为sha256:9cacb71397b640eca97488cf08582ae4e4068513101088e9f96c9814bfda95e0
消化:
$ docker run alpine@sha256:9cacb71397b640eca97488cf08582ae4e4068513101088e9f96c9814bfda95e0 date
选项
[OPTIONS]
用于配置容器的选项。例如,您可以
为容器命名 (--name
) 或将其作为后台进程运行 (-d
).
您还可以设置选项来控制资源约束和
联网。
命令和参数
您可以使用[COMMAND]
和[ARG...]
要指定的位置参数
命令和参数,以便容器在启动时运行。例如
您可以指定sh
作为[COMMAND]
与-i
和-t
标志
要在容器中启动交互式 shell(如果您选择的镜像具有sh
可执行PATH
).
$ docker run -it IMAGE sh
注意
根据您的 Docker 系统配置,您可能会 required 作为
docker run
command 替换为sudo
.为避免 必须使用sudo
使用docker
命令、您的系统 管理员可以创建一个名为docker
并将用户添加到 它。有关此配置的更多信息,请参阅 Docker 作系统的安装文档。
前景和背景
启动容器时,容器默认在前台运行。
如果您想在后台运行容器,可以使用--detach
(或-d
) 标志。这将启动容器,而不会占用您的
终端窗口。
$ docker run -d <IMAGE>
当容器在后台运行时,您可以与容器交互
使用其他 CLI 命令。例如docker logs
用于查看
容器,以及docker attach
将其置于前台。
$ docker run -d nginx
0246aa4d1448a401cabd2ce8f242192b6e7af721527e48a810463366c7ff54f1
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0246aa4d1448 nginx "/docker-entrypoint.…" 2 seconds ago Up 1 second 80/tcp pedantic_liskov
$ docker logs -n 5 0246aa4d1448
2023/11/06 15:58:23 [notice] 1#1: start worker process 33
2023/11/06 15:58:23 [notice] 1#1: start worker process 34
2023/11/06 15:58:23 [notice] 1#1: start worker process 35
2023/11/06 15:58:23 [notice] 1#1: start worker process 36
2023/11/06 15:58:23 [notice] 1#1: start worker process 37
$ docker attach 0246aa4d1448
^C
2023/11/06 15:58:40 [notice] 1#1: signal 2 (SIGINT) received, exiting
...
有关docker run
与 foreground 和
背景模式,请参阅:
docker run --detach
:在后台运行容器docker run --attach
:䵗stdin
,stdout
和stderr
docker run --tty
:分配一个伪 ttydocker run --interactive
:保持stdin
即使未连接也打开
有关重新附加到后台容器的更多信息,请参阅docker attach
.
容器识别
您可以通过三种方式识别容器:
标识符类型 | 示例值 |
---|---|
UUID 长标识符 | f78375b1c487e03c9438c729345e54db9d20cfa2ac1fc3494b6eb60872e74778 |
UUID 短标识符 | f78375b1c487 |
名字 | evil_ptolemy |
UUID 标识符是守护程序分配给容器的随机 ID。
守护程序会自动为容器生成一个随机字符串名称。您可以
还可以使用这--name
旗.
定义name
可以成为为容器添加含义的便捷方式。如果你
指定一个name
中,您可以在
用户定义的网络。这适用于后台和前台 Docker
器皿。
容器标识符与镜像引用不是一回事。镜像
reference 指定在运行容器时要使用的镜像。你不能运行docker exec nginx:alpine sh
在容器中打开 shell 时,请根据nginx:alpine
镜像,因为docker exec
需要一个容器标识符
(name 或 ID),而不是镜像。
虽然容器使用的镜像不是容器的标识符,但您可以
使用 Image 查找容器的 ID--filter
旗。为
example,则以下docker ps
command 获取所有正在运行的
基于nginx:alpine
镜像:
$ docker ps -q --filter ancestor=nginx:alpine
有关使用筛选条件的更多信息,请参阅筛选。
容器联网
容器默认启用联网,并且它们可以将 连接。如果您正在运行多个需要通信的容器 您可以创建自定义网络并将容器附加到 网络。
当多个容器连接到同一个自定义网络时,它们可以
使用容器名称作为 DNS 主机名相互通信。这
以下示例创建一个名为my-net
运行两个
连接到网络的容器。
$ docker network create my-net
$ docker run -d --name web --network my-net nginx:alpine
$ docker run --rm -it --network my-net busybox
/ # ping web
PING web (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.326 ms
64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.257 ms
64 bytes from 172.18.0.2: seq=2 ttl=64 time=0.281 ms
^C
--- web ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.257/0.288/0.326 ms
有关容器联网的更多信息,请参阅联网 概述
文件系统挂载
默认情况下,容器中的数据存储在临时的可写 容器层。删除容器也会删除其数据。如果您想 将持久数据与容器结合使用,您可以使用 Filesystem 挂载来存储 data 持久地存储在主机系统上。文件系统挂载还可以让您共享 容器和主机之间的数据。
Docker 支持两种主要类别的挂载:
- 卷挂载
- 绑定挂载
卷挂载非常适合为容器持久存储数据,以及 在容器之间共享数据。另一方面,Bind mounts 用于 在容器和主机之间共享数据。
您可以使用--mount
flag 的docker run
命令。
以下部分显示了如何创建卷和绑定的基本示例 坐骑。有关更深入的示例和描述,请参阅 文档中的 storage 部分。
卷挂载
要创建卷挂载:
$ docker run --mount source=<VOLUME_NAME>,target=[PATH] [IMAGE] [COMMAND...]
这--mount
在本例中,flag 接受两个参数:source
和target
.
的source
parameter 是卷的名称。的值target
是容器内卷的挂载位置。一旦你
创建了卷,则写入卷的任何数据都会保留,即使您
停止或移除容器:
$ docker run --rm --mount source=my_volume,target=/foo busybox \
echo "hello, volume!" > /foo/hello.txt
$ docker run --mount source=my_volume,target=/bar busybox
cat /bar/hello.txt
hello, volume!
这target
必须始终是绝对路径,例如/src/docs
.绝对的
path 以 (正斜杠) 开头。卷名称必须以
字母数字字符,后跟/
a-z0-9
、(下划线)、_
.
(句点)或 (连字符)。-
绑定挂载
要创建绑定挂载:
$ docker run -it --mount type=bind,source=[PATH],target=[PATH] busybox
在这种情况下,--mount
flag 接受三个参数。A 型 (bind
) 和
两条路径。这source
path 是主机上要
将 mount 绑定到容器中。这target
path 是挂载目标
在容器内。
默认情况下,绑定挂载是读写的,这意味着您可以读取和写入 文件从容器挂载位置。更改 make(例如添加或编辑文件)会反映在主机文件系统上:
$ docker run -it --mount type=bind,source=.,target=/foo busybox
/ # echo "hello from container" > /foo/hello.txt
/ # exit
$ cat hello.txt
hello from container
退出状态
的退出代码docker run
提供有关容器原因的信息
运行失败或退出原因。以下部分描述了
不同的容器退出代码值。
125
退出代码125
表示错误与 Docker 守护程序本身有关。
$ docker run --foo busybox; echo $?
flag provided but not defined: --foo
See 'docker run --help'.
125
126
退出代码126
指示无法调用指定的 contained 命令。
以下示例中的 container 命令为:/etc
.
$ docker run busybox /etc; echo $?
docker: Error response from daemon: Container command '/etc' could not be invoked.
126
127
退出代码127
表示找不到包含的命令。
$ docker run busybox foo; echo $?
docker: Error response from daemon: Container command 'foo' not found or does not exist.
127
其他退出代码
除125
,126
和127
表示
提供的 container 命令。
$ docker run busybox /bin/sh -c 'exit 3'
$ echo $?
3
资源的运行时约束
作员还可以调整 容器:
选择 | 描述 |
---|---|
-m ,--memory="" | 内存限制(格式:<number>[<unit>] ).Number 是一个正整数。单位可以是以下之一b ,k ,m 或g .最小值为 6M。 |
--memory-swap="" | 总内存限制(内存 + 交换,格式:<number>[<unit>] ).Number 是一个正整数。单位可以是以下之一b ,k ,m 或g . |
--memory-reservation="" | 内存软限制(格式:<number>[<unit>] ).Number 是一个正整数。单位可以是以下之一b ,k ,m 或g . |
--kernel-memory="" | 内核内存限制(格式:<number>[<unit>] ).Number 是一个正整数。单位可以是以下之一b ,k ,m 或g .最小值为 4M。 |
-c ,--cpu-shares=0 | CPU 份额(相对权重) |
--cpus=0.000 | CPU 数量。Number 是一个小数。0.000 表示没有限制。 |
--cpu-period=0 | 限制 CPU CFS (Completely Fair Scheduler) 周期 |
--cpuset-cpus="" | 允许执行的 CPU (0-3, 0,1) |
--cpuset-mems="" | 允许在其中执行的内存节点 (MEM) (0-3, 0,1)。仅在 NUMA 系统上有效。 |
--cpu-quota=0 | 限制 CPU CFS (Completely Fair Scheduler) 配额 |
--cpu-rt-period=0 | 限制 CPU 实时周期。以微秒为单位。需要设置 parent cgroup,并且不能高于 parent。还要检查 rtprio ulimits。 |
--cpu-rt-runtime=0 | 限制 CPU 实时运行时间。以微秒为单位。需要设置 parent cgroup,并且不能高于 parent。还要检查 rtprio ulimits。 |
--blkio-weight=0 | 数据块 IO 权重 (相对权重) 接受介于 10 和 1000 之间的权重值。 |
--blkio-weight-device="" | 块 IO 权重(相对设备权重,格式:DEVICE_NAME:WEIGHT ) |
--device-read-bps="" | 限制设备的读取速率(格式:<device-path>:<number>[<unit>] ).Number 是一个正整数。单位可以是以下之一kb ,mb 或gb . |
--device-write-bps="" | 限制设备的写入速率 (格式:<device-path>:<number>[<unit>] ).Number 是一个正整数。单位可以是以下之一kb ,mb 或gb . |
--device-read-iops="" | 限制设备读取速率(每秒 IO)(格式:<device-path>:<number> ).Number 是一个正整数。 |
--device-write-iops="" | 限制对设备的写入速率(每秒 IO)(格式:<device-path>:<number> ).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 (默认) | 容器没有内存限制。容器可以使用 所需内存。 |
memory=L<inf,memory-swap=inf | (指定 memory 并将 memory-swap 设置为-1 ) 容器为
不允许使用超过 L 字节的内存,但可以使用尽可能多的 swap
根据需要(如果主机支持 Swap Memory)。 |
内存=L<inf,内存交换=2*L | (指定不带 memory-swap 的内存)容器不允许 使用超过 L 字节的内存,交换加内存使用量翻倍 的。 |
内存=L<inf, 内存交换=S<inf, L<=S | (指定 memory 和 memory-swap)容器不允许 使用超过 L 字节的内存,交换加内存使用受到限制 发帖人S. |
例子:
$ docker run -it ubuntu:24.04 /bin/bash
我们没有设置内存,这意味着容器中的进程可以使用 所需数量的内存和 swap 内存。
$ docker run -it -m 300M --memory-swap -1 ubuntu:24.04 /bin/bash
我们设置了内存限制并禁用了 swap 内存限制,这意味着 容器可以使用 300M 内存和所需的交换内存(如果 host 支持交换内存)。
$ docker run -it -m 300M ubuntu:24.04 /bin/bash
我们只设置内存限制,这意味着容器中的进程可以使用 300M 内存和 300M 交换内存,默认情况下,虚拟内存总大小 (--memory-swap) 将设置为双倍内存,在本例中为 memory + swap 将是 2*300M,因此进程也可以使用 300M 交换内存。
$ docker run -it -m 300M --memory-swap 1G ubuntu:24.04 /bin/bash
我们同时设置了 memory 和 swap memory,这样容器中的进程就可以使用 300M 内存和 700M 交换内存。
内存预留是一种内存软限制,它允许更大的
共享内存。在正常情况下,容器可以使用尽可能多的
内存,并且仅受使用-m
/--memory
选择。设置内存预留后,Docker 会检测内存
争用或内存不足,并强制容器将其消耗限制为
预留限制。
始终将内存预留值设置为低于硬限制,否则将 limit 优先。预留 0 等同于设置 no 保留。默认情况下(未设置预留),内存预留是 与 Hard Memory 限制相同。
内存预留是一种软限制功能,不保证限制 不会超过。相反,该功能会尝试确保当内存为 内存是根据预留提示/设置分配的。
以下示例限制内存 (-m
) 设置为 500M,并将内存
reservation 到 200M。
$ docker run -it -m 500M --memory-reservation 200M ubuntu:24.04 /bin/bash
在此配置下,当容器消耗内存超过 200M 且 小于 500M 时,下一次系统内存回收会尝试收缩容器 内存低于 200M。
以下示例将内存预留设置为 1G,没有硬内存限制。
$ docker run -it --memory-reservation 1G ubuntu:24.04 /bin/bash
容器可以根据需要使用任意数量的内存。内存预留设置 确保容器不会长时间消耗太多内存,因为 每次内存回收都会将容器的消耗缩减到预留。
默认情况下,如果内存不足 (OOM)
发生错误。要更改此行为,请使用--oom-kill-disable
选择。
仅在您还设置了-m/--memory
选择。如果-m
标志,这可能会导致主机
内存不足,需要终止主机的系统进程才能释放
记忆。
以下示例将内存限制为 100M,并禁用 此容器:
$ docker run -it -m 100M --oom-kill-disable ubuntu:24.04 /bin/bash
以下示例说明了使用标志的危险方法:
$ docker run -it --oom-kill-disable ubuntu:24.04 /bin/bash
容器具有无限内存,这可能会导致主机耗尽内存
并且需要终止系统进程以释放内存。这--oom-score-adj
参数以选择哪些容器将
当系统内存不足时被杀死,负分使它们
被杀死的可能性较小,而正分的可能性更大。
内核内存约束
内核内存与用户内存有着根本的不同,因为内核内存不能 被换掉。无法交换使容器可以 通过消耗过多的内核内存来阻止系统服务。内核内存包括:
- 堆栈页面
- 板页
- sockets 内存压力
- TCP 内存压力
您可以设置 kernel memory limit 来限制这些类型的内存。例如 每个进程都会消耗一些堆栈页。通过限制内核内存,您可以 防止在内核内存使用率过高时创建新进程。
内核内存从来都不是完全独立于用户内存的。相反,您可以限制 kernel memory 在用户内存限制的上下文中。假设 “U” 是用户内存 limit 和 “K” 内核限制。有三种可能的方法可以设置限制:
选择 | 结果 |
---|---|
U != 0, K = inf (默认) | 这是在使用 内核内存。内核内存被完全忽略。 |
U != 0, K < U | 内核内存是用户内存的子集。此设置在 每个 cgroup 的内存总量超额使用的部署。 绝对不建议过度使用内核内存限制,因为 Box 仍会耗尽不可回收的内存。 在这种情况下,您可以配置 K,以便所有组的总和 永远不会大于总内存。然后,以牺牲 系统的服务质量。 |
U != 0, K > U | 由于内核内存费用也被馈送到用户计数器和回收 为这两种内存的容器触发。此配置 为 Admin 提供统一的内存视图。它对人们也很有用 谁只想跟踪内核内存使用情况。 |
例子:
$ docker run -it -m 500M --kernel-memory 50M ubuntu:24.04 /bin/bash
我们设置了 memory 和 kernel memory,这样容器中的进程就可以使用 总共 500M 内存,在这 500M 内存中,可以是 50M 内核内存的顶部。
$ docker run -it --kernel-memory 50M ubuntu:24.04 /bin/bash
我们设置内核内存时没有 -m,这样容器中的进程就可以 他们想用多少内存就用多少,但是他们只能用 50M 的内核内存。
Swappiness 约束
默认情况下,容器的内核可以换出一定比例的匿名页面。
要为容器设置此百分比,请指定--memory-swappiness
价值
介于 0 和 100 之间。值为 0 将关闭匿名页面交换。值
100 会将所有匿名页面设置为可交换页面。默认情况下,如果您未使用--memory-swappiness
,内存交换值将从父级继承。
例如,您可以设置:
$ docker run -it --memory-swappiness=0 ubuntu:24.04 /bin/bash
设置--memory-swappiness
选项非常有用,当您想保留
容器的工作集,以避免交换性能损失。
CPU 份额约束
默认情况下,所有容器获得相同比例的 CPU 周期。此比例 可以通过更改容器的 CPU 份额权重相对 添加到所有其他正在运行的容器的权重。
要修改默认 1024 的比例,请使用-c
或--cpu-shares
标志将权重设置为 2 或更高。如果设置为 0,系统将忽略
值并使用默认值 1024。
该比例仅在 CPU 密集型进程运行时适用。 当一个容器中的任务空闲时,其他容器可以使用 剩余 CPU 时间。实际 CPU 时间量会有所不同,具体取决于 系统上运行的容器数。
例如,考虑三个容器,一个容器的 cpu-share 为 1024,并且 另外两个项目的 CPU 份额设置为 512。When 进程 容器尝试使用 100% 的 CPU,第一个容器将收到 总 CPU 时间的 50%。如果您添加具有 cpu-share 的第四个容器 的 1024 个容器中,第一个容器仅获得 33% 的 CPU。其余容器 获得 16.5%、16.5% 和 33% 的 CPU。
在多核系统上,CPU 时间份额分布在所有 CPU 上 核心。即使容器被限制在小于 100% 的 CPU 时间,它也可以 使用每个 CPU 内核的 100%。
例如,考虑具有三个以上内核的系统。如果您开始一个
容器{C0}
跟-c=512
运行一个进程和另一个容器{C1}
跟-c=1024
运行两个进程,这可能会导致以下结果
CPU 份额划分:
PID container CPU CPU share
100 {C0} 0 100% of CPU0
101 {C1} 1 100% of CPU1
102 {C1} 2 100% of CPU2
CPU 周期约束
默认的 CPU CFS (Completely Fair Scheduler) 周期为 100 毫秒。我们可以使用--cpu-period
设置 CPU 的周期以限制容器的 CPU 使用率。
通常--cpu-period
应该适用于--cpu-quota
.
例子:
$ docker run -it --cpu-period=50000 --cpu-quota=25000 ubuntu:24.04 /bin/bash
如果有 1 个 CPU,这意味着容器每 50 毫秒可以获得 50% 的 CPU 运行时间。
除了使用--cpu-period
和--cpu-quota
用于设置 CPU 周期约束,
可以指定--cpus
替换为 float 数字来实现相同的目的。
例如,如果有 1 个 CPU,则--cpus=0.5
将获得与
设置--cpu-period=50000
和--cpu-quota=25000
(50% CPU)。
的默认值--cpus
是0.000
,这意味着没有限制。
有关更多信息,请参阅 CFS 关于带宽限制的文档。
cpuset 约束
我们可以设置允许容器执行的 cpu。
例子:
$ docker run -it --cpuset-cpus="1,3" ubuntu:24.04 /bin/bash
这意味着容器中的进程可以在 cpu 1 和 cpu 3 上执行。
$ docker run -it --cpuset-cpus="0-2" ubuntu:24.04 /bin/bash
这意味着容器中的进程可以在 cpu 0、cpu 1 和 cpu 2 上执行。
我们可以设置 mems 以允许容器执行。仅有效 在 NUMA 系统上。
例子:
$ docker run -it --cpuset-mems="1,3" ubuntu:24.04 /bin/bash
此示例将容器中的进程限制为仅使用 内存节点 1 和 3。
$ docker run -it --cpuset-mems="0-2" ubuntu:24.04 /bin/bash
此示例将容器中的进程限制为仅使用 内存节点 0、1 和 2。
CPU 配额约束
这--cpu-quota
标志限制容器的 CPU 使用率。默认值 0
允许容器占用 100% 的 CPU 资源(1 个 CPU)。CFS(完全公平
Scheduler) 处理执行流程的资源分配,并且是默认的
内核使用的 Linux Scheduler。将此值设置为 50000 以限制容器
到 CPU 资源的 50%。对于多个 CPU,请调整--cpu-quota
根据需要。
有关更多信息,请参阅 CFS 关于带宽限制的文档。
块 IO 带宽 (Blkio) 约束
默认情况下,所有容器获得相同比例的块 IO 带宽
(blkio)。此比例为 500。要修改此比例,请将
容器的 BLKIO 权重相对于所有其他正在运行的
使用--blkio-weight
旗。
注意
blkio 权重设置仅适用于直接 IO。缓冲 IO 不是 目前支持。
这--blkio-weight
flag 可以将权重设置为介于 10 到 1000 之间的值。
例如,下面的命令会创建两个具有不同 blkio 的容器
重量:
$ docker run -it --name c1 --blkio-weight 300 ubuntu:24.04 /bin/bash
$ docker run -it --name c2 --blkio-weight 600 ubuntu:24.04 /bin/bash
如果您同时在两个容器中执行块 IO,例如:
$ time dd if=/mnt/zerofile of=test.out bs=1M count=1024 oflag=direct
你会发现 time 的比例和 blkio 的比例是一样的 两个容器的 weight。
这--blkio-weight-device="DEVICE_NAME:WEIGHT"
flag 设置特定的设备权重。
这DEVICE_NAME:WEIGHT
是一个字符串,其中包含以冒号分隔的设备名称和权重。
例如,要将/dev/sda
设备重量设置为200
:
$ docker run -it \
--blkio-weight-device "/dev/sda:200" \
ubuntu
如果同时指定--blkio-weight
和--blkio-weight-device
Docker
使用--blkio-weight
作为默认权重,并使用--blkio-weight-device
在特定设备上使用新值覆盖此默认值。
以下示例使用默认权重300
并覆盖此默认值
上/dev/sda
将该权重设置为200
:
$ docker run -it \
--blkio-weight 300 \
--blkio-weight-device "/dev/sda:200" \
ubuntu
这--device-read-bps
flag 限制设备的读取速率 (字节/秒)。
例如,此命令创建一个容器并将读取速率限制为1mb
每秒从/dev/sda
:
$ docker run -it --device-read-bps /dev/sda:1mb ubuntu
这--device-write-bps
flag 限制设备的写入速率 (每秒字节数)。
例如,此命令创建一个容器并将写入速率限制为1mb
per second for/dev/sda
:
$ docker run -it --device-write-bps /dev/sda:1mb ubuntu
这两个标志都采用<device-path>:<limit>[unit]
格式。两者都读取
写入速率必须为正整数。您可以在kb
(千字节)、mb
(兆字节) 或gb
(千兆字节)。
这--device-read-iops
flag 限制设备的读取速率(每秒 IO)。
例如,此命令创建一个容器并将读取速率限制为1000
每秒 IO 从/dev/sda
:
$ docker run -it --device-read-iops /dev/sda:1000 ubuntu
这--device-write-iops
标志限制对设备的写入速率(每秒 IO)。
例如,此命令创建一个容器并将写入速率限制为1000
IO 每秒设置为/dev/sda
:
$ docker run -it --device-write-iops /dev/sda:1000 ubuntu
这两个标志都采用<device-path>:<limit>
格式。读取和
写入速率必须为正整数。
其他组
--group-add: Add additional groups to run as
默认情况下,docker 容器进程在运行时会显示 up 的 UP 指定用户。如果想向该组列表添加更多内容,那么 可以使用这个标志:
$ docker run --rm --group-add audio --group-add nogroup --group-add 777 busybox id
uid=0(root) gid=0(root) groups=10(wheel),29(audio),99(nogroup),777
运行时权限和 Linux 功能
选择 | 描述 |
---|---|
--cap-add | 添加 Linux 功能 |
--cap-drop | 丢弃 Linux 功能 |
--privileged | 为此容器授予扩展权限 |
--device=[] | 允许您在容器内运行设备,而无需--privileged 旗。 |
默认情况下,Docker 容器是 “无特权” 的,并且不能,因为 示例,在 Docker 容器中运行 Docker 守护程序。这是因为 默认情况下,不允许容器访问任何设备,但 “privileged” 容器被授予对所有设备的访问权限(请参阅 cgroups 设备上的文档)。
这--privileged
flag 为容器提供所有功能。当运算符
执行docker run --privileged
,Docker 允许访问
主机,并重新配置 AppArmor 或 SELinux 以允许容器
几乎所有对主机的访问权都与在外部运行的进程相同
containers 的请谨慎使用此标志。
有关--privileged
标志,请参阅docker run
参考.
如果要限制对特定设备或可以使用
这--device
旗。它允许您指定一个或多个设备
将在容器内访问。
$ docker run --device=/dev/snd:/dev/snd ...
默认情况下,容器将能够read
,write
和mknod
这些设备。
这可以使用第三个:rwm
选项集--device
旗:
$ docker run --device=/dev/sda:/dev/xvdc --rm -it ubuntu fdisk /dev/xvdc
Command (m for help): q
$ docker run --device=/dev/sda:/dev/xvdc:r --rm -it ubuntu fdisk /dev/xvdc
You will not be able to write the partition table.
Command (m for help): q
$ docker run --device=/dev/sda:/dev/xvdc:w --rm -it ubuntu fdisk /dev/xvdc
crash....
$ docker run --device=/dev/sda:/dev/xvdc:m --rm -it ubuntu fdisk /dev/xvdc
fdisk: unable to open /dev/xvdc: Operation not permitted
除了--privileged
,作员可以对
功能--cap-add
和--cap-drop
.默认情况下,Docker 有一个默认的
保留的功能列表。下表列出了 Linux 功能
默认情况下允许且可以删除的选项。
功能键 | 能力描述 |
---|---|
AUDIT_WRITE | 将记录写入内核审计日志。 |
CHOWN 先生 | 对文件的 UID 和 GID 进行任意的修改(参见 chown(2))。 |
DAC_OVERRIDE | 绕过文件读取、写入和执行权限检查。 |
FOWNER | 对通常需要进程的文件系统 UID 与文件的 UID 匹配的作进行权限检查。 |
FSETID | 修改文件时,不要清除 set-user-ID 和 set-group-ID 权限位。 |
杀 | 绕过发送信号的权限检查。 |
猴子 | 使用 mknod(2) 创建特殊文件。 |
NET_BIND_SERVICE | 将套接字绑定到 Internet 域特权端口(端口号小于 1024)。 |
NET_RAW | 使用 RAW 和 PACKET 套接字。 |
SETFCAP | 设置文件功能。 |
SETGID | 对进程 GID 和补充 GID 列表进行任意作。 |
赛特卡普 | 修改流程功能。 |
赛蒂德 | 对进程 UID 进行任意作。 |
SYS_CHROOT | 使用 chroot(2),更改根目录。 |
下表显示了默认情况下未授予但可以添加的功能。
功能键 | 能力描述 |
---|---|
AUDIT_CONTROL | 启用和禁用内核审计;更改审计过滤规则;检索审核状态和筛选规则。 |
AUDIT_READ | 允许通过多播 netlink 套接字读取审计日志。 |
BLOCK_SUSPEND | 允许 防止系统挂起。 |
BPF | 允许创建 BPF 映射、加载 BPF 类型格式 (BTF) 数据、检索 BPF 程序的 JIT 代码等。 |
CHECKPOINT_RESTORE | 允许检查点/还原相关作。在内核 5.9 中引入。 |
DAC_READ_SEARCH | 绕过文件读取权限检查和目录读取执行权限检查。 |
IPC_LOCK | 锁定内存 (mlock(2)、mlockall(2)、mmap(2)、shmctl(2))。 |
IPC_OWNER | 绕过对 System V IPC 对象作的权限检查。 |
租赁 | 在任意文件上建立租约(参见 fcntl(2))。 |
LINUX_IMMUTABLE | 设置 FS_APPEND_FL 和 FS_IMMUTABLE_FL i-node 标志。 |
MAC_ADMIN | 允许 MAC 配置或状态更改。为 Smack LSM 实现。 |
MAC_OVERRIDE | 覆盖强制访问控制 (MAC)。为 Smack Linux 安全模块 (LSM) 实现。 |
NET_ADMIN | 执行各种与网络相关的作。 |
NET_BROADCAST | 进行套接字广播,并侦听多播。 |
性能 | 允许使用 perf_events、i915_perf 和其他内核子系统进行系统性能和可观察性特权作 |
SYS_ADMIN | 执行一系列系统管理作。 |
SYS_BOOT | 使用 reboot(2) 和 kexec_load(2),重启并加载一个新内核以供以后执行。 |
SYS_MODULE | 加载和卸载内核模块。 |
SYS_NICE | 提高 process nice 值 (nice(2), setpriority(2)) 并更改任意进程的 nice 值。 |
SYS_PACCT | 使用 acct(2),打开或关闭进程记帐。 |
SYS_PTRACE | 使用 ptrace(2) 跟踪任意进程。 |
SYS_RAWIO | 执行 I/O 端口作(iopl(2) 和 ioperm(2))。 |
SYS_RESOURCE | 覆盖资源限制。 |
SYS_TIME | 设置系统时钟 (settimeofday(2), stime(2), adjtimex(2));设置实时(硬件)时钟。 |
SYS_TTY_CONFIG | 使用 vhangup(2);在虚拟终端上使用各种特权 ioctl(2)作。 |
系统日志 | 执行特权 syslog(2)作。 |
WAKE_ALARM | 触发将唤醒系统的内容。 |
更多参考信息可以在 capabilities(7) - Linux 手册页中找到。 和 Linux 内核源代码中。
两个标志都支持该值ALL
,因此允许容器使用所有功能
除了MKNOD
:
$ docker run --cap-add=ALL --cap-drop=MKNOD ...
这--cap-add
和--cap-drop
flags 接受使用
一个CAP_
前缀。因此,以下示例是等效的:
$ docker run --cap-add=SYS_ADMIN ...
$ docker run --cap-add=CAP_SYS_ADMIN ...
为了与网络堆栈交互,而不是使用--privileged
他们
应该使用--cap-add=NET_ADMIN
以修改网络接口。
$ docker run -it --rm ubuntu:24.04 ip link add dummy0 type dummy
RTNETLINK answers: Operation not permitted
$ docker run -it --rm --cap-add=NET_ADMIN ubuntu:24.04 ip link add dummy0 type dummy
要挂载基于 FUSE 的文件系统,您需要将两者组合在一起--cap-add
和--device
:
$ docker run --rm -it --cap-add SYS_ADMIN sshfs sshfs sven@10.10.10.20:/home/sven /mnt
fuse: failed to open /dev/fuse: Operation not permitted
$ docker run --rm -it --device /dev/fuse sshfs sshfs sven@10.10.10.20:/home/sven /mnt
fusermount: mount failed: Operation not permitted
$ docker run --rm -it --cap-add SYS_ADMIN --device /dev/fuse sshfs
# sshfs sven@10.10.10.20:/home/sven /mnt
The authenticity of host '10.10.10.20 (10.10.10.20)' can't be established.
ECDSA key fingerprint is 25:34:85:75:25:b0:17:46:05:19:04:93:b5:dd:5f:c6.
Are you sure you want to continue connecting (yes/no)? yes
sven@10.10.10.20's password:
root@30aa0cfaf1b5:/# ls -la /mnt/src/docker
total 1516
drwxrwxr-x 1 1000 1000 4096 Dec 4 06:08 .
drwxrwxr-x 1 1000 1000 4096 Dec 4 11:46 ..
-rw-rw-r-- 1 1000 1000 16 Oct 8 00:09 .dockerignore
-rwxrwxr-x 1 1000 1000 464 Oct 8 00:09 .drone.yml
drwxrwxr-x 1 1000 1000 4096 Dec 4 06:11 .git
-rw-rw-r-- 1 1000 1000 461 Dec 4 06:08 .gitignore
....
默认的 seccomp 配置文件将调整为所选功能,以允许 使用功能允许的设施,因此您不必调整此设置。
覆盖镜像默认值
当您从 Dockerfile 构建镜像时,
或者在提交时,您可以设置一些默认参数,这些参数采用
效果。运行镜像时,您可以
使用docker run
命令。
默认命令和选项
的命令语法docker run
支持选择性地指定命令和
参数,表示为[COMMAND]
和[ARG...]
在以下概要示例中:
$ docker run [OPTIONS] IMAGE[:TAG|@DIGEST] [COMMAND] [ARG...]
此命令是可选的,因为无论谁创建了IMAGE
可能已经
提供了默认的COMMAND
、使用 DockerfileCMD
指令。当您
运行容器,则可以覆盖该CMD
指令,只需指定
新增功能COMMAND
.
如果镜像还指定了ENTRYPOINT
然后CMD
或COMMAND
作为参数附加到ENTRYPOINT
.
默认入口点
--entrypoint="": Overwrite the default entrypoint set by the image
入口点是指在运行
容器。容器的入口点是使用 Dockerfile 定义的ENTRYPOINT
指令。这类似于指定默认命令,因为
它指定了,但区别在于您需要将显式标志传递给
覆盖 EntryPoint,而您可以使用
位置参数。这定义了容器的默认行为,其思路是
当您设置入口点时,您可以像运行容器一样运行容器
binary,并带有默认选项,并且你可以将更多选项作为
命令。但在某些情况下,您可能希望在内部运行其他内容
容器。这是在运行时覆盖默认入口点的时候
在 Handy 中,使用--entrypoint
flag 的docker run
命令。
这--entrypoint
flag 需要一个字符串值,表示名称或路径
的Binaries。以下内容
示例演示如何在已设置的容器中运行 Bash shell
以自动运行其他一些Binaries(如/usr/bin/redis-server
):
$ docker run -it --entrypoint /bin/bash example/redis
以下示例演示如何将其他参数传递给自定义 entryPoint 中使用 positional 命令参数:
$ docker run -it --entrypoint /bin/bash example/redis -c ls -l
$ docker run -it --entrypoint /usr/bin/redis-cli example/redis --help
您可以通过传递空字符串来重置容器入口点,例如:
$ docker run -it --entrypoint="" mysql bash
注意
通过
--entrypoint
清除镜像上设置的任何默认命令。那 is、anyCMD
指令。
暴露的端口
默认情况下,当您运行容器时,不会公开容器的任何端口 添加到主机。这意味着您将无法访问任何 容器可能正在侦听。若要使容器的端口可从 主机,您需要发布端口。
您可以使用-P
或-p
标志来公开其端口:
这
-P
(或--publish-all
) 标志将所有公开的端口发布到 主机。Docker 将每个公开的端口绑定到主机上的随机端口。这
-P
flag 仅发布显式标记为 公开的,或者使用 DockerfileEXPOSE
指令或--expose
flag 的docker run
命令。这
-p
(或--publish
) 标志允许您显式映射单个端口或范围 容器中的端口数。
容器内部的端口号(服务监听的位置)不需要
要匹配容器外部发布的端口号(其中
客户端连接)。例如,在容器内部,HTTP 服务可能是
侦听端口 80。在运行时,端口可能会绑定到主机上的 42800。
要查找主机端口和公开端口之间的映射,请使用docker port
命令。
环境变量
Docker 在创建 Linux 时会自动设置一些环境变量 容器。Docker 在创建 Windows 时不设置任何环境变量 容器。
为 Linux 容器设置了以下环境变量:
变量 | 价值 |
---|---|
HOME | 根据USER |
HOSTNAME | 与容器关联的主机名 |
PATH | 包括常用目录,例如/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin |
TERM | xterm 如果为容器分配了伪 TTY |
此外,您可以使用
一个或多个-e
标志。您甚至可以覆盖上述变量,或者
使用 Dockerfile 定义的变量ENV
说明。
如果在未指定值的情况下命名环境变量,则当前的 值将传播到容器的 环境:
$ export today=Wednesday
$ docker run -e "deep=purple" -e today --rm alpine env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=d2219b854598
deep=purple
today=Wednesday
HOME=/root
PS C:\> docker run --rm -e "foo=bar" microsoft/nanoserver cmd /s /c set
ALLUSERSPROFILE=C:\ProgramData
APPDATA=C:\Users\ContainerAdministrator\AppData\Roaming
CommonProgramFiles=C:\Program Files\Common Files
CommonProgramFiles(x86)=C:\Program Files (x86)\Common Files
CommonProgramW6432=C:\Program Files\Common Files
COMPUTERNAME=C2FAEFCC8253
ComSpec=C:\Windows\system32\cmd.exe
foo=bar
LOCALAPPDATA=C:\Users\ContainerAdministrator\AppData\Local
NUMBER_OF_PROCESSORS=8
OS=Windows_NT
Path=C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Users\ContainerAdministrator\AppData\Local\Microsoft\WindowsApps
PATHEXT=.COM;.EXE;.BAT;.CMD
PROCESSOR_ARCHITECTURE=AMD64
PROCESSOR_IDENTIFIER=Intel64 Family 6 Model 62 Stepping 4, GenuineIntel
PROCESSOR_LEVEL=6
PROCESSOR_REVISION=3e04
ProgramData=C:\ProgramData
ProgramFiles=C:\Program Files
ProgramFiles(x86)=C:\Program Files (x86)
ProgramW6432=C:\Program Files
PROMPT=$P$G
PUBLIC=C:\Users\Public
SystemDrive=C:
SystemRoot=C:\Windows
TEMP=C:\Users\ContainerAdministrator\AppData\Local\Temp
TMP=C:\Users\ContainerAdministrator\AppData\Local\Temp
USERDOMAIN=User Manager
USERNAME=ContainerAdministrator
USERPROFILE=C:\Users\ContainerAdministrator
windir=C:\Windows
运行状况检查
以下docker run
命令允许您控制参数
对于容器运行状况检查:
选择 | 描述 |
---|---|
--health-cmd | 运行以检查运行状况的命令 |
--health-interval | 运行检查之间的时间 |
--health-retries | 报告运行状况不佳所需的连续失败 |
--health-timeout | 允许运行一项检查的最长时间 |
--health-start-period | 容器在开始运行状况重试倒计时之前要初始化的开始时段 |
--health-start-interval | 在开始期间运行检查之间的时间 |
--no-healthcheck | 禁用任何容器指定的HEALTHCHECK |
例:
$ docker run --name=test -d \
--health-cmd='stat /etc/passwd || exit 1' \
--health-interval=2s \
busybox sleep 1d
$ sleep 2; docker inspect --format='{{.State.Health.Status}}' test
healthy
$ docker exec test rm /etc/passwd
$ sleep 2; docker inspect --format='{{json .State.Health}}' test
{
"Status": "unhealthy",
"FailingStreak": 3,
"Log": [
{
"Start": "2016-05-25T17:22:04.635478668Z",
"End": "2016-05-25T17:22:04.7272552Z",
"ExitCode": 0,
"Output": " File: /etc/passwd\n Size: 334 \tBlocks: 8 IO Block: 4096 regular file\nDevice: 32h/50d\tInode: 12 Links: 1\nAccess: (0664/-rw-rw-r--) Uid: ( 0/ root) Gid: ( 0/ root)\nAccess: 2015-12-05 22:05:32.000000000\nModify: 2015..."
},
{
"Start": "2016-05-25T17:22:06.732900633Z",
"End": "2016-05-25T17:22:06.822168935Z",
"ExitCode": 0,
"Output": " File: /etc/passwd\n Size: 334 \tBlocks: 8 IO Block: 4096 regular file\nDevice: 32h/50d\tInode: 12 Links: 1\nAccess: (0664/-rw-rw-r--) Uid: ( 0/ root) Gid: ( 0/ root)\nAccess: 2015-12-05 22:05:32.000000000\nModify: 2015..."
},
{
"Start": "2016-05-25T17:22:08.823956535Z",
"End": "2016-05-25T17:22:08.897359124Z",
"ExitCode": 1,
"Output": "stat: can't stat '/etc/passwd': No such file or directory\n"
},
{
"Start": "2016-05-25T17:22:10.898802931Z",
"End": "2016-05-25T17:22:10.969631866Z",
"ExitCode": 1,
"Output": "stat: can't stat '/etc/passwd': No such file or directory\n"
},
{
"Start": "2016-05-25T17:22:12.971033523Z",
"End": "2016-05-25T17:22:13.082015516Z",
"ExitCode": 1,
"Output": "stat: can't stat '/etc/passwd': No such file or directory\n"
}
]
}
运行状况也会显示在docker ps
输出。
用户
容器中的默认用户为root
(uid = 0) 的 URL 中。您可以设置默认值
user 使用 Dockerfile 运行第一个进程USER
指令。什么时候
启动容器时,您可以覆盖USER
指令,方法是将-u
选择。
-u="", --user="": Sets the username or UID used and optionally the groupname or GID for the specified command.
以下示例均有效:
--user=[ user | user:group | uid | uid:gid | user:gid | uid:group ]
注意
如果您传递数字用户 ID,则它必须在 0-2147483647 的范围内。如果 您传递用户名,则用户必须存在于容器中。
工作目录
在容器中运行Binaries的默认工作目录是
根目录 ()。镜像的默认工作目录是使用
Dockerfile/
WORKDIR
命令。您可以覆盖默认的工作
目录下,使用-w
(或--workdir
) 标志docker run
命令:
$ docker run --rm -w /my/workdir alpine pwd
/my/workdir
如果容器中尚不存在该目录,则会创建该目录。