容器运行时的 -dit 选项
docker run 命令的选项
{.line-numbers} 1 2 3 4 --attach , -a Attach to STDIN, STDOUT or STDERR --detach , -d Run container in background and print container ID --interactive , -i Keep STDIN open even if not attached --tty , -t Allocate a pseudo-TTY
docker exec 命令
{.line-numbers} 1 2 3 4 5 -d, --detach Detached mode: run command in the background -i, --interactive Keep STDIN open even if not attached -t, --tty Allocate a pseudo-TTY 没有 -a --attach 选项
-a 可以多次指定 ,比如 -a stdin -a stdout
不要同时使用 -t 和 -a stderr,因为 pty 本身的限制。
Do not use the -t and -a stderr options together due to limitations in the pty implementation. All stderr in pty mode simply goes to stdout.
使用 bash:lastest 镜像,通过观察 /dev/fd/ 目录,查看容器控制台IO的打开关闭情况。
默认,dit组合是001,前台运行,无法输入,只能看到输出。 只有 -i 没有 -t,容器可以接受stdin的输入,也可以输出,但是通过管道,不是伪终端,是批处理模式,而不是交互模式。
默认:前台运行,stdout 和 stderr 转接出来,而stdin关了
默认 -d=false, -i=false, -t=false
默认 -d=false -d=false时,默认-i=false,-t=false
dit:000
{.line-numbers} 1 2 3 4 5 6 7 8 9 10 11 12 13 14 [work@cdh06 ~]$ docker run --rm bash -c 'ls -l /dev/fd/' total 0 ls: /dev/fd/3: cannot read link: No such file or directory lrwx------ 1 root root 64 Jun 22 09:11 0 -> /dev/null l-wx------ 1 root root 64 Jun 22 09:11 1 -> pipe:[55404435] l-wx------ 1 root root 64 Jun 22 09:11 2 -> pipe:[55404436] lr-x------ 1 root root 64 Jun 22 09:11 3 [work@cdh06 ~]$ docker run --rm -d=false bash -c 'ls -l /dev/fd/' total 0 ls: /dev/fd/3: cannot read link: No such file or directory lrwx------ 1 root root 64 Jun 22 09:11 0 -> /dev/null l-wx------ 1 root root 64 Jun 22 09:11 1 -> pipe:[55409027] l-wx------ 1 root root 64 Jun 22 09:11 2 -> pipe:[55409028] lr-x------ 1 root root 64 Jun 22 09:11 3
此时,docker 使用了 -a STDERR -a STDOUT 选项。
前台 -t
dit: 001
{.line-numbers} 1 2 3 4 5 $ docker run --rm -t bash -c 'ls -l /dev/fd/' total 0 lrwx------ 1 root root 64 Jun 22 10:14 0 -> /dev/pts/0 lrwx------ 1 root root 64 Jun 22 10:14 1 -> /dev/pts/0 lrwx------ 1 root root 64 Jun 22 10:14 2 -> /dev/pts/0
但是 stdin (/dev/fd/0)是得不到输入的。
前台 -i
dit:010
{.line-numbers} 1 2 3 4 5 $ docker run --rm -i bash -c 'ls -l /dev/fd/' total 0 lr-x------ 1 root root 64 Jun 22 10:18 0 -> pipe:[55703397] l-wx------ 1 root root 64 Jun 22 10:18 1 -> pipe:[55703398] l-wx------ 1 root root 64 Jun 22 10:18 2 -> pipe:[55703399]
前台 -it
dit:011
{.line-numbers} 1 2 3 4 5 $ docker run --rm -it bash -c 'ls -l /dev/fd/' total 0 lrwx------ 1 root root 64 Jun 22 10:19 0 -> /dev/pts/0 lrwx------ 1 root root 64 Jun 22 10:19 1 -> /dev/pts/0 lrwx------ 1 root root 64 Jun 22 10:19 2 -> /dev/pts/0
Q: -it 和 -t 没有看出来区别呀。 Ans: 有的。-i才能接收标准输入,前台运行时,只有-t没有-i,虽然会保持不退出,但无法输入任何命令和特殊字符,要退出,只有再开 一个窗口,docker rm -f 命令删除容器。
detach模式
-d=true 时,默认 -i=false,-t=true
后台模式,执行docker run 命令是看不到任何标准输出的,需要借助docker logs 命令。
{.line-numbers} 1 2 3 4 5 6 $ docker run --rm -dit bash -c 'echo hello' 689d972fb889adf9e62e2a003e7976827cf0405233ffdc30dc54a70aa7e67aaa $ docker run --name demo -d bash -c 'echo hello' && docker logs demo && docker rm demo 4a9aeb1cfdf5686cdfba00512b83d3e2e4635d989332c60f13aa63940ef36940 hello demo
{.line-numbers} 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 # -d 模式 $ docker run --name demo -d bash -c 'ls -l /dev/fd/' && docker logs demo && docker rm demo 5d137c240eab57296702faec3ba155402ca72ed99086573951c0d07269b84dd3 ls: /dev/fd/3: cannot read link: No such file or directory total 0 lrwx------ 1 root root 64 Jun 22 10:48 0 -> /dev/null l-wx------ 1 root root 64 Jun 22 10:48 1 -> pipe:[55834607] l-wx------ 1 root root 64 Jun 22 10:48 2 -> pipe:[55834608] lr-x------ 1 root root 64 Jun 22 10:48 3 demo # -dit 模式 $ docker run --name demo -dit bash -c 'ls -l /dev/fd/' && docker logs demo && docker rm demo dda596f4c4edc1b8a720490b64bc9101bd17f97343075e5017efa69dab5ef9eb total 0 lrwx------ 1 root root 64 Jun 22 10:49 0 -> /dev/pts/0 lrwx------ 1 root root 64 Jun 22 10:49 1 -> /dev/pts/0 lrwx------ 1 root root 64 Jun 22 10:49 2 -> /dev/pts/0 ls: /dev/fd/3: cannot read link: No such file or directory lr-x------ 1 root root 64 Jun 22 10:49 3 demo # -di # ps: 其实,后台模式下,开启 STDIN 没有意义 $ docker run --name demo -di bash -c 'ls -l /dev/fd/' && docker logs demo && docker rm demo lr-x------ 1 root root 64 Jun 22 10:54 0 -> pipe:[55975007] l-wx------ 1 root root 64 Jun 22 10:54 1 -> pipe:[55975008] l-wx------ 1 root root 64 Jun 22 10:54 2 -> pipe:[55975009] # -dt $ docker run --name demo -dt bash -c 'ls -l /dev/fd/' && docker logs demo && docker rm demo lrwx------ 1 root root 64 Jun 22 10:58 0 -> /dev/pts/0 lrwx------ 1 root root 64 Jun 22 10:58 1 -> /dev/pts/0 lrwx------ 1 root root 64 Jun 22 10:58 2 -> /dev/pts/0
前后台切换
docker attach 命令可以把后台运行的容器挂到前台来。 如果容器运行时使用了 -it,那么可以使用 Ctrl-P Ctrl-Q 把容器重新放到后台,继续执行。 如果没有使用 -it,那么就只能使用 Ctrl-C 杀死容器才能退出。
–attach
使用 -a stdin 之后,就进入detach模式,还得按下Ctrl-D才能返回。 这是因为不指定 -a,容器默认有 -a stdout 和 -a stderr,而指定了-a stdin,默认绑定就没了,没了默认绑定就只有进入后台了。
{.line-numbers} 1 2 3 $ docker run -a stdin --name demo bash a642ce63d68c8ac8edca395b51004a2f7ee635a9ecbac4ca28f31d2a8d721fef <Ctrl-D>
分析一下,借助 ls -l /dev/fd/ 查看文件描述符,借助 cat 读取标准输入。
{.line-numbers} 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 # 容器的标准输入并没有打开,但外部确实看到好像标准输入能读取 $ docker run -a stdin --name demo bash -c 'ls -l /dev/fd/; cat' 4465e310ef751b79245b598b09d35b149fc5ee85002fb97d24ddcfae53fe95b9 hello, world <Ctrl-D> [work@cdh06 ~]$ docker logs demo total 0 lrwx------ 1 root root 64 Jun 22 11:26 0 -> /dev/null l-wx------ 1 root root 64 Jun 22 11:26 1 -> pipe:[56065531] l-wx------ 1 root root 64 Jun 22 11:26 2 -> pipe:[56065532] lr-x------ 1 root root 64 Jun 22 11:26 3 ls: /dev/fd/3: cannot read link: No such file or directory # 加上-i就通了。 $ docker rm -f demo demo [work@cdh06 ~]$ docker run -a stdin -i --name demo bash -c 'ls -l /dev/fd/; cat' 28548534643ab2a6fde1ac7ef4393eca13e2671b95570a5ff898732f0f165fbf hello world <Ctrl-D> [work@cdh06 ~]$ docker logs demo total 0 ls: /dev/fd/3: cannot read link: No such file or directory lr-x------ 1 root root 64 Jun 22 11:27 0 -> pipe:[56069724] l-wx------ 1 root root 64 Jun 22 11:27 1 -> pipe:[56069725] l-wx------ 1 root root 64 Jun 22 11:27 2 -> pipe:[56069726] lr-x------ 1 root root 64 Jun 22 11:27 3 hello world # -a stdout 和 -a stderr 指定至少一个,就不会进入后台 [work@cdh06 ~]$ docker run --rm -a stdout -a stderr bash -c 'ls -l /dev/fd/' ls: /dev/fd/3: cannot read link: No such file or directory total 0 lrwx------ 1 root root 64 Jun 22 11:49 0 -> /dev/null l-wx------ 1 root root 64 Jun 22 11:49 1 -> pipe:[56124973] l-wx------ 1 root root 64 Jun 22 11:49 2 -> pipe:[56124974] lr-x------ 1 root root 64 Jun 22 11:49 3 [work@cdh06 ~]$ docker run --rm -a stdout bash -c 'ls -l /dev/fd/' total 0 lrwx------ 1 root root 64 Jun 22 11:49 0 -> /dev/null l-wx------ 1 root root 64 Jun 22 11:49 1 -> pipe:[56128608] l-wx------ 1 root root 64 Jun 22 11:49 2 -> pipe:[56128609] lr-x------ 1 root root 64 Jun 22 11:49 3 [work@cdh06 ~]$ docker run --rm -a stderr bash -c 'ls -l /dev/fd/' ls: /dev/fd/3: cannot read link: No such file or directory # 不论如何,stdout 和 stderr 的输出都可以通过logs没了查看 $ docker run --name demo -a stderr bash -c 'ls -l /dev/fd/' ls: /dev/fd/3: cannot read link: No such file or directory [work@cdh06 ~]$ docker logs demo total 0 ls: /dev/fd/3: cannot read link: No such file or directory lrwx------ 1 root root 64 Jun 22 11:54 0 -> /dev/null l-wx------ 1 root root 64 Jun 22 11:54 1 -> pipe:[56138416] l-wx------ 1 root root 64 Jun 22 11:54 2 -> pipe:[56138417] lr-x------ 1 root root 64 Jun 22 11:54 3 # Extend:甚至,交互模式的容器,其标准IO也可以用 docker logs 命令查看 $ docker run -it --name demo bash bash-5.1# echo hello hello bash-5.1# exit [work@cdh06 ~]$ docker logs demo bash-5.1# echo hello hello bash-5.1# exit # 由此,有时候交互模式卡顿,可能是日志阻塞了交互,可以使用异步日志 docker run --rm -it --log-opt mode=non-blocking --log-opt max-buffer-size=10m bash docker run --rm -it bash
-i 和 -a
容器内的进程 P,docker 服务进程 D,命令行进程 S。 想要容器读取输入,必须做两点:
使用 -i 选项,把 P 的 STDIN 打开,打开的STDIN的另一头在进程D中。
使用 -a stdin 把 S 的标准输入对接到 P 的STDIN,通过 D 做中转。
-i 会默认启用 -a stdin;但 -a stdin 却不会自动启用 -i。
注:bash 镜像
使用 bash 镜像的时候,
{.line-numbers} 1 docker run bash -c 'ls -l /dev/fd/'
完整的格式应该写成
{.line-numbers} 1 docker run bash bash -c 'ls -l /dev/fd/'
{.line-numbers} 1 2 3 COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] CMD ["bash"]
而 docker-engrypoint.sh 就这一点。
{.line-numbers} 1 2 3 4 5 6 7 8 9 10 11 # !/usr/bin/env bash set -Eeuo pipefail # first arg is `-f` or `--some-option` # or there are no args if [ "$#" -eq 0 ] || [ "${1#-}" != "$1" ]; then # docker run bash -c 'echo hi' exec bash "$@" fi exec "$@"
当指定 -c 的时候,脚本会自动补上 bash。
注:本文转载自https://blog.csdn.net/chenxizhan1995/article/details/118116216