Docker -it 命令与 Docker 镜像或 Docker 容器有关。

3

我是 Docker 的新手,正在尝试使用 101-tutorial docker 镜像(https://github.com/dockersamples/101-tutorial)学习 Docker。

图片描述

在这个教程中,他们试图解释,当从同一镜像运行两个容器实例时,默认情况下第一个容器创建的数据不会在第二个容器中可用(除非我们使用容器卷和挂载等)。

第1点和第2点显示一个 Ubuntu 容器正在运行,并有一个名为 data.txt 的文件。

据我所知,docker -it 用于获取访问 Docker 容器内部终端的权限。https://docs.docker.com/engine/reference/run/

但我不明白第3点中使用的命令。为什么要在 Ubuntu 镜像上运行 docker run -it ubuntu ls / 命令,而不是在使用容器 ID 的容器上运行?该命令是否只用于显示镜像内的内容,而不是使用 ls / 显示 Docker 容器中的内容?

我原本以为第3点应该创建另一个容器实例,然后运行 ls /,但根据 docker ps,我看到我的机器上只有一个正在运行的 Ubuntu 容器。


1
如果我理解正确的话,它会启动一个容器并在其中运行 ls 命令,但该容器会立即关闭。 - daniu
因此,使用传递到命令中的镜像名称创建docker容器,然后在该容器上运行ls /,然后立即关闭docker容器? - firstpostcommenter
1
尝试使用 docker ps -a 列出所有容器。现在你只能得到“正在运行”的容器。@daniu 是正确的,因为只要 PID=1 的进程在运行,容器就会一直运行。ls 运行然后退出,这使得容器进入“已退出”状态。更多信息请参见:https://dev59.com/vlwY5IYBdhLWcg3wnYx3 - tgogos
1
@tgogos:谢谢。很清楚。 - firstpostcommenter
此外,docker run 命令始终与 ImageID 有关,而不是 containerID,这意味着它将始终启动一个新的容器。https://dev59.com/gFsW5IYBdhLWcg3wm4QK#46138763 - firstpostcommenter
3个回答

3
根据docker run文档的说明:
Docker在隔离的容器中运行进程。容器是在主机上运行的进程。主机可以是本地的或远程的。当操作员执行docker run命令时,运行的容器进程是被隔离的,它有自己的文件系统、网络和与主机分离的独立进程树。
进程完成后,容器将被关闭。
至于您是否“指的是镜像还是容器”的问题 - 您将镜像作为参数传递以创建容器,然后在创建的容器中运行进程。
Docker容器的生命周期为:
- docker run imagename -> 从镜像imagename创建容器x - docker exec x ls -> 在正在运行的容器x中执行ls命令 - docker stop x -> 停止容器(但仍会在docker container ls -a中显示) - docker start x -> 重新启动容器x - docker stop x -> 再次停止容器x - docker rm x -> 删除容器x(现在也不会在ls -a中显示)

所以,当我们使用 docker run 运行长时间运行的命令(如启动 Spring Boot 应用程序等)时,由于这些命令除非我们手动停止它们否则不会完成,因此 Docker 容器将一直运行,除非手动停止容器。但是对于像 ls / 这样的短命令的 docker run,由于返回了结果并且命令已完成,因此在运行命令后 Docker 容器将退出/停止/关闭。正确吗? - firstpostcommenter
@firstpostcommenter 是的(虽然您不需要手动停止容器,而是可以终止进程)。我编辑了我的帖子,列出了常见的生命周期命令。 - daniu

3

Docker容器是完全隔离的。使用镜像创建容器时,通过命名空间和控制组从您的系统中分离出一小部分资源,然后将镜像中的文件复制到此隔离环境的资源中。

执行命令docker run -it ubuntu ls /时,它会创建一个新的容器,运行指定的命令ls /,并使用-i-t标志为Docker容器提供交互式tty。

运行此进程并显示输出后,容器立即退出,因此在docker ps的输出中没有任何内容。要检查已创建的容器,请运行docker ps --all命令。


0

我看到这个问题是关于docker run imagename命令的。

简而言之:您没有看到Docker容器,因为Docker容器已经创建、启动,然后立即退出。为什么?因为这完全取决于在用于构建您正在尝试运行的Docker镜像(在本例中为ubuntu Docker镜像)的Dockerfile中给出的CMD命令。


关于Docker和docker run命令的一些背景信息:-
在您的情况下,当您运行docker run ubuntu命令时,Docker容器被创建并启动,然后立即退出,因此您无法在docker ps容器列表中看到它,但是您可以在docker ps -a命令结果中看到具有exited状态。
这是因为容器旨在运行特定的任务或进程,例如托管Web服务器或应用程序服务器或数据库的实例,或仅执行某种计算或分析。
完成任务后,容器将退出。容器只在其中的进程存活期间存在。如果容器内的WebService停止或崩溃,那么容器将退出。
那么是谁定义了在容器内运行什么进程呢?
如果我们查看像nginx这样的流行Docker镜像的dockerfile,我们会看到一个称为CMD的指令,该指令代表在容器启动时将运行哪个程序。
对于nginx镜像,它是nginx命令,对于mysql镜像,它是mysqld命令。
早些时候你尝试运行一个带有Ubuntu镜像的容器,如果我们查看该镜像的dockerfile(Ubuntu Docker image's dockerfile),就会看到它在CMD行中使用bash作为默认命令。现在bash并不像Web服务器或数据库服务器一样是一个进程。它是一个监听来自终端的输入的shell,如果找不到终端,它就会退出。因此,当您先前运行镜像时,Docker从镜像创建了一个容器并启动了bash程序。默认情况下,当Docker运行容器时,它不会连接终端,因此bash程序找不到终端,就会退出。由于在创建容器时启动的进程已经结束,所以容器也会退出。
那么我们该如何指定启动容器的不同命令呢?

一种方法是在 docker run 命令中附加一个命令,这样就可以覆盖镜像中指定的默认命令。例如:docker run ubuntu sleep 5,将 sleep 5 命令添加为选项。这样,当容器启动时,它将运行 sleep 程序,等待 5 秒钟,然后退出。但是我们如何使此更改永久化呢?假设我们希望镜像在启动时始终运行 sleep 命令。那么我们应该从基础的 ubuntu 镜像创建自己的镜像,并指定一个新的命令。

Dockerfile 中使用 CMD 指令。

FROM Ubuntu
CMD sleep 5

使用EntrypointCMD指令哪个更好?

FROM Ubuntu
ENTRYPOINT ["sleep"]
CMD ["5"]

现在我们可以使用docker build命令构建新的镜像,并将其命名为ubuntu-sleeper或类似的名称。现在,我们只需运行docker run ubuntu-sleeper命令,就可以获得相同的结果,它总是会睡眠5秒钟然后退出。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接