• 浅谈 docker run 命令中的 -i -t 和 -d 选项


    docker Ubuntu 镜像为例,ubuntu镜像启动时默认执行的命令是"/bin/bash"。

    不带任何选项

    root@ubuntu20:~# docker run ubuntu:20.04 
    
    root@ubuntu20:~# docker ps
    CONTAINER ID   IMAGE              COMMAND                  CREATED          STATUS                    PORTS                                                                                   NAMES            
    
    • 1
    • 2
    • 3
    • 4

    容器启动后立马就停止运行了。

    这是因为:不加 -i 选项,docker容器中执行的程序【/bin/bash】的标准输入默认是关闭的,由于 bash 程序需要从标准输入读取数据,因此标准输入一旦关闭,bash 程序就退出了,容器也就退出了。

    带 -i 选项

    root@ubuntu20:~# docker run -i ubuntu:20.04
    ls -lh
    total 48K
    lrwxrwxrwx   1 root root    7 Oct  3 02:03 bin -> usr/bin
    drwxr-xr-x   2 root root 4.0K Apr 15  2020 boot
    drwxr-xr-x   5 root root  340 Oct 22 06:37 dev
    drwxr-xr-x   1 root root 4.0K Oct 22 06:37 etc
    drwxr-xr-x   2 root root 4.0K Apr 15  2020 home
    lrwxrwxrwx   1 root root    7 Oct  3 02:03 lib -> usr/lib
    lrwxrwxrwx   1 root root    9 Oct  3 02:03 lib32 -> usr/lib32
    lrwxrwxrwx   1 root root    9 Oct  3 02:03 lib64 -> usr/lib64
    lrwxrwxrwx   1 root root   10 Oct  3 02:03 libx32 -> usr/libx32
    drwxr-xr-x   2 root root 4.0K Oct  3 02:03 media
    drwxr-xr-x   2 root root 4.0K Oct  3 02:03 mnt
    drwxr-xr-x   2 root root 4.0K Oct  3 02:03 opt
    dr-xr-xr-x 389 root root    0 Oct 22 06:37 proc
    drwx------   2 root root 4.0K Oct  3 02:06 root
    drwxr-xr-x   5 root root 4.0K Oct  3 02:06 run
    lrwxrwxrwx   1 root root    8 Oct  3 02:03 sbin -> usr/sbin
    drwxr-xr-x   2 root root 4.0K Oct  3 02:03 srv
    dr-xr-xr-x  13 root root    0 Oct 22 06:37 sys
    drwxrwxrwt   2 root root 4.0K Oct  3 02:06 tmp
    drwxr-xr-x  13 root root 4.0K Oct  3 02:03 usr
    drwxr-xr-x  11 root root 4.0K Oct  3 02:06 var
    
    ll
    /bin/bash: line 3: ll: command not found
    exit
    
    root@ubuntu20:~# docker ps
    CONTAINER ID   IMAGE              COMMAND                  CREATED          STATUS                    PORTS                                                                                   NAMES
    
    • 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

    加上 -i 选项后,docker 容器中执行的程序【/bin/bash】的标准输入是打开的,并且就是执行“docker run -i ubuntu:20.04”这个命令启动的程序的标准输入。因此,我们可以输入一些数据和容器内的 bash 程序交互。最后输入exit,bash 程序执行 exit 命令后退出,容器也就退出了。

    再看一个例子,我们让 Ubuntu 镜像启动时执行 cat 命令:

    root@ubuntu20:~# echo 123 | docker run -i ubuntu:20.04 cat
    123
    
    • 1
    • 2

    由于加了-i 选项,并且使用了管道,则执行“docker run -i ubuntu:20.04 cat”命令后,它启动的程序的标准输入就是管道的标准输出,于是 cat 程序打印出“123”之后退出,容器也退出了。

    带 -i 和 -t 选项

    在这里插入图片描述

    可以看到bash执行命令的输出有了终端的颜色。这是因为加了 -t 选项后,标准输入就变成了一个伪终端设备,bash 如果检查到输入是终端设备就会做一些特殊的处理。

    再看一个例子:

    root@ubuntu20:~# docker run -i ubuntu:20.04 passwd root
    New password: 123
    Retype new password: 1234
    Sorry, passwords do not match.
    passwd: Authentication token manipulation error
    passwd: password unchanged
    root@ubuntu20:~# 
    root@ubuntu20:~# docker run -it ubuntu:20.04 passwd root
    New password: 
    Retype new password: 
    Sorry, passwords do not match.
    passwd: Authentication token manipulation error
    passwd: password unchanged
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    加 -t 选项后,passwd 程序检测到输入是一个终端,则密码不会显示出来。

    -i 和 -t 选项通常都一起使用。

    -d 选项

    从上述几个例子看,如果不带 -d 选项,则在交互完成后,Ubuntu 容器就会退出。原因就是交互完成后,会使标准输入关闭。有一种办法就是交互完成后,不要敲 exit 命令或 ctrl+c,而是敲 ctrl+p 再加上ctrl+q。

    root@ubuntu20:~# docker run -it ubuntu:20.04
    lroot@b5f8b4f4178d:/# ls
    bin  boot  dev  etc  home  lib  lib32  lib64  libx32  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
    root@b5f8b4f4178d:/# root@ubuntu20:~# 
    root@ubuntu20:~# docker ps
    CONTAINER ID   IMAGE              COMMAND                  CREATED          STATUS                    PORTS                                                                                   NAMES
    b5f8b4f4178d   ubuntu:20.04       "/bin/bash"              13 seconds ago   Up 12 seconds                                                                                                     tender_visvesvaraya
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    接下来再想和 bash 交互,就使用 docker attach 命令:

    root@ubuntu20:~# docker attach b5f8b4f4178d
    root@b5f8b4f4178d:/# ls
    bin  boot  dev  etc  home  lib  lib32  lib64  libx32  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
    root@b5f8b4f4178d:/# exit
    exit
    
    • 1
    • 2
    • 3
    • 4
    • 5

    但是这样太麻烦了。当启动像 Ubuntu 这样操作系统的镜像时,我们一般都是希望它启动后就一直存在,这样就需要添加 -d 选项:

    root@ubuntu20:~# docker run -itd ubuntu:20.04
    e911274f4b2bfbbc627dc3aaa2ae1e888931522f124904ba05c8617a3a31422a
    root@ubuntu20:~# docker ps
    CONTAINER ID   IMAGE              COMMAND                  CREATED          STATUS                       PORTS                                                                                   NAMES
    e911274f4b2b   ubuntu:20.04       "/bin/bash"              3 seconds ago    Up 2 seconds                                                                                                         amazing_murdock
    
    • 1
    • 2
    • 3
    • 4
    • 5

    这样的话,当我们执行 docker run 命令时,它只会返回容器的 id 就退出,而不会和容器中的 bash 程序进行交互。由于使用了 -i 选项,容器中的 bash 程序中的标准输入并未关闭,所以它一直在等待用户输入,所以容器也就不会退出。

    接下来我们想进入容器中交互时,就是用docker exec 命令:

    root@ubuntu20:~# docker exec -it e911274f4b2b bash
    root@e911274f4b2b:/# ls
    bin  boot  dev  etc  home  lib  lib32  lib64  libx32  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
    root@e911274f4b2b:/# exit
    exit
    root@ubuntu20:~# 
    root@ubuntu20:~# docker ps
    CONTAINER ID   IMAGE              COMMAND                  CREATED          STATUS                       PORTS                                                                                   NAMES
    e911274f4b2b   ubuntu:20.04       "/bin/bash"              4 minutes ago    Up 4 minutes                                                                                                         amazing_murdock
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    这会在容器中新启动一个 bash 程序,然后我们与它做交互即可。

    如果使用 docker attach 命令,则会和初始的 bash 程序交互,那么当我们输入 exit 时,容器就会退出:

    root@ubuntu20:~# docker attach e911274f4b2b
    root@e911274f4b2b:/# exit
    exit
    root@ubuntu20:~# docker ps
    CONTAINER ID   IMAGE              COMMAND                  CREATED             STATUS                       PORTS                                                                                   NAMES
    
    • 1
    • 2
    • 3
    • 4
    • 5

    对于像 nginx 这些服务器程序的镜像,由于它的启动命令不需要和标准输入交互,所以我们不需要添加 -it 选项,直接使用 -d 选项就可以:

    root@ubuntu20:~# docker run -d --name some-nginx nginx
    d0eba4fba2f68f5dd23f32569d5a633c275724c75035d54a3e7daf59db2f6620
    
    root@ubuntu20:~# docker exec -it some-nginx bash
    root@d0eba4fba2f6:/# ls -lh /etc/nginx/conf.d/default.conf 
    -rw-r--r-- 1 root root 1.1K Oct 22 07:23 /etc/nginx/conf.d/default.conf
    root@d0eba4fba2f6:/# exit
    exit
    root@ubuntu20:~# 
    root@ubuntu20:~# docker ps
    CONTAINER ID   IMAGE              COMMAND                  CREATED          STATUS                       PORTS                                                                                   NAMES
    d0eba4fba2f6   nginx              "/docker-entrypoint.…"   34 seconds ago   Up 33 seconds                80/tcp                                                                                  some-nginx
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    也是使用 docker exec 命令与容器中的 bash 程序交互来实现对容器中进程和文件的管理。

  • 相关阅读:
    指针和数组笔试题解析
    23年计算机408复习规划以及高分技巧--上岸学姐总结
    昇思25天学习打卡营第16天|Vision Transformer图像分类
    微软正式发布.NET 6:号称迄今为止最快
    【前端学习 -Vue (7) Vue2.x组件通信有哪些方式?】
    西安邮电大学第三届网络安全技能大赛---PWN方向WP
    MVCC实现过程
    beego开发博客系统学习(二)
    某大厂AI Lab 算法研究员 Intern面经
    【编译原理】概述
  • 原文地址:https://blog.csdn.net/woay2008/article/details/133973226