目录
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

结尾的 :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-signal | docker stop 送出的信号,默认 SIGTERM |
| 停止 | --stop-timeout | docker stop 等待的秒数,默认 10 |
| 资源 | --cpuset-cpus | 只使用指定的 CPU,例如 0,1 或 0-3 |
| 资源 | -c, --cpu-shares | CPU 相对权重(资源竞争时才有作用) |
| 资源 | --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日