Docker run参考手册
Docker 在隔离的容器中运行进程。容器是在主机上运行的进程。主机可以是本地的或远程的。当操作符执行时docker run
,运行的容器进程是隔离的,因为它有自己的文件系统、自己的网络以及与主机分离的自己的隔离进程树。
此页面详细介绍了如何使用 docker run
命令在运行时定义容器的资源。
一般形式
基本 docker run
命令采用以下形式:
$ docker run [OPTIONS] IMAGE[:TAG|@DIGEST] [COMMAND] [ARG...]
docker run
命令必须指定制作容器的镜像。镜像开发人员可以定义以下与镜像相关的默认值:
- 分离或前台运行
- 集装箱标识
- 网络设置
- CPU 和内存的运行时限制
随着docker run [OPTIONS]
操作者可以添加或覆盖由开发者设置的镜像的默认值。此外,使用者可以覆盖几乎所有由 Docker 运行时本身设置的默认值。使用者能够覆盖镜像和 Docker 运行时默认值的能力是run
比任何其他docker
命令都有更多选项的原因 。
要了解如何解释 的类型 [OPTIONS]
,请参阅 选项类型。
笔记
根据您的 Docker 系统配置,您可能需要在docker run
命令前加上sudo
.
为了避免使用sudo
该docker
命令,您的系统管理员可以创建一个名为的 Unix
组docker
并向其中添加用户。有关此配置的更多信息,请参阅适用于您的操作系统的 Docker 安装文档。
使用者专用配置
只有使用者(执行者 docker run
)可以设置以下选项。
分离与前台
启动 Docker 容器时,首先要决定是要在后台以“分离”模式还是默认前台模式运行容器:
-d=false: Detached mode: Run container in the background, print new container id
分离(-d)
要以分离模式启动容器,您可以使用 -d=true
或只是 -d
选项。按照设计,当用于运行容器的根进程退出时,容器以分离模式启动,除非您还指定了 --rm
选项。如果使用 -d
和 --rm
,则在容器退出或守护程序退出时(以先发生者为准)将移除容器。
不要将 service x start
命令传递给分离的容器。例如,此命令尝试启动 nginx
服务。
$ docker run -d -p 80:80 my_image service nginx start
这成功地启动了容器内的 nginx
服务。然而,它在分离容器中失败了,根进程 (service nginx start
) 返回,分离容器按设计停止。结果,该 nginx
服务已启动但无法使用。相反,要启动诸如 nginx
Web 服务器之类的进程,请执行以下操作:
$ 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
。您可以指定要连接到三个标准流 ( STDIN
, STDOUT
, STDERR
) 中的哪一个,如下所示:
$ 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
笔记
在容器内作为 PID 1 运行的进程被 Linux
特殊对待:它忽略任何具有默认操作的信号。因此,进程将不会终止,SIGINT或者SIGTERM除非它被编码为这样做。
容器标识
Name(–name)
使用者可以通过三种方式标识容器:
标识符类型 | 示例值 |
---|---|
UUID 长标识符 | “f78375b1c487e03c9438c729345e54db9d20cfa2ac1fc3494b6eb60872e74778” |
UUID 短标识符 | “f78375b1c487” |
名称 | “evil_ptolemy” |
UUID 标识符来自 Docker 守护进程。如果您没有使用该 --name
选项分配容器名称,那么守护程序会为您生成一个随机字符串名称。定义一个 name
可以很方便地为容器制定一个有意义的名称。如果指定了一个 name
,则可以在 Docker 网络中引用容器时使用它。这适用于后台和前台 Docker 容器。
笔记
默认桥接网络上的容器必须通过名称进行连接通信。
PID equivalent
最后,为了帮助实现自动化,您可以让 Docker 将容器 ID 写入您选择的文件中。这类似于某些程序可能会将其进程 ID 写入文件的方式(您已将它们视为 PID 文件):
--cidfile="": Write the container ID to the file
Image[:tag]
虽然严格来说这不是一种识别容器的方法,但您可以通过在命令中添加 image[:tag]
来指定要用于运行容器的镜像版本。例如,docker run ubuntu:14.04
。
Image[@digest]
使用 v2 或更高版本镜像格式的图像具有摘要类型的标识符。只要用于生成镜像的输入不变,摘要值就是可预测和可参考的。
以下示例从镜像 alpine
使用摘要 sha256:9cacb71397b640eca97488cf08582ae4e4068513101088e9f96c9814bfda95e0
运行了容器:
$ docker run alpine@sha256:9cacb71397b640eca97488cf08582ae4e4068513101088e9f96c9814bfda95e0 date
PID settings(–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 settings (–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
和 --domainname
在 hostUTS 模式下无效。
如果您希望容器的主机名随着主机的主机名更改而更改,您可能希望与主机共享 UTS 命名空间。更高级的用例是从容器更改主机的主机名。
IPC settings(–ipc)
--ipc="MODE" : Set the IPC mode for the container
接受以下值:
价值 | 描述 |
---|---|
“” | 默认使用守护进程 |
“none” | 自己的私有 IPC 命名空间,没有挂载 /dev/shm。 |
“private” | 拥有私有 IPC 命名空间。 |
“shareable” | 拥有私有 IPC 命名空间,可以与其他容器共享。 |
“container:<name-or-ID>” | 加入另一个(“可共享”)容器的 IPC 命名空间。 |
“host” | 使用主机系统的 IPC 命名空间。 |
如果未指定,则默认使用守护程序,可以是 "private"
或 "shareable"
,具体取决于守护程序版本和配置。
IPC (POSIX/SysV IPC) 命名空间提供命名共享内存段、信号量和消息队列的分离。
共享内存段用于以内存速度加速进程间通信,而不是通过管道或网络堆栈。共享内存通常被用于科学计算和金融服务行业的数据库和定制(通常是 C/OpenMPI、C++/using boost libraries)高性能应用程序使用。如果这些类型的应用程序被分成多个容器,您可能需要共享容器的 IPC 机制,使用 "shareable"
主(例如"donor")容器和"container:"其他容器的模式。
Network settings
--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 STDIN 和 STDOUT 的操作了。
发布端口和链接到其他容器仅适用于默认值(网桥)。链接功能是遗留功能。与链接相比,您应该始终更喜欢使用 Docker 网络驱动程序。
默认情况下,您的容器将使用与主机相同的 DNS 服务器,但您可以使用 --dns
覆盖配置.
默认情况下,MAC 地址是使用分配给容器的 IP 地址生成的。您可以通过 --mac-address
参数(格式:12:34:56:78:9a:bc)提供 MAC 地址来显式设置容器的 MAC 地址。请注意,Docker 不会检查手动指定的 MAC 地址是否唯一。
支持的网络:
网络 | 描述 |
---|---|
none | 容器中没有网络。 |
bridge(默认) | 通过 veth 接口将容器连接到网桥。 |
host | 在容器内使用主机的网络堆栈。 |
container:<name/id> | 使用另一个容器的网络堆栈,通过其名称或id指定。 |
NETWORK | 将容器连接到用户创建的网络(使用 docker network create 命令) |
Network: none
使用网络 none
的容器将无法访问任何外部路由。容器仍将 loopback
在容器中启用,但它没有任何通往外部流量的路由。
Network: bridge
将网络设置为 bridge
容器将使用 docker 的默认网络设置。在主机上设置了一个网桥,通常命名为 docker0
,并且容器将创建一对 veth
接口。veth
的一端将保留在连接到网桥的主机上,另一端将放置在除 loopback
接口之外的容器命名空间内。将为网桥网络上的容器分配 IP 地址,流量将通过此网桥路由到容器。
默认情况下,容器可以通过其 IP 地址进行通信。如果要按名称进行通信,必须先将它们链接起来。
Network: host
将网络设置为 host
容器将共享主机的网络栈,并且来自主机的所有接口都可用于容器。容器的主机名将与主机系统上的主机名匹配。请注意,--mac-address
在 host
网络模式下无效。即使在 host
网络模式下,容器也默认有自己的 UTS 命名空间。 --hostname
和 --domainname
允许在 host
的网络模式使用,仅改变容器内的主机名和域名。类似 --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,因此被认为是不安全的。
Network: container
将网络设置为 container
, 容器将共享另一个容器的网络堆栈。另一个容器的名称必须以 --network container:<name|id>
的格式提供. 注意 --add-host
--hostname
--dns
--dns-search
--dns-option
和 --mac-address
在 container
网络模式下无效,--publish
--publish-all
--expose
无效,在 container
网络模式下也无效。
示例:运行绑定 localhost
的 Redis 容器,然后运行 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
如果容器连接到默认桥接网络并与其他容器连接,则容器的 /etc/hosts
文件将使用链接容器的名称进行更新。
笔记
由于 Docker 可能会实时更新容器的
/etc/hosts
文件,因此可能会出现容器内的进程最终读取空/etc/hosts
文件或不完整文件的情况。在大多数情况下,再次重试读取应该可以解决问题。
重启策略 (–restart)
使用 --restart
您可以指定一个重启策略,用于在退出时应该或不应该重新启动容器。
当重新启动策略在容器上进行时,它将被显示为 Up
或 Restarting
在使用 docker ps
命令时。使用 docker events
可以查看生效的重启策略。
Docker 支持以下重启策略:
策略 | 结果 |
---|---|
no | 退出时不要自动重启容器。这是默认设置。 |
on-failure[:max-retries] | 仅当容器以非零退出状态退出时才重新启动。(可选)限制 Docker 守护程序尝试重新启动的次数。 |
always | 无论退出状态如何,始终重新启动容器。当您指定 always 时,Docker 守护进程将尝试无限期地重新启动容器。无论容器的当前状态如何,容器也将始终在守护程序启动时启动。 |
unless-stopped | 无论退出状态如何,始终重启容器,包括守护进程启动时,除非容器在 Docker 守护进程停止之前进入停止状态。 |
每次重新启动之前都会使用一个不断增加的延迟(前一个延迟的两倍,从 100 毫秒开始),以防止服务器泛滥。这意味着守护程序将等待 100 毫秒,然后是 200 毫秒、400、800、1600 毫秒,依此类推,直到达到 on-failure
限制,或者您 docker stop
或 docker rm -f
容器时。
如果容器成功重启(容器启动并运行至少 10 秒),延迟将重置为其默认值 100 毫秒。
您可以指定 Docker 在使用 on-failure
策略时尝试重新启动容器的最大次数。默认情况下,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
使用 on-failure
重启策略 和最大重启次数 10 运行 redis
容器。如果容器以非零退出状态退出超过 10 次,Docker 将中止尝试重启容器。提供最大重启限制仅对 on-failure
策略有效 。
退出状态
退出代码 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将以相同的逻辑删除:如果原始卷指定了名称,则不会删除。