根据我目前阅读的教程,使用“docker run -d
”将从图像启动一个容器,该容器将在后台运行。这是它的样子,我们可以看到我们已经有了容器 id。
root@docker:/home/root# docker run -d centos
605e3928cdddb844526bab691af51d0c9262e0a1fc3d41de3f59be1a58e1bd1d
但如果我运行“docker ps
”,则没有返回任何内容。
所以我尝试了“docker ps -a
”,我可以看到容器已经退出:
root@docker:/home/root# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
605e3928cddd centos:latest "/bin/bash" 31 minutes ago Exited (0) 31 minutes ago kickass_swartz
我做错什么了吗?如何解决此问题?
docker run -it -d <image> /bin/bash
让它以交互方式启动一个 bash shell 并且不会关闭容器,因为 shell 进程处于活动状态。
centos dockerfile 有一个默认命令 bash
。
这意味着,当在后台 (-d
) 运行时,shell 会立即退出。
2017 年更新
最新版本的 docker 授权在 foreground mode(-t
、-i
或 -it
)的 detached mode 和 中运行容器
在这种情况下,您不需要任何额外的命令,这就足够了:
docker run -t -d centos
bash 将在后台等待。
这最初在 kalyani-chaudhari 的 answer 中报告,并在 jersey bean 的 answer 中详细说明。
vonc@voncvb:~$ d ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4a50fd9e9189 centos "/bin/bash" 8 seconds ago Up 2 seconds wonderful_wright
请注意,对于 alpine,Marinos An 报告 in the comments:
docker run -t -d alpine/git 不会保持进程正常。不得不做: docker run --entrypoint "/bin/sh" -it alpine/git
原始答案(2015)
如 this article 中所述:
建议不要使用 docker run -i -t image your-command 运行,而是使用 -d,因为您只需一个命令即可运行容器,并且无需通过按 Ctrl + P + Q 来分离容器的终端。
但是,-d 选项存在问题。除非命令继续在前台运行,否则您的容器会立即停止。 Docker 要求您的命令继续在前台运行。否则,它会认为您的应用程序停止并关闭容器。
问题是某些应用程序没有在前台运行。我们怎样才能让它变得更容易?
在这种情况下,您可以将 tail -f /dev/null 添加到您的命令中。通过这样做,即使您的主命令在后台运行,您的容器也不会停止,因为 tail 一直在前台运行。
所以这会起作用:
docker run -d centos tail -f /dev/null
或者在 Dockerfile 中:
ENTRYPOINT ["tail"]
CMD ["-f","/dev/null"]
docker ps
将显示 centos 容器仍在运行。
从那里,您可以attach to it or detach from it(或 docker exec
一些命令)。
根据 this answer,添加 -t
标志将阻止容器在后台运行时退出。然后您可以使用 docker exec -i -t <image> /bin/bash
进入 shell 提示符。
docker run -t -d <image> <command>
似乎 -t 选项 isn't documented very well,虽然帮助说它“分配一个伪 TTY”。
tail -f /dev/null
docker run -t -d --name mysql -p 3306:3306 mysql
- 对我不起作用(ubuntu 14.04.5):STATUS=Exited (1) 4 秒前
背景
Docker 容器运行一个进程(“命令”或“入口点”)以使其保持活动状态。只要命令继续运行,容器就会继续运行。
在您的情况下,命令(/bin/bash
,默认情况下,在 centos:latest
上)会立即退出(就像 bash 在未连接到终端并且没有任何内容可运行时所做的那样)。
通常,当您以守护程序模式(使用 -d
)运行容器时,容器正在运行某种守护进程(如 httpd
)。在这种情况下,只要 httpd 守护进程正在运行,容器就会保持活动状态。
您似乎想要做的是让容器保持活动状态,而不会在容器内运行守护进程。这有点奇怪(因为在您与容器交互之前,容器不会做任何有用的事情,也许是使用 docker exec
),但在某些情况下,这样做可能有意义。
(您的意思是进入容器内的 bash 提示符吗?这很简单!docker run -it centos:latest
)
解决方案
使容器无限期地以守护程序模式保持活动的一种简单方法是将 sleep infinity
作为容器的命令运行。这不依赖于做一些奇怪的事情,比如在守护进程模式下分配一个 TTY。虽然它确实依赖于做一些奇怪的事情,比如使用 sleep
作为你的主要命令。
$ docker run -d centos:latest sleep infinity
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d651c7a9e0ad centos:latest "sleep infinity" 2 seconds ago Up 2 seconds nervous_visvesvaraya
替代解决方案
如 cjsimon 所示,-t
选项分配一个“伪 tty”。这会欺骗 bash 无限期地继续运行,因为它认为它已连接到交互式 TTY(即使如果您不通过 -i
,您将无法与该特定 TTY 进行交互)。无论如何,这也应该可以解决问题:
$ docker run -t -d centos:latest
不能 100% 确定 -t
是否会产生其他奇怪的交互;如果是这样,也许可以在下面发表评论。
infinity
。
您好,这个问题是因为如果容器中没有正在运行的应用程序,docker 容器就会退出。
-d
选项只是以守护程序模式运行容器。
所以让你的容器持续运行的技巧是指向 docker 中的一个 shell 文件,这将使你的应用程序保持运行。你可以尝试使用 start.sh 文件
Eg: docker run -d centos sh /yourlocation/start.sh
这个 start.sh 应该指向一个永无止境的应用程序。
如果您不想运行任何应用程序,您可以安装 monit
以保持您的 docker 容器运行。请让我们知道这两种情况是否对您保持容器运行有效。
一切顺利
您可以通过以下任一方式完成您想要的:
docker run -t -d <image-name>
或者
docker run -i -d <image-name>
或者
docker run -it -d <image-name>
其他答案(即tail -f /dev/null)建议的命令参数是完全可选的,并且不需要让您的容器保持在后台运行。
另请注意 Docker 文档建议组合 -i 和 -t 选项将使其表现得像一个 shell。
看:
https://docs.docker.com/engine/reference/run/#foreground
我从 docker 文件中的 ENTRYPOINT
运行此代码片段:
while true
do
echo "Press [CTRL+C] to stop.."
sleep 1
done
将构建的 docker 映像运行为:
docker run -td <image name>
登录容器外壳:
docker exec -it <container id> /bin/bash
执行命令如下:
docker run -t -d <image-name>
如果要指定端口,则命令如下:
docker run -t -d -p <port-no> <image-name>
使用以下命令验证正在运行的容器:
docker ps
-t -d
与 -i -d
有什么优势吗?两者都将保持容器运行。
如果里面的任务完成,Docker 容器就会退出,所以如果你想让它保持活动状态,即使它没有任何工作或已经完成它们,你可以做 docker run -di image
。执行 docker container ls
后,您将看到它正在运行。
Docker 要求您的命令继续在前台运行。否则,它会认为您的应用程序停止并关闭容器。
因此,如果您的 docker entry 脚本是一个后台进程,如下所示:
/usr/local/bin/confd -interval=30 -backend etcd -node $CONFIG_CENTER &
如果后面没有触发其他前台进程,'&' 使容器停止并退出。所以解决方案只是删除“&”或在其后运行另一个前台 CMD,例如
tail -f server.log
touch
该文件,以防您找不到日志文件。
如果您在 Dockerfile 末尾使用 CMD,您可以在末尾添加代码。这仅在您的 docker 构建在 ubuntu 或任何可以使用 bash 的操作系统上时才有效。
&& /bin/bash
简而言之,你的 Dockerfile 的结尾看起来像这样。
...
CMD ls && ... && /bin/bash
因此,如果您在运行 docker 映像后自动运行任何东西,并且当任务完成时,bash 终端将在您的 docker 中处于活动状态。因此,您可以输入您的 shell 命令。
也许只有我一个人,但在 CentOS 7.3.1611 和 Docker 1.12.6 上,但我最终不得不使用@VonC 和@Christopher Simon 发布的答案的组合来让它可靠地工作。在此之前我所做的任何事情都不会阻止容器在成功运行 CMD 后退出。我正在启动 oracle-xe-11Gr2 和 sshd。
Dockerfile
...
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -N '' && systemctl enable sshd
...
CMD /etc/init.d/oracle-xe start && /sbin/sshd && tail -f /dev/null
然后添加 -d -t 和 -i 运行
docker run --shm-size=2g --name oracle-db -d -t -i -p 5022:22 -p 5080:8080 -p 1521:1521 centos-oracle:7.3.1611
终于在把我的头撞到墙上几个小时之后
ssh -v root@127.0.0.1 -p 5022
...
root@127.0.0.1's password:
debug1: Authentication succeeded (password).
无论出于何种原因,如果尾部 -f 被删除,或者任何 -t -d -i 选项被省略,则在执行 CMD 后上述内容将退出。
以交互模式运行 docker 可能会解决此问题。
这是使用和不使用交互模式运行图像的示例
chaitra@RSK-IND-BLR-L06:~/dockers$ sudo docker run -d -t -i test_again1.0 b6b9a942a79b1243bada59db19c7999cfff52d0a8744542fa843c95354966a18
chaitra@RSK-IND-BLR-L06:~/dockers$ sudo docker ps
容器 ID 图像命令创建状态端口名称
chaitra@RSK-IND-BLR-L06:~/dockers$ sudo docker run -d -t -i test_again1.0 bash c3d6a9529fd70c5b2dc2d7e90fe662d19c6dad8549e9c812fb2b7ce2105d7ff5
chaitra@RSK-IND-BLR-L06:~/dockers$ sudo docker ps
容器 ID 图像命令已创建状态端口名称 c3d6a9529fd7 test_again1.0 "bash" 2 秒前 1 秒 awesome_haibt
我遇到了同样的问题,只是打开另一个带有 bash 的终端对我有用:
创建容器:
docker run -d mcr.microsoft.com/mssql/server:2019-CTP3.0-ubuntu
containerid=52bbc9b30557
启动容器:
docker start 52bbc9b30557
启动 bash 以保持容器运行:
docker exec -it 52bbc9b30557 bash
启动您需要的过程:
docker exec -it 52bbc9b30557 /path_to_cool_your_app
我也面临同样的问题,但方式不同。当我创建 docker 容器时。它会自动停止在后台运行的未使用容器。有时它还会停止正在使用的容器。在我的情况下,这是因为它之前拥有的 docker.sock 文件的权限。你要做的是:-
再次安装 docker。(当我在 ubuntu 上工作时,我从这里安装它)运行命令以更改权限。 sudo chmod 666 /var/run/docker.sock 安装 docker-compose(这是可选的,因为我有 compose 文件可以一起创建许多容器) sudo curl -L "https://github.com/docker/compose/releases/download /1.26.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose 检查对于版本,以确保我拥有最新版本并且不会因某些贬低而出现问题。然后我运行 docker 容器构建。
您可以简单地使用:
docker container run -d -it <container name or id> /bin/bash
有多个选项可以在前台/分离状态下运行容器。但是如果您仍然觉得问题没有解决,您可以尝试通过查看日志来解决问题。
sudo docker logs -f >> container.log
此外,您还可以使用 --details 显示提供给日志的额外详细信息。
Dockerfile 中的应用程序路径不正确:
我正在使用 Alpine Linux 将应用程序从 RHEL 服务器迁移到 Docker 容器。
构建过程中没有错误,所以我很惊讶地看到容器立即退出!
第一个停靠港:
docker logs <containerID>
这表明我在 Dockerfile 中提供给 CMD 的二进制文件的路径是伪造的:
line 0: /sbin/postfix: not found
好吧,这告诉了我事情是如何被破坏的,但没有具体说明在哪里:我仍然需要 Alpine Linux 中二进制文件的正确路径......
故障排除:
谷歌搜索没有显示正确的路径,所以我在我的 Dockerfile 中添加了以下行:
RUN which postfix
然后,我查看了我的构建日志记录 - 由附加到我的构建命令的以下命令提供 - 以检索 RUN which postfix
的值
--progress=plain > /path/to/build.log 2>&1
修复:
我删除了这个测试版本,在 Dockerfile 中为 CMD 提供了正确的路径 - /usr/sbin/postfix
,删除了 RUN which postfix
并运行了另一个构建。
瞧;这个过程现在仍然存在。
所以一个 duff 路径导致容器立即退出......
论证顺序很重要
Jersey Beans 答案(所有 3 个示例)对我有用。经过相当多的反复试验,我意识到论点的顺序很重要。
保持容器在后台运行:docker run -t -d <image-name>
保持容器在前台运行:docker run <image-name> -t -d
对我来说,来自 Powershell 背景并不明显。
如果要对容器进行操作,则需要在前台运行它以使其保持活力。
这 4 个命令都可以使您的 docker 容器保持运行:
docker run -td centos
docker run -dt centos
docker run -t -d centos
docker run -d -t centos
docker exec -it <yourContainer> bash
。