使用-it选项时,Docker容器退出

7

考虑以下Dockerfile:

FROM ubuntu:16.04

RUN apt-get update && \
    apt-get install -y apache2 && \
    apt-get clean

ENTRYPOINT ["apache2ctl", "-D", "FOREGROUND"]

当使用命令docker run -p 8080:80 <image-id>运行容器时,容器将启动并保持运行状态,从而可以在主机上按预期访问默认的Apache网页https://localhost:8080。然而,使用此运行命令时,我无法使用Ctrl+C退出容器,这也是预期的,因为容器没有使用-it选项启动。现在,如果将-it选项添加到运行命令中,则容器在启动后立即退出。为什么会这样?是否有一种优雅的方式使Apache在前台运行并在Ctrl+C上退出?

1
只是出于好奇,你尝试过使用 CMD 而不是 ENTRYPOINT 吗?另外,你知道 -it 不是一个命令,而是两个命令 -i-t 吗? - mad.meesh
当我自己运行它时,这一切似乎都按照你的期望工作。我运行了 docker run --rm -it image-id 命令,容器会一直运行,直到我使用 CTRL+C 发送 INT 信号。我的 Docker 版本是 Docker version 17.09.1-ce, build 19e2cf6 - Stephen Crosby
嗯,这很有趣,在我家的机器上也能运行,我正在运行 Docker version 17.12.0-ce, build c97c6d6。明天我得检查一下在工作中遇到问题的那台机器上我运行的是哪个版本。 - Sam Herrmann
你能否提供一个失败容器的 docker inspect 命令输出? - BMitch
我刚刚发现同样的问题在这里被问到了:(https://dev59.com/0aXja4cB1Zd3GeqPKgCh)。然而,那里提供的答案并不能解决我的问题。 - Sam Herrmann
显示剩余6条评论
5个回答

5
这种行为是Apache引起的,而不是Docker的问题。Apache设计时会在接收到SIGWINCH信号时优雅地关闭。当交互式运行容器时,SIGWINCH信号从主机传递到容器,有效地向Apache发出优雅关闭的信号。在某些主机上,容器可能在启动后立即退出。在其他主机上,容器可能会一直运行,直到终端窗口大小改变。
可以通过以下方式确认容器退出后是否有问题:查看Apache日志文件。
# Run container interactively:
docker run -it <image-id>

# Get the ID of the container after it exits:
docker ps -a

# Copy the Apache log file from the container to the host:
docker cp <container-id>:/var/log/apache2/error.log .

# Use any text editor to review the log file:
vim error.log

# The last line in the log file should contain the following:
AH00492: caught SIGWINCH, shutting down gracefully

Sources:


3
由于缺乏其他信号编号,并且考虑到httpd通常在与终端分离的情况下运行,因此选择使用SIGWINCH信号来指示httpd进行优雅关闭。像这种情况不是应该使用SIGTERM信号吗?毕竟SIGKILL是“立即停止,不要进行清理关闭”的命令。 - DBX12

4
您只需在运行命令中添加-d选项即可:
docker run -d -p 8080:80 my-container

2
谢谢您的回复yamenk,不幸的是这并没有回答问题。使用“-d”选项会在后台运行容器,而不是像所需的那样在前台运行。 - Sam Herrmann
这意味着它将在分离模式下持续运行,而用户希望它在“非分离”模式下运行。 - Majid Ali Khan
好的。这个答案意味着容器(和Apache)不会输出到主机的标准输出,并且Ctrl-C无法停止容器。 - Jason

3
如yamenk所述,将程序daemonize的原因是将其放置到后台并分离窗口大小调整。因为随后的帖子提到了在前台运行可能是理想的,所以有一种很好的方法可以在daemonizing之后模拟那种体验:使用"docker logs -f 容器名称"命令,这样就可以将常规stdout消息(如“GET / HTTP…”连接消息)返回到控制台,以便您可以查看它们的流动情况。现在,您可以调整窗口大小等操作,同时仍然能够看到您的故障排除信息。

1
我认为这是一个不错的替代方案。它不允许使用Ctrl-C,但我建议使用docker stop container-name来停止容器,根据您的工作流程可能还需要使用docker container rm container-name。我在我的开发目录中编写了名为start.shstop.sh的脚本。start.sh将启动带有-d的容器并开始将日志显示到stdout。stop.sh将停止容器并删除它。 - Jason

0

我在 Windows 10 的 wsl2 中,使用的是 Docker Engine v20.10.7,也遇到了这个问题。

解决方法:

# start bash in httpd container:
docker run --rm -ti -p 80:80 httpd:2.4.48 /bin/bash
# inside container execute:
httpd -D FOREGROUND

现在Apache httpd会一直运行,直到你按下CTRL-C或调整终端窗口大小。

关闭httpd后,输入:

exit

离开容器


0

一种解决方法是将输出导入到 cat 中:

docker run -it -p 8080:80 <image-id> | cat

注意:使用 -i -t 是很重要的。

Ctrl+C 可以工作,调整终端大小不会关闭 Apache。


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