简体   繁体   English

docker 容器无法启动,因为现有的 pid 文件

[英]docker container won't start because an existing pid file

When I start a docker container it fails because an existing pid file:当我启动一个 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

How can I remove such a file, because I don't find it.我怎样才能删除这样的文件,因为我没有找到它。

[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

Try:尝试:

docker-compose down

To destroy any environments that are already running.销毁任何已经在运行的环境。

After way too much frustration, I solved this in my broke phabricator container:在经历了太多的挫折之后,我在我坏掉的 phabricator 容器中解决了这个问题:

You have to know what the name/path to the http pid file is.您必须知道 http pid 文件的名称/路径是什么。 In the example below it's at /run/apache2/apache2.pid inside the container.在下面的示例中,它位于/run/apache2/apache2.pid内的/run/apache2/apache2.pid Once you have that, you run the following:完成后,运行以下命令:

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

What this does is start the container and then immediately tries to run the command to delete the PID file--hopefully before whatever process docker is supposed to start has time to fail.这样做是启动容器,然后立即尝试运行命令来删除 PID 文件——希望在 docker 应该启动的任何进程有时间失败之前。 If your container process fails to quickly this might not work for you.如果您的容器进程快速失败,这可能对您不起作用。 Try running it a few times and you might beat it to the punch.尝试运行几次,您可能会击败它。

To find the location of my PID file, I did something similar to @sebelk, but instead of expanding the tar file I saved some time by just listing its contents and looking for the right filename...like so:为了找到我的 PID 文件的位置,我做了一些类似于 @sebelk 的事情,但是我没有扩展 tar 文件,而是通过列出其内容并寻找正确的文件名来节省一些时间......像这样:

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

This is silly, and there's probably a much better way to look through the contents of the container.这很愚蠢,而且可能有更好的方法来查看容器的内容。 Ideally you can find out the name of the PID file some other way (comments welcome!).理想情况下,您可以通过其他方式找出 PID 文件的名称(欢迎评论!)。

Epiphany顿悟

The answer above is useful, but I now realize that I and many others here have misunderstood Docker at a fundamental level.上面的答案很有用,但我现在意识到我和这里的许多其他人从根本上误解了 Docker。 In fact, @styonsk's downvoted answer below is the correct one.事实上,@styonsk 在下面被否决的答案是正确的。 And, @avijendr's critical comment of it is also correct: that will destroy data in the container--but it shouldn't matter.而且,@avijendr 对它的批判性评论也是正确的:这会破坏容器中的数据——但这无关紧要。 I'll explain.我来解释一下。

I was originally told that Docker was "like chroot but better."最初有人告诉我 Docker “像 chroot 但更好”。 That's truthy but misleading.这是实话,但具有误导性。 In a chroot jail, your data lives inside the jail (of course it does, how else would the jailed process see it?).在 chroot jail 中,您的数据存在于 jail 中(当然是这样,否则被监禁的进程将如何看到它?)。 So when I started using Docker, I thought that the Volumes feature was a way to get at the data in the container--that you could mount the Volume to your local system and see what was in it.因此,当我开始使用 Docker 时,我认为 Volumes 功能是获取容器中数据的一种方式——您可以将 Volume 挂载到本地系统并查看其中的内容。 When I tried that I got really ticked off because it was as if the container LOST all my data--the container app acted that way, and there was nothing in the local mounted location!当我尝试这样做时,我真的很生气,因为就好像容器丢失了我所有的数据——容器应用程序就是这样运行的,并且本地安装位置没有任何东西! Wrong wrong wrong.错错错。

Volumes in Docker mount your local data/files into the container, not the other way around. Docker 中的卷将您的本地数据/文件挂载到容器中,而不是相反。 So, when I mounted the volume to an empty local directory (expecting the files in the container to appear), instead the empty local directory was mounted into the container, hiding the files that existed in the container and making the app look like it had lost its data (well, because it had ).因此,当我将卷安装到一个空的本地目录时(期望容器中的文件出现),而不是将空的本地目录安装到容器中,隐藏容器中存在的文件并使应用程序看起来像丢失了它的数据(嗯,因为它)。 In reality, the fact that the Docker container even works without a Volume mounted is a side effect, and arguably a harmful one.实际上,Docker 容器甚至在没有挂载 Volume 的情况下也能工作这一事实是一种副作用,可以说是有害的。 That's not the way its intended to work.这不是它的工作方式。 Any data that gets written to the Volume's location within the container is expected to be disposable!任何写入到容器内 Volume 位置的数据都应该是一次性的!

(Incidentally, I started using Docker via Kitematic, which will pull, create, and start a container in one step without asking where you want to mount your Volumes , which is part of what gave me the wrong idea I think...I now personally believe it shouldn't start the container until you've mounted the Volumes somewhere or explicitly decided not to do so.) (顺便说一句,我开始通过 Kitematic 使用 Docker,它将在一步中拉取、创建和启动一个容器,而无需询问您要将 Volumes 安装在哪里,这是我认为错误想法的部分原因...我现在个人认为,在您将卷安装到某处或明确决定不这样做之前,它不应该启动容器。)

So the intended use of a Docker container is usually (and should be) to run the application inside the container which acts on data outside the container, that is in the Volumes that are mounted through to your local system.因此,Docker 容器的预期用途通常是(并且应该是)在容器运行应用程序,该应用程序对容器数据进行操作,即通过挂载到本地系统的卷中的数据。 That means that you should be able to just destroy the container if something goes wrong with it and start another copy mounted to the same Volumes--you get all your data back because it wasn't in the container in the first place.这意味着您应该能够在容器出现问题时销毁容器并启动另一个安装到相同卷的副本 - 您可以取回所有数据,因为它首先不在容器中。

Therefore, @styonsk's answer is the right answer: if you're using Docker correctly, you should just be able to destroy the container and fire up a new one.因此,@styonsk 的答案是正确的答案:如果您正确使用 Docker,您应该能够销毁容器并启动一个新容器。 On the one hand this sounds like overkill, but on the other hand, the point of the containerized application is that you don't have to know what's going on inside it and arguably you don't...how do you know the only thing broken after an unclean shutdown is that the httpd.pid file is still there?一方面,这听起来有点矫枉过正,但另一方面,容器化应用程序的重点是您不必知道其中发生了什么,而且可以说您不知道……您怎么知道唯一的不正常关机后损坏的东西是 httpd.pid 文件仍然存在吗? There could be a lot more messed up that you don't know about!可能还有很多你不知道的乱七八糟的东西! That's arguably what the abstraction is for.这可以说是抽象的用途。

If that model doesn't work for your use case--or you simply don't like it--the answer is probably that you shouldn't be using a Docker container.如果该模型不适用于您的用例——或者您只是不喜欢它——答案可能是您不应该使用 Docker 容器。 That's not a bad thing either, it's just that you may be trying to put a flathead screw in with a Phillips driver.这也不是坏事,只是您可能试图用十字螺丝刀将平头螺丝拧入。 You may just need a lightweight but full-stack VM environment instead.您可能只需要一个轻量级但全栈的 VM 环境。

Rebuilding/recreating might help.重建/重建可能会有所帮助。 docker-compose up --build --force-recreate <service-name>

Also, the host (physical server) might have no disk space left.此外,主机(物理服务器)可能没有剩余的磁盘空间。

Based on Paul's comment and docker documentation I've found the solution:根据 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

Then I have to perform some minor fixes, remove temporary files on /var/run/httpd, commit the changes, and then I could start again my container.然后我必须执行一些小的修复,删除 /var/run/httpd 上的临时文件,提交更改,然后我可以重新启动我的容器。

More information at https://docs.docker.com/reference/commandline/cli/#import Docker Command Line更多信息请访问https://docs.docker.com/reference/commandline/cli/#import Docker 命令行

You shouldn't need to destroy the container.您不应该需要销毁容器。 Since you didn't properly stop the container, there's still pieces hanging around.由于您没有正确停止容器,因此仍有碎片。 Specifically, the network is still connected to the container.具体来说,网络仍然连接到容器。

try: docker network list尝试: docker network list

You'll see something like:你会看到类似的东西:

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

Then all you need to do is disconnect:然后你需要做的就是断开连接:

docker network disconnect folderNameOfContainer_default my_container_name

It's fine to docker-compose down too, but strictly speaking it isn't necessary. docker-compose down也可以,但严格来说没有必要。

我不是 Docker 专家,但是清除本地网站的容器的缓存可以解决问题。

somehow only down does not worked for me.不知何故,只有向下对我不起作用。 Best solution for me so far was make a bash file like given below.到目前为止,对我来说最好的解决方案是制作一个如下所示的 bash 文件。 tested many times myself it did the needed hack.我自己测试了很多次,它完成了所需的黑客攻击。

#!/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

This is a common issue occurs while running httpd as container,这是运行 httpd 作为容器时的常见问题,

  • To avoid this error make sure the httpd runs in background(-D FOREGROUND),include below line in your Dockerfile for the same.为避免此错误,请确保 httpd 在后台运行(-D FOREGROUND),在您的 Dockerfile 中包含以下行。

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

  • Restart the docker and try again NB: stop all containers重新启动 docker 并重试 注意:停止所有容器

  • Is this issue occuring only after the commit?这个问题只在提交后发生吗? then follow the below steps,然后按照以下步骤,

  1. Create docker file创建泊坞窗文件

  2. Build the image构建图像

  3. Run the container运行容器

  4. stop the container停止容器

  5. commit with the stopped container (id)使用停止的容器 (id) 提交

Thus the httpd process(pid 1) will not be running if the container is already stopped.因此,如果容器已经停止,httpd 进程(pid 1)将不会运行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM