docker container exec 的核心作用是在一个正在运行的容器中执行命令
使用方法:
docker container exec [OPTIONS] CONTAINER COMMAND [ARG...]
还有另外一种写法是
docker exec ...
本文将围绕 docker exec这种写法来进行讲解
最常用形式:
docker exec -it CONTAINER bash
docker exec -it CONTAINER sh
常用参数记忆:
-i 保持输入打开,适合交互或重定向输入
-t 分配伪终端,适合进入 Shell
-it 最常见,交互式进入容器
-d 后台执行命令
-e 临时设置环境变量
--env-file 从文件读取环境变量
-u 指定执行用户
-w 指定工作目录
--privileged 给本次 exec 命令更高权限
最重要的几个注意点:
docker exec只能用于运行中的容器- 进入容器常用
docker exec -it CONTAINER sh - 复杂命令要用
sh -c '...' - 脚本、管道、重定向场景通常不要加
-t docker exec中的路径是容器内部路径
基本作用
docker exec 用于在一个已经运行中的容器里执行命令
基本语法:
docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
例如:
docker exec my-nginx nginx -v
含义是:在名为 my-nginx 的运行中容器里执行 nginx -v
等价写法:
docker container exec my-nginx nginx -v
前提条件
docker exec 只能作用于正在运行的容器。
先查看运行中的容器:
docker ps
示例输出:
CONTAINER ID IMAGE COMMAND NAMES
abc123456789 nginx "/docker-entrypoint.…" my-nginx
然后可以使用容器名或容器 ID 执行命令:
docker exec my-nginx ls
docker exec abc123456789 ls
如果容器已经停止,docker exec 会失败
docker exec my-nginx ls
可能报错:
Error response from daemon: Container ... is not running
停止状态下应使用:
docker start my-nginx
然后再执行:
docker exec my-nginx ls
最常用:进入容器 Shell
进入 Bash
docker exec -it CONTAINER bash
例如:
docker exec -it my-app bash
其中:
-i:保持标准输入打开-t:分配一个伪终端bash:进入容器中的 Bash Shell
这是最常见的组合
进入 sh
有些精简镜像没有 bash,例如 Alpine、BusyBox以及部分 distroless 镜像
可以使用:
docker exec -it CONTAINER sh
例如:
docker exec -it alpine-container sh
执行单条命令
如果只需要执行单条命令,不需要进入 Shell,可以直接执行命令
docker exec CONTAINER COMMAND
例如查看目录:
docker exec my-nginx ls /usr/share/nginx/html
-i 和 -t 的区别
-i:保持 STDIN 打开
docker exec -i CONTAINER COMMAND
常用于需要从标准输入传递内容的场景。
例如导入 SQL:
docker exec -i mysql-container mysql -uroot -p123456 mydb < backup.sql
这里必须用 -i,否则标准输入可能无法传入容器。
-t:分配伪终端
docker exec -t CONTAINER COMMAND
用于需要终端交互体验的命令。
-it:交互式终端
最常用组合:
docker exec -it CONTAINER bash
适合进入容器进行交互式操作。
什么时候不要用 -t
如果使用管道、重定向、脚本自动化,通常不要加 -t
例如:
docker exec -i mysql-container mysql -uroot -p123456 mydb < backup.sql
不要写成:
docker exec -it mysql-container mysql -uroot -p123456 mydb < backup.sql
否则可能出现:
the input device is not a TTY
总结
- 交互式登录容器:用
-it - 管道/重定向输入:用
-i - 普通执行命令:通常不用
-i -t
后台执行命令:-d
-d 表示 detached mode,即后台执行
docker exec -d CONTAINER COMMAND
例如在容器中后台执行脚本:
docker exec -d my-app sh -c "python /app/task.py"
或者:
docker exec -d my-app sh -c "sleep 60 && echo done > /tmp/done.log"
注意:
docker exec -d不会把命令输出显示在当前终端- 如果需要查看结果,应将输出写入文件或通过容器日志查看
指定环境变量:-e
可以给本次执行的命令临时设置环境变量。
docker exec -e KEY=VALUE CONTAINER COMMAND
例如:
docker exec -e APP_ENV=debug my-app env
多个环境变量:
docker exec \
-e APP_ENV=debug \
-e LOG_LEVEL=trace \
my-app env
在 Shell 中使用:
docker exec -e NAME=huajibenji my-app sh -c 'echo $NAME'
注意这里建议使用单引号:
sh -c 'echo $NAME'
如果写成双引号:
sh -c "echo $NAME"
$NAME 可能会先被宿主机 Shell 展开,而不是在容器内展开。
使用环境变量文件:--env-file
可以从文件读取环境变量。
docker exec --env-file ./exec.env CONTAINER COMMAND
exec.env 示例:
APP_ENV=debug
LOG_LEVEL=debug
USERNAME=huajibenji
执行:
docker exec --env-file ./exec.env my-app env
注意:
--env-file中的变量只对本次docker exec命令生效- 不会永久修改容器环境变量
- 不会修改镜像或 Dockerfile
指定用户执行:-u
默认情况下,docker exec 使用容器的默认用户执行命令。
可以用 -u 指定用户:
docker exec -u USER CONTAINER COMMAND
例如使用 root:
docker exec -u root -it my-app bash
使用普通用户:
docker exec -u appuser -it my-app sh
也可以使用 UID:
docker exec -u 1000 my-app whoami
指定用户和组:
docker exec -u 1000:1000 my-app id
格式:
<name|uid>[:<group|gid>]
常见用途:
docker exec -u root my-app apt update
docker exec -u www-data my-app php artisan cache:clear
docker exec -u postgres postgres-container psql
注意:
- 指定的用户必须在容器内存在,或者使用 UID/GID
- 使用 root 执行命令要谨慎,可能会改变文件权限
指定工作目录:-w
-w 或 --workdir 用于指定命令在容器内的工作目录。
docker exec -w /path/in/container CONTAINER COMMAND
例如:
docker exec -w /app my-app pwd
输出:
/app
执行项目命令:
docker exec -w /app my-app npm run build
进入指定目录的 Shell:
docker exec -it -w /app my-app bash
等价于进入容器后执行:
cd /app
使用 Shell 执行复杂命令
如果要执行复杂命令,比如管道、重定向、变量展开、条件判断,则需要通过 Shell
错误示例:
docker exec my-app echo hello > /tmp/a.txt
这个 > 是在宿主机执行的,不是在容器内执行
正确写法:
docker exec my-app sh -c 'echo hello > /tmp/a.txt'
执行多条命令
docker exec my-app sh -c 'cd /app && npm install && npm run build'
或者:
docker exec my-app sh -c '
cd /app
npm install
npm run build
'
使用管道
docker exec my-app sh -c 'ps aux | grep nginx'
使用重定向
docker exec my-app sh -c 'echo "hello" > /tmp/hello.txt'
追加内容:
docker exec my-app sh -c 'echo "world" >> /tmp/hello.txt'
条件执行
docker exec my-app sh -c 'test -f /app/config.yml && echo exists || echo missing'
使用特权模式:--privileged
--privileged 会给本次 exec 执行的命令更高权限
docker exec --privileged CONTAINER COMMAND
例如:
docker exec --privileged my-container iptables -L
或:
docker exec --privileged -it my-container sh
注意:
--privileged只影响这次exec执行的进程- 不等于整个容器以 privileged 模式运行
- 安全风险较高,应谨慎使用
- 容器本身如果没有相关能力或挂载,某些操作仍可能失败
通常只有在排查网络、内核能力、设备访问等问题时才考虑使用
修改 detach 快捷键:--detach-keys
当使用交互式终端时,默认可以通过快捷键脱离容器终端
常见默认快捷键是:
Ctrl-p Ctrl-q
可以用 --detach-keys 自定义:
docker exec -it --detach-keys="ctrl-x" my-app bash
这样可以用 Ctrl-x 脱离当前 exec 会话
注意:
- 脱离不是停止容器
- 该操作只是退出当前终端连接
常见实际场景
进入正在运行的容器
docker exec -it my-app bash
如果没有 Bash:
docker exec -it my-app sh
查看容器内文件
docker exec my-app ls -lah /app
docker exec my-app cat /app/config.yml
查看容器内进程
docker exec my-app ps aux
查看端口监听
docker exec my-app netstat -tunlp
或者:
docker exec my-app ss -tunlp
有些精简镜像可能没有这些命令
测试容器内网络
docker exec my-app ping bing.com
docker exec my-app curl http://localhost:8080
docker exec my-app wget -qO- http://localhost:8080
注意:
localhost指的是容器内部自身- 不是宿主机
- 不是其他容器
在容器内执行项目命令
Node.js:
docker exec -w /app my-node npm install
docker exec -w /app my-node npm run build
Python:
docker exec -w /app my-python python manage.py migrate
PHP Laravel:
docker exec -w /var/www/html my-php php artisan migrate
Java:
docker exec my-java java -version
执行数据库命令
MySQL:
docker exec -it mysql-container mysql -uroot -p
直接执行 SQL:
docker exec mysql-container mysql -uroot -p123456 -e "SHOW DATABASES;"
导入 SQL:
docker exec -i mysql-container mysql -uroot -p123456 mydb < backup.sql
导出 SQL:
docker exec mysql-container mysqldump -uroot -p123456 mydb > backup.sql
PostgreSQL:
docker exec -it postgres-container psql -U postgres
执行 SQL:
docker exec postgres-container psql -U postgres -c '\l'
Redis:
docker exec -it redis-container redis-cli
执行 Redis 命令:
docker exec redis-container redis-cli ping
查看容器内环境变量
docker exec my-app env
查看某个变量:
docker exec my-app sh -c 'echo $PATH'
在容器中创建文件
docker exec my-app sh -c 'echo hello > /tmp/hello.txt'
追加内容:
docker exec my-app sh -c 'echo world >> /tmp/hello.txt'
查看:
docker exec my-app cat /tmp/hello.txt
docker exec 与 docker run 的区别
docker exec
在已有运行中容器里执行命令:
docker exec -it my-app bash
特点:
- 容器必须已经运行
- 不会创建新容器
- 适合调试、排查、临时执行命令
docker run
基于镜像创建并启动新容器:
docker run -it ubuntu bash
特点:
- 会创建新容器
- 可以从镜像启动
- 适合启动服务或创建临时容器
对比:
docker exec:进入或操作一个已经存在且运行中的容器
docker run :基于镜像创建一个新的容器
docker exec 与 docker attach 的区别
docker exec
启动一个新的进程:
docker exec -it my-app bash
特点:
- 在容器内新开一个命令进程
- 常用于进入容器调试
- 退出 Shell 不会影响容器主进程
docker attach
连接到容器的主进程:
docker attach my-app
特点:
- 附加到容器当前主进程的标准输入输出
- 如果退出方式不当,可能影响容器主进程
- 不如
docker exec常用于调试
日常进入容器优先使用:
docker exec -it CONTAINER bash
而不是:
docker attach CONTAINER
常见错误与解决方法
容器没有运行
错误:
Error response from daemon: Container ... is not running
解决:
docker ps -a
docker start CONTAINER
docker exec -it CONTAINER sh
容器里没有 bash
错误:
exec: "bash": executable file not found in $PATH
解决:
docker exec -it CONTAINER sh
命令不存在
错误:
exec: "curl": executable file not found in $PATH
说明容器内没有安装 curl
解决方式:
Debian/Ubuntu:
docker exec -u root CONTAINER sh -c 'apt update && apt install -y curl'
Alpine:
docker exec -u root CONTAINER sh -c 'apk add --no-cache curl'
输入设备不是 TTY
错误:
the input device is not a TTY
常见原因是在脚本、管道或重定向场景中使用了 -t
错误示例:
docker exec -it mysql-container mysql -uroot -p123456 mydb < backup.sql
正确示例:
docker exec -i mysql-container mysql -uroot -p123456 mydb < backup.sql
权限不足
错误:
Permission denied
解决方式之一:
docker exec -u root -it CONTAINER sh
或:
docker exec -u root CONTAINER chmod +x /path/script.sh
注意不要随意改变生产容器中的文件权限
变量没有正确展开
错误示例:
docker exec my-app sh -c "echo $HOME"
这里 $HOME 可能被宿主机 Shell 先展开
更推荐:
docker exec my-app sh -c 'echo $HOME'
常用命令
进入容器:
docker exec -it CONTAINER bash
docker exec -it CONTAINER sh
以 root 进入:
docker exec -u root -it CONTAINER bash
指定目录进入:
docker exec -it -w /app CONTAINER bash
执行单条命令:
docker exec CONTAINER ls -lah /app
执行复杂命令:
docker exec CONTAINER sh -c 'cd /app && npm run build'
后台执行:
docker exec -d CONTAINER sh -c 'long-running-command'
设置临时环境变量:
docker exec -e APP_ENV=debug CONTAINER env
从文件读取环境变量:
docker exec --env-file .env CONTAINER env
导入 MySQL 数据:
docker exec -i mysql-container mysql -uroot -p123456 mydb < backup.sql
导出 MySQL 数据:
docker exec mysql-container mysqldump -uroot -p123456 mydb > backup.sql
实践
日常进入容器优先使用
docker exec -it CONTAINER sh
如果确定有 Bash:
docker exec -it CONTAINER bash
自动化脚本中尽量不用 -t
脚本中推荐:
docker exec CONTAINER command
或者需要输入时:
docker exec -i CONTAINER command
不推荐:
docker exec -it CONTAINER command
复杂命令使用 sh -c
推荐:
docker exec CONTAINER sh -c 'cd /app && command1 && command2'
注意容器内外路径区别
宿主机路径:
/home/user/project
容器内路径:
/app
docker exec 后面的路径都是容器内部路径。
例如:
docker exec my-app ls /app
这里 /app 是容器内的 /app
参考说明
https://docs.docker.com/reference/cli/docker/container/exec/
本文使用了生成式人工智能来协助整理