目录

docker run 参数完整说明(附实际运行结果)

docker run 是最常用、参数也最多的 Docker 命令。基本格式是:

docker run [参数] 镜像[:tag] [命令] [命令的参数]

镜像名称之后的部分会取代镜像默认的命令(CMD):

$ docker run --rm alpine:3.23 cat /etc/alpine-release
3.23.6

--rm 是给 Docker 的参数;cat /etc/alpine-release 则是在容器里运行的命令,它取代了 alpine 默认的 /bin/sh。

参数一定要写在镜像名称之前

写在镜像名称后面的东西,全部会被当成容器内的命令:

$ docker run alpine:3.23 --rm echo hi
docker: Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: exec: "--rm": executable file not found in $PATH

Run 'docker run --help' for more information

Docker 试图在容器里运行一个叫 --rm 的程序,当然找不到(executable file not found)。看到这种错误,先检查参数的位置。

运行模式

参数说明
-d, --detach在后台运行,输出容器 ID 后立即返回
-i, --interactive保持标准输入打开
-t, --tty配置一个虚拟终端
--rm容器结束后自动删除
--name指定容器名称,否则会随机生成(例如 dreamy_solomon)
docker run -it --rm ubuntu:26.04 bash      # 交互式进入,离开后自动删除
docker run -d --name cache redis:8-alpine  # 后台服务

-it 几乎总是一起使用,用来进入交互式的 shell。只用 -i 则可以把数据用管道送进容器:

$ echo "hello" | docker run -i --rm alpine:3.23 cat
hello

端口:-p

格式是 -p 主机端口:容器端口。下面三种写法实际对照:

$ docker run -d --name p1 -p 8080:80 nginx:1.30
27b89a4fae92dfe05bf051e11700033c7b9bb71f8747acc986d2a535cc1baa00

$ docker run -d --name p2 -p 127.0.0.1:8081:80 nginx:1.30
3327f3c1df4fa1e03fa3a120e5d889859fc0cb53d0aaf269826c81b25f4411c2

$ docker run -d --name p3 -P nginx:1.30
57c9a309c4758786361738b7b9a4231f404cb9bbab28f38cad39b4b6e996d9e0

$ docker port p1
80/tcp -> 0.0.0.0:8080
80/tcp -> [::]:8080

$ docker port p2
80/tcp -> 127.0.0.1:8081

$ docker port p3
80/tcp -> 0.0.0.0:32768
80/tcp -> [::]:32768
写法结果
-p 8080:80绑定所有网络接口(0.0.0.0 与 IPv6 的 [::]),其他电脑也能连
-p 127.0.0.1:8081:80只绑定本机,只有这台电脑自己能连
-P把镜像 EXPOSE 的端口对应到随机的主机端口(这次分到 32768)

docker port 容器名称 可以查看实际的对应。UDP 端口要写成 -p 5353:53/udp。

-p 8080:80 在云服务器上代表外部可以直接连到;而且 Docker 会自己改写防火墙规则,ufw 的设置可能挡不住。数据库等不该对外的服务,请绑定 127.0.0.1,或干脆不要用 -p,改用 自定义网络 让容器互连。

数据:-v 与 --mount

-v 主机路径:容器路径 把主机上的文件夹挂进容器(bind mount)。准备一个 site 文件夹,里面有一个 index.html:

$ ls site
index.html

$ docker run -d --name site -p 8080:80 -v "$(pwd)/site:/usr/share/nginx/html:ro" nginx:1.30
e91f46b91ff8f0f64d59d6605bfddea0ee5bca809de86d81cbd5051815e65dd1

$ curl -s http://localhost:8080 | head -n 3
<!doctype html>
<html><head><meta charset="utf-8"><title>My site</title>
<style>body{font-family:system-ui,sans-serif;max-width:640px;margin:60px auto;padding:0 16px;color:#1f2937}h1{color:#1d63ed}</style></head>

对应 Windows 的写法(点击标签切换):

docker run -d --name site -p 8080:80 -v "$(pwd)/site:/usr/share/nginx/html:ro" nginx:1.30
docker run -d --name site -p 8080:80 -v "${PWD}/site:/usr/share/nginx/html:ro" nginx:1.30
docker run -d --name site -p 8080:80 -v "%cd%/site:/usr/share/nginx/html:ro" nginx:1.30
nginx 显示 bind mount 进来的网页
nginx 显示的是主机上 site/index.html 的内容

结尾的 :ro 代表只读。容器里想写入这个文件夹会被拒绝:

$ docker exec site sh -c "echo test > /usr/share/nginx/html/x.txt"
sh: 1: cannot create /usr/share/nginx/html/x.txt: Read-only file system

另一种挂载方式是使用 Docker 管理的 Volume(-v 名称:容器路径),适合保存数据库等数据:

docker run -d -v pgdata:/var/lib/postgresql postgres:18

--mount 是写法较长但更明确的版本,两者的差异和使用时机请看 Volume 与 Bind Mount。

环境变量:-e 与 --env-file

$ docker run --rm -e GREETING=hello -e APP_ENV=dev alpine:3.23 env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=18f035817c43
GREETING=hello
APP_ENV=dev
HOME=/root

-e 变量名称(不写值)会沿用主机目前的同名环境变量:

$ APP_ENV=prod docker run --rm -e APP_ENV alpine:3.23 sh -c 'echo $APP_ENV'
prod

变量很多时改用 --env-file 文件,详见 环境变量与 .env 文件。

网络

在同一个自定义网络中的容器,可以用容器名称互相连接:

$ docker network create mynet
2ecd542737519b0b8919061077814e007a72e2d07973f0840608b1b5454c678e

$ docker run -d --name myweb --network mynet nginx:1.30
9a6ca3dca3a003e28b9870f3eec436cf7023a6872e8ddd4cee971d29f845583b

$ docker run --rm --network mynet alpine:3.23 ping -c 2 myweb
PING myweb (172.19.0.2): 56 data bytes
64 bytes from 172.19.0.2: seq=0 ttl=64 time=0.094 ms
64 bytes from 172.19.0.2: seq=1 ttl=64 time=0.064 ms

--- myweb ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.064/0.079/0.094 ms

$ docker run --rm alpine:3.23 ping -c 1 -W 2 myweb
ping: bad address 'myweb'
  • 第一个 ping 容器在 mynet 里,myweb 被 Docker 内置的 DNS 解析成 172.19.0.2。
  • 第二个没有加 --network,在默认网络里,找不到 myweb(bad address)。

容器名称避免取成 web、app 这类刚好是顶级域名(TLD)的单词。在没有加入同一网络时,这种名称会被外部 DNS 解析到奇怪的地址(例如 127.0.53.53),让调试更困惑。

docker run --network host nginx:1.30     # 直接使用主机网络(Linux)
docker run --network none alpine:3.23    # 完全没有网络

详见 网络与容器互连。

重启策略

docker run -d --restart unless-stopped nginx:1.30

可用值有 no、on-failure、always、unless-stopped,实际行为见 容器生命周期。

资源限制

$ docker run -d --name limited --memory 64m --cpus 0.5 nginx:1.30
2e65ce89f346cb7d9d57f1e6ad529d63ad53d1d914b6d3178dc3344a1d3325f0

$ docker stats --no-stream limited
CONTAINER ID   NAME      CPU %     MEM USAGE / LIMIT   MEM %     NET I/O       BLOCK I/O         PIDS
2e65ce89f346   limited   0.00%     3.922MiB / 64MiB    6.13%     736B / 126B   1.77MB / 8.19kB   2

MEM USAGE / LIMIT 显示 3.922MiB / 64MiB,内存上限生效了。nginx 空闲时只用了不到 4 MB。

参数说明
--memory, -m内存上限,例如 512m、2g;超过时进程会被终止(OOM,退出码 137)
--memory-swap内存 + swap 的总上限
--cpus可使用的 CPU 数量,可以是小数,0.5 代表半个
--pids-limit容器内最多的进程数

内存超过上限时的实际情况,见 查看日志与调试 中的 OOM 示例。

覆盖镜像的默认值

$ docker run --rm --entrypoint sh nginx:1.30 -c "nginx -v; whoami"
nginx version: nginx/1.30.5
root

$ docker run --rm -u 1000:1000 alpine:3.23 id
uid=1000 gid=1000 groups=1000

$ docker run --rm -w /tmp alpine:3.23 pwd
/tmp

$ docker run --rm -h myhost alpine:3.23 hostname
myhost
参数说明
--entrypoint覆盖 ENTRYPOINT,常用来进入原本会直接启动服务的镜像里看看
-u, --user以指定的用户(UID:GID)运行
-w, --workdir覆盖工作目录
-h, --hostname容器的主机名称

-u 常用来让容器生成的文件属于你自己,而不是 root:

docker run --rm -u "$(id -u):$(id -g)" -v "$(pwd):/work" -w /work node:24-alpine npm install

只读文件系统

$ docker run --rm --read-only alpine:3.23 touch /hello
touch: /hello: Read-only file system

--read-only 让整个容器的文件系统只读,就算程序被入侵也无法修改文件。需要写入的地方再用 --tmpfs /tmp 或 Volume 开放,见 安全最佳实践。

其他实用参数

参数说明
--init用小型 init 进程当 PID 1,正确转发信号(docker stop 不用等 10 秒,见 容器生命周期)
--platform指定平台,例如 linux/amd64
--add-host加一笔 hosts 记录,例如 --add-host host.docker.internal:host-gateway
--label加上标签,方便筛选
--pull always每次运行前都重新拉取镜像
--log-opt max-size=10m限制日志文件大小

更多参数速查

以下依 docker run --help(Docker 29)整理本章没有详细介绍、但实用的参数。完整清单请运行 docker run --help。

分类参数说明
安全--cap-add / --cap-drop增加或删除 Linux capabilities,实测见 安全最佳实践
安全--security-opt安全选项,例如 no-new-privileges、seccomp 设置
安全--privileged给容器所有权限,几乎关闭隔离,避免使用
安全--userns使用的 user namespace
健康检查--health-cmd健康检查命令,例如 --health-cmd "curl -f http://localhost/"
健康检查--health-interval / --health-timeout / --health-retries检查间隔、逾时、连续失败几次才算 unhealthy
健康检查--health-start-period / --health-start-interval启动期间的宽限时间与检查间隔
健康检查--no-healthcheck停用镜像中设置的 HEALTHCHECK
网络--network-alias在网络中多一个名称,见 docker network
网络--ip在自定义网络中指定固定 IP
网络--dns / --dns-search自定义 DNS 服务器与搜索域
网络--expose声明端口(不对应到主机),效果同 Dockerfile 的 EXPOSE
网络-P, --publish-all把所有声明的端口对应到随机的主机端口
停止--stop-signaldocker stop 送出的信号,默认 SIGTERM
停止--stop-timeoutdocker stop 等待的秒数,默认 10
资源--cpuset-cpus只使用指定的 CPU,例如 0,1 或 0-3
资源-c, --cpu-sharesCPU 相对权重(资源竞争时才有作用)
资源--memory-reservation内存软上限
资源--shm-size/dev/shm 的大小,PostgreSQL、浏览器等程序常需要调大
资源--ulimit例如 --ulimit nofile=65535:65535 调整打开文件数上限
资源--oom-kill-disable停用内存不足时的强制终止(要搭配 --memory)
设备--device把主机设备交给容器,例如 /dev/ttyUSB0
设备--gpus使用 GPU,例如 --gpus all(需要 NVIDIA Container Toolkit)
命名空间--pid host / --ipc / --uts共用主机或其他容器的命名空间,原理见 底层原理
系统--sysctl设置容器的内核参数,例如 net.core.somaxconn=1024
系统--umask容器中进程的 umask
挂载--volumes-from挂载另一个容器的所有 Volume
其他--cidfile把容器 ID 写进文件,方便脚本使用
其他--label-file从文件读取标签
其他--log-driver日志驱动程序,例如 json-file、local、syslog
其他-q, --quiet下载镜像时不显示进度
其他--use-api-socket把 Docker API socket 与登录凭证挂进容器(等同主机 root 权限,见 安全最佳实践)

常见组合示例

# 1. 一次性的工具容器:在目前文件夹运行命令
docker run --rm -v "$(pwd):/data" -w /data alpine:3.23 ls -la

# 2. 本机开发用数据库,只开放本机连接
docker run -d --name devdb --restart unless-stopped \
  -p 127.0.0.1:5432:5432 \
  -e POSTGRES_PASSWORD=dev \
  -v devdb:/var/lib/postgresql \
  postgres:18

# 3. 正式服务,限制资源与日志大小
docker run -d --name api --restart unless-stopped \
  --memory 1g --cpus 2 \
  --log-opt max-size=10m --log-opt max-file=3 \
  --env-file .env -p 3000:3000 \
  myorg/api:1.4.2
# 1. 一次性的工具容器:在目前文件夹运行命令
docker run --rm -v "${PWD}:/data" -w /data alpine:3.23 ls -la

# 2. 本机开发用数据库,只开放本机连接
docker run -d --name devdb --restart unless-stopped `
  -p 127.0.0.1:5432:5432 `
  -e POSTGRES_PASSWORD=dev `
  -v devdb:/var/lib/postgresql `
  postgres:18

# 3. 正式服务,限制资源与日志大小
docker run -d --name api --restart unless-stopped `
  --memory 1g --cpus 2 `
  --log-opt max-size=10m --log-opt max-file=3 `
  --env-file .env -p 3000:3000 `
  myorg/api:1.4.2
# 1. 一次性的工具容器:在目前文件夹运行命令
docker run --rm -v "%cd%:/data" -w /data alpine:3.23 ls -la

# 2. 本机开发用数据库,只开放本机连接
docker run -d --name devdb --restart unless-stopped ^
  -p 127.0.0.1:5432:5432 ^
  -e POSTGRES_PASSWORD=dev ^
  -v devdb:/var/lib/postgresql ^
  postgres:18

# 3. 正式服务,限制资源与日志大小
docker run -d --name api --restart unless-stopped ^
  --memory 1g --cpus 2 ^
  --log-opt max-size=10m --log-opt max-file=3 ^
  --env-file .env -p 3000:3000 ^
  myorg/api:1.4.2

参数一多,命令就很难维护。需要长期运行或多个容器一起运作时,建议改用 Docker Compose 把设置写进文件里。

重点回顾

  • 参数写在镜像名称之前,之后的内容是容器内要运行的命令。
  • -d、--rm、--name、-p、-v、-e 是最常用的组合。
  • --memory、--cpus、--pids-limit 限制资源。
  • --entrypoint、-u、-w 覆盖镜像的默认值。

动手练习

练习 1:写出一个命令:在后台运行 nginx:1.30-alpine,名称 site,只让本机的 8080 端口连得到,内存上限 128 MB,结束后不保留容器。

答案
docker run -d --rm --name site -p 127.0.0.1:8080:80 --memory 128m nginx:1.30-alpine

--rm 让容器停止后自动删除。

练习 2:postgres:18 镜像的 ENTRYPOINT 会启动数据库。怎么只进入它的 shell 看看,而不启动数据库?

答案
docker run --rm -it --entrypoint sh postgres:18

--entrypoint 覆盖镜像的 ENTRYPOINT。

常见问题

参数写在镜像名称后面为什么没有作用?

镜像名称之后的内容会被当成要在容器内运行的命令。docker run 的参数一定要写在镜像名称之前。

-p 8080:80 和 -p 127.0.0.1:8080:80 有什么不同?

前者绑定所有网络接口,其他电脑也能连;后者只绑定本机。数据库等不需要对外的服务,请用后者或完全不加 -p。

docker run 有多少个参数?

Docker 29 的 docker run --help 列出约 100 个参数。本章介绍最常用的,最后的「更多参数速查」整理了其他实用的参数。

更新于 2026年10月14日