Docker 容器无法启动,因为现有的 PID 文件



当我启动一个docker容器时,它失败了,因为现有的pid文件:

[root@newhope sergio]# docker logs sharp_shockley 
httpd (pid 1) already running
httpd (pid 1) already running
httpd (pid 1) already running
httpd (pid 1) already running

我怎么能删除这样一个文件,因为我找不到它。

[root@newhope sergio]# docker version
Client version: 1.4.1
Client API version: 1.16
Go version (client): go1.3.3
Git commit (client): 5bc2ff8/1.4.1
OS/Arch (client): linux/amd64
Server version: 1.4.1
Server API version: 1.16
Go version (server): go1.3.3
Git commit (server): 5bc2ff8/1.4.1
[root@newhope sergio]# find / -name "httpd.pid"
find: ‘/run/user/1000/gvfs’: Permiso denegado

尝试:

docker-compose down

销毁任何已在运行的环境。

在经历了太多挫折之后,我在我损坏的phabricator容器中解决了这个问题:

您必须知道http pid文件的名称/路径是什么。在下面的示例中,它位于容器内的/run/apache2/apache2.pid。一旦你有了它,你就运行以下程序:

docker start [container_id]; docker exec [container_id] rm /run/apache2/apache2.pid

这样做的目的是启动容器,然后立即尝试运行命令来删除PID文件——希望在应该启动的任何进程docker有时间失败之前。如果您的容器进程失败得很快,这可能对您不起作用。试着跑几次,你可能会把它打得落花流水。

为了找到PID文件的位置,我做了类似@sebelk的操作,但我没有扩展tar文件,而是通过列出其内容并查找正确的文件名来节省一些时间。。。像这样:

docker export [container_id] > /tmp/brokecontainercontents.tar
tar -tf /tmp/brokecontainercontents.tar | less 

这很愚蠢,而且可能有更好的方法来查看容器中的内容。理想情况下,您可以通过其他方式找到PID文件的名称(欢迎评论!)。

主显节

上面的答案很有用,但我现在意识到,我和这里的许多其他人从根本上误解了Docker。事实上,@styonsk下面被否决的答案是正确的。而且,@avijendr对此的批评性评论也是正确的:这会破坏容器中的数据——但这并不重要。我来解释。

我最初被告知Docker"像chroot,但更好"。这是真实的,但具有误导性。在chroot监狱中,你的数据生活在监狱里(当然是这样,否则被监禁的过程会怎么看?)。因此,当我开始使用Docker时,我认为Volumes功能是获取容器中数据的一种方式——你可以将Volume装载到本地系统,看看里面有什么。当我尝试时,我真的很生气,因为容器好像丢失了我所有的数据——容器应用程序就是这样做的,而本地装载的位置什么都没有!错了错了。

Docker中的卷将本地数据/文件装载到容器中,而不是相反。因此,当我将卷装载到一个空的本地目录(期望容器中的文件出现)时,空的本地文件夹被装载到容器中,隐藏了容器中存在的文件,使应用程序看起来像丢失了数据(好吧,因为它)。事实上,Docker容器甚至在没有安装Volume的情况下也能工作,这是一个副作用,可以说是一个有害的副作用。这不是它想要的工作方式。任何写入容器中卷位置的数据都应该是一次性的!

(顺便说一句,我是通过Kitematic开始使用Docker的,它将在一步中提取、创建和启动容器,而无需询问您想在哪里安装卷。我认为这是我错误想法的一部分……我现在个人认为,在您将卷安装到某个位置或明确决定不安装之前,它不应该启动容器。)

因此,Docker容器的预期用途通常(也应该)是在容器内部运行应用程序,该应用程序作用于容器外部的数据,即装载到本地系统的卷中。这意味着应该能够在容器出现问题时销毁容器,并启动另一个装载到同一卷的副本——您可以取回所有数据,因为它最初不在容器中。

因此,@styonsk的答案是正确的:如果你正确使用Docker,你应该能够摧毁容器并启动一个新容器。一方面,这听起来有些过头了,但另一方面,容器化应用程序的意义在于,你不必知道它内部发生了什么,而且可以说你不。。。你怎么知道在一次不干净的关闭后唯一坏掉的是httpd.pid文件还在那里?可能会有更多你不知道的混乱!可以说,这就是抽象的意义所在。

如果该模型不适用于您的用例,或者您根本不喜欢它,那么答案可能是您不应该使用Docker容器。这也不是一件坏事,只是你可能试图用菲利普斯螺丝刀拧一个平头螺丝。您可能只需要一个轻量级但全栈的VM环境。

重建/重新创建可能会有所帮助。docker-compose up --build --force-recreate <service-name>

此外,主机(物理服务器)可能没有剩余的磁盘空间。

您不需要销毁容器。由于你没有正确地停止容器,仍然有碎片挂在周围。具体地说,网络仍然连接到容器。

尝试:docker network list

你会看到这样的东西:

NETWORK ID          NAME                             DRIVER              SCOPE
3d8f4b8ce4e5        bridge                           bridge              local
5ec8cb6bbe44        folderNameOfContainer_default    bridge              local
2503d2978229        host                             host                local

然后你所需要做的就是断开连接:

docker network disconnect folderNameOfContainer_default my_container_name

docker-compose down也可以,但严格来说没有必要。

根据Paul的评论和docker文档,我找到了解决方案:

docker export sharp_shockley > /tmp/sharp_shockley.tar
mkdir /tmp/sharp_shockley
cd /tmp/sharp_shockley/
tar xvf sharp_shockley.tar
rm run/httpd/httpd.pid
rm sharp_shockley.tar
tar -c . | sudo docker import - apache3

然后,我必须执行一些小修复,删除/var/run/httpd上的临时文件,提交更改,然后我可以重新启动我的容器。

更多信息,请访问https://docs.docker.com/reference/commandline/cli/#importDocker命令行

我不是Docker专家,但清除容器的缓存(用于本地网站)就成功了。

这是将httpd作为容器运行时常见的问题,

  • 为了避免这个错误,请确保httpd在后台运行(-D FOREGROUND),在Dockerfile中包含以下行

CMD["/usr/sbin/httpd","-D","前景"]

  • 重新启动docker,然后重试注意:停止所有集装箱

  • 此问题是否仅在提交之后发生?然后按照以下步骤,

  1. 创建docker文件

  2. 构建图像

  3. 运行容器

  4. 停止集装箱

  5. 使用停止的容器(id)提交

因此,如果容器已经停止,httpd进程(pid 1)将不会运行。

不知何故,只向下对我不起作用。到目前为止,对我来说最好的解决方案是制作一个bash文件,如下所示。我自己测试了很多次,它做到了需要的破解。

#!/usr/bin/env bash
# chmod +x start_dockers.sh
# ./start_dockers.sh
sudo docker-compose down
#stop all containers
sudo docker stop $(docker ps -aq)
sudo docker-compose up --build

相关内容

最新更新