为什么 docker 容器立即退出
Why docker container exits immediately
我运行一个容器在后台使用
docker run -d --name hadoop h_Service
它很快就退出了。但是如果我 运行 在前台,它工作正常。我使用
检查日志
docker logs hadoop
没有错误。有什么想法吗?
DOCKERFILE
FROM java_ubuntu_new
RUN wget http://archive.cloudera.com/cdh4/one-click-install/precise/amd64/cdh4-repository_1.0_all.deb
RUN dpkg -i cdh4-repository_1.0_all.deb
RUN curl -s http://archive.cloudera.com/cdh4/ubuntu/precise/amd64/cdh/archive.key | apt-key add -
RUN apt-get update
RUN apt-get install -y hadoop-0.20-conf-pseudo
RUN dpkg -L hadoop-0.20-conf-pseudo
USER hdfs
RUN hdfs namenode -format
USER root
RUN apt-get install -y sudo
ADD . /usr/local/
RUN chmod 777 /usr/local/start-all.sh
CMD ["/usr/local/start-all.sh"]
开始-all.sh
#!/usr/bin/env bash
/etc/init.d/hadoop-hdfs-namenode start
/etc/init.d/hadoop-hdfs-datanode start
/etc/init.d/hadoop-hdfs-secondarynamenode start
/etc/init.d/hadoop-0.20-mapreduce-tasktracker start
sudo -u hdfs hadoop fs -chmod 777 /
/etc/init.d/hadoop-0.20-mapreduce-jobtracker start
/bin/bash
A docker 容器在其主进程完成时退出。
在这种情况下,它将在您的 start-all.sh
脚本结束时退出。我对 hadoop 的了解还不够,无法告诉您在这种情况下该怎么做,但是您需要在前台留下一些 运行ning 或使用进程管理器,例如 运行it 或 supervisord 运行 流程。
我认为如果您不指定 -d
,您一定是误认为它可以正常工作;它应该具有完全相同的效果。我怀疑您是使用稍微不同的命令或使用 -it
启动它的,这会改变一些事情。
一个简单的解决方案可能是添加如下内容:
while true; do sleep 1000; done
到脚本结尾。但是我不喜欢这样,因为脚本实际上应该监视它启动的进程。
(我应该说我从 https://github.com/sequenceiq/hadoop-docker/blob/master/bootstrap.sh 那里偷了那个代码)
这对我有用:
docker run -dit ubuntu
之后,我检查进程 运行 使用:
docker ps -a
用于再次附加容器
docker attach CONTAINER_NAME
提示:要在不停止容器类型的情况下退出:^P^Q
我想扩展或者我敢说,改进 camposer
提到的答案
当你运行
docker run -dit ubuntu
你基本上是 运行在后台以交互模式连接容器。
当您通过 CTRL+D 附加和退出容器时(最常用的方法),您停止了容器,因为您刚刚终止了使用上述命令启动容器的主进程。
利用已经 运行ning 的容器,我将分叉 bash 的另一个进程并通过 运行ning 获得伪 TTY:
docker exec -it <container ID> /bin/bash
由于图像是 linux,需要检查的一件事是确保容器中使用的任何 shell 脚本都具有 unix 行结尾。如果它们末尾有 ^M 那么它们就是 windows 行结尾。修复它们的一种方法是在 /usr/local/start-all.sh 上使用 dos2unix 将它们从 windows 转换为 unix。 运行 交互模式下的 docker 可以帮助解决其他问题。您可能有文件名拼写错误或其他内容。见 https://en.wikipedia.org/wiki/Newline
一个不错的方法是在后台启动您的进程和服务 运行 它们并在脚本末尾使用 wait [n ...]
命令。在bash中,等待命令强制当前进程:
Wait for each specified process and return its termination status. If n is not given, all currently active child processes are waited for, and the return status is zero.
我从 Sébastien Pujadas 那里得到了这个想法 start script for his elk build。
从最初的问题来看,你的开始-all.sh 看起来像这样......
#!/usr/bin/env bash
/etc/init.d/hadoop-hdfs-namenode start &
/etc/init.d/hadoop-hdfs-datanode start &
/etc/init.d/hadoop-hdfs-secondarynamenode start &
/etc/init.d/hadoop-0.20-mapreduce-tasktracker start &
sudo -u hdfs hadoop fs -chmod 777 /
/etc/init.d/hadoop-0.20-mapreduce-jobtracker start &
wait
我的做法是在Dockerfile中启动一个shell不会立即退出CMD [ "sh", "-c", "service ssh start; bash"]
,然后运行docker run -dit image_name
。这样 (ssh) 服务和容器就启动了 运行ning.
每当我希望容器在完成脚本执行后保持运行时,我添加
&& tail -f /dev/null
在命令结束时。所以应该是:
/usr/local/start-all.sh && tail -f /dev/null
添加
exec "$@"
在我的 shell 脚本的末尾是我的修复!
有很多方法可以使 docker 立即退出。对我来说,这是我 Dockerfile
的问题。该文件中有一个错误。我有 ENTRYPOINT ["dotnet", "M4Movie_Api.dll]
而不是 ENTRYPOINT ["dotnet", "M4Movie_Api.dll"]
。如您所见,我在最后漏掉了一个引号 (")。
为了分析问题,我启动了我的容器并快速附加了我的容器,这样我就可以看到确切的问题是什么。
C:\SVenu\M4Movie\Api\Api>docker start 4ea373efa21b
C:\SVenu\M4Movie\Api\Api>docker attach 4ea373efa21b
其中 4ea373efa21b 是我的容器 ID。这让我想到了实际问题。
发现问题后,我不得不重新构建、恢复、发布我的容器。
Why docker container exits immediately?
如果你想强制图像挂起(为了调试某些东西或检查文件系统的状态)你可以覆盖入口点以将其更改为 shell:
docker run -it --entrypoint=/bin/bash myimagename
将此添加到 Docker 文件的末尾:
CMD tail -f /dev/null
示例 Docker 文件:
FROM ubuntu:16.04
# other commands
CMD tail -f /dev/null
例如,如果您从容器中检查 Dockerfile
fballiano/magento2-apache-php
您会看到他在文件末尾添加了以下命令:
虽然真实;睡觉1;完成
现在,我建议您这样做
docker container ls --all | grep 127
然后,您将查看您的 docker 图像是否有错误,如果它以 0 退出,那么它可能需要这些将永远休眠的命令之一。
我在最后添加了 read
shell 语句。这样就保留了容器的主进程——启动shell脚本——运行.
来自重复项,我在这里看不到任何解决 运行 将您的主要工作负载作为后台作业的非常常见的反模式,然后想知道为什么 Docker 退出。
简单来说,如果你有
my-main-thing &
然后要么把&
去掉到运行前台的作业,要么加上
wait
在脚本末尾使其等待所有后台作业。
如果主要工作负载退出,它仍然会退出,所以可能 运行 在 while true
循环中强制它永远重新启动:
while true; do
my-main-thing &
other things which need to happen while the main workload runs in the background
maybe if you have such things
wait
done
(另请注意 while true
的写法。经常会看到像 while [ true ]
或 while [ 1 ]
这样的愚蠢的东西碰巧有效,但这并不意味着作者可能想象他们应该是这个意思。)
您需要 运行 它带有 -d 标志以使其 运行 宁作为后台守护进程。
docker run -d -it ubuntu bash
如果您只需要一个容器 运行ning 而不退出,只需 运行
docker run -dit --name MY_CONTAINER MY_IMAGE:latest
然后
docker exec -it MY_CONTAINER /bin/bash
你会在容器的bash
shell里面,应该不会退出。
或者如果退出发生在 docker-compose
期间,请使用
command: bash -c "MY_COMMAND --wait"
正如其他两个答案已经说明的那样(虽然没有明确提到 docker-compose,这就是为什么我仍然再次提到“等待”技巧)。
我运行一个容器在后台使用
docker run -d --name hadoop h_Service
它很快就退出了。但是如果我 运行 在前台,它工作正常。我使用
检查日志docker logs hadoop
没有错误。有什么想法吗?
DOCKERFILE
FROM java_ubuntu_new
RUN wget http://archive.cloudera.com/cdh4/one-click-install/precise/amd64/cdh4-repository_1.0_all.deb
RUN dpkg -i cdh4-repository_1.0_all.deb
RUN curl -s http://archive.cloudera.com/cdh4/ubuntu/precise/amd64/cdh/archive.key | apt-key add -
RUN apt-get update
RUN apt-get install -y hadoop-0.20-conf-pseudo
RUN dpkg -L hadoop-0.20-conf-pseudo
USER hdfs
RUN hdfs namenode -format
USER root
RUN apt-get install -y sudo
ADD . /usr/local/
RUN chmod 777 /usr/local/start-all.sh
CMD ["/usr/local/start-all.sh"]
开始-all.sh
#!/usr/bin/env bash
/etc/init.d/hadoop-hdfs-namenode start
/etc/init.d/hadoop-hdfs-datanode start
/etc/init.d/hadoop-hdfs-secondarynamenode start
/etc/init.d/hadoop-0.20-mapreduce-tasktracker start
sudo -u hdfs hadoop fs -chmod 777 /
/etc/init.d/hadoop-0.20-mapreduce-jobtracker start
/bin/bash
A docker 容器在其主进程完成时退出。
在这种情况下,它将在您的 start-all.sh
脚本结束时退出。我对 hadoop 的了解还不够,无法告诉您在这种情况下该怎么做,但是您需要在前台留下一些 运行ning 或使用进程管理器,例如 运行it 或 supervisord 运行 流程。
我认为如果您不指定 -d
,您一定是误认为它可以正常工作;它应该具有完全相同的效果。我怀疑您是使用稍微不同的命令或使用 -it
启动它的,这会改变一些事情。
一个简单的解决方案可能是添加如下内容:
while true; do sleep 1000; done
到脚本结尾。但是我不喜欢这样,因为脚本实际上应该监视它启动的进程。
(我应该说我从 https://github.com/sequenceiq/hadoop-docker/blob/master/bootstrap.sh 那里偷了那个代码)
这对我有用:
docker run -dit ubuntu
之后,我检查进程 运行 使用:
docker ps -a
用于再次附加容器
docker attach CONTAINER_NAME
提示:要在不停止容器类型的情况下退出:^P^Q
我想扩展或者我敢说,改进 camposer
提到的答案当你运行
docker run -dit ubuntu
你基本上是 运行在后台以交互模式连接容器。
当您通过 CTRL+D 附加和退出容器时(最常用的方法),您停止了容器,因为您刚刚终止了使用上述命令启动容器的主进程。
利用已经 运行ning 的容器,我将分叉 bash 的另一个进程并通过 运行ning 获得伪 TTY:
docker exec -it <container ID> /bin/bash
由于图像是 linux,需要检查的一件事是确保容器中使用的任何 shell 脚本都具有 unix 行结尾。如果它们末尾有 ^M 那么它们就是 windows 行结尾。修复它们的一种方法是在 /usr/local/start-all.sh 上使用 dos2unix 将它们从 windows 转换为 unix。 运行 交互模式下的 docker 可以帮助解决其他问题。您可能有文件名拼写错误或其他内容。见 https://en.wikipedia.org/wiki/Newline
一个不错的方法是在后台启动您的进程和服务 运行 它们并在脚本末尾使用 wait [n ...]
命令。在bash中,等待命令强制当前进程:
Wait for each specified process and return its termination status. If n is not given, all currently active child processes are waited for, and the return status is zero.
我从 Sébastien Pujadas 那里得到了这个想法 start script for his elk build。
从最初的问题来看,你的开始-all.sh 看起来像这样......
#!/usr/bin/env bash
/etc/init.d/hadoop-hdfs-namenode start &
/etc/init.d/hadoop-hdfs-datanode start &
/etc/init.d/hadoop-hdfs-secondarynamenode start &
/etc/init.d/hadoop-0.20-mapreduce-tasktracker start &
sudo -u hdfs hadoop fs -chmod 777 /
/etc/init.d/hadoop-0.20-mapreduce-jobtracker start &
wait
我的做法是在Dockerfile中启动一个shell不会立即退出CMD [ "sh", "-c", "service ssh start; bash"]
,然后运行docker run -dit image_name
。这样 (ssh) 服务和容器就启动了 运行ning.
每当我希望容器在完成脚本执行后保持运行时,我添加
&& tail -f /dev/null
在命令结束时。所以应该是:
/usr/local/start-all.sh && tail -f /dev/null
添加
exec "$@"
在我的 shell 脚本的末尾是我的修复!
有很多方法可以使 docker 立即退出。对我来说,这是我 Dockerfile
的问题。该文件中有一个错误。我有 ENTRYPOINT ["dotnet", "M4Movie_Api.dll]
而不是 ENTRYPOINT ["dotnet", "M4Movie_Api.dll"]
。如您所见,我在最后漏掉了一个引号 (")。
为了分析问题,我启动了我的容器并快速附加了我的容器,这样我就可以看到确切的问题是什么。
C:\SVenu\M4Movie\Api\Api>docker start 4ea373efa21b
C:\SVenu\M4Movie\Api\Api>docker attach 4ea373efa21b
其中 4ea373efa21b 是我的容器 ID。这让我想到了实际问题。
发现问题后,我不得不重新构建、恢复、发布我的容器。
Why docker container exits immediately?
如果你想强制图像挂起(为了调试某些东西或检查文件系统的状态)你可以覆盖入口点以将其更改为 shell:
docker run -it --entrypoint=/bin/bash myimagename
将此添加到 Docker 文件的末尾:
CMD tail -f /dev/null
示例 Docker 文件:
FROM ubuntu:16.04
# other commands
CMD tail -f /dev/null
例如,如果您从容器中检查 Dockerfile fballiano/magento2-apache-php
您会看到他在文件末尾添加了以下命令: 虽然真实;睡觉1;完成
现在,我建议您这样做
docker container ls --all | grep 127
然后,您将查看您的 docker 图像是否有错误,如果它以 0 退出,那么它可能需要这些将永远休眠的命令之一。
我在最后添加了 read
shell 语句。这样就保留了容器的主进程——启动shell脚本——运行.
来自重复项,我在这里看不到任何解决 运行 将您的主要工作负载作为后台作业的非常常见的反模式,然后想知道为什么 Docker 退出。
简单来说,如果你有
my-main-thing &
然后要么把&
去掉到运行前台的作业,要么加上
wait
在脚本末尾使其等待所有后台作业。
如果主要工作负载退出,它仍然会退出,所以可能 运行 在 while true
循环中强制它永远重新启动:
while true; do
my-main-thing &
other things which need to happen while the main workload runs in the background
maybe if you have such things
wait
done
(另请注意 while true
的写法。经常会看到像 while [ true ]
或 while [ 1 ]
这样的愚蠢的东西碰巧有效,但这并不意味着作者可能想象他们应该是这个意思。)
您需要 运行 它带有 -d 标志以使其 运行 宁作为后台守护进程。
docker run -d -it ubuntu bash
如果您只需要一个容器 运行ning 而不退出,只需 运行
docker run -dit --name MY_CONTAINER MY_IMAGE:latest
然后
docker exec -it MY_CONTAINER /bin/bash
你会在容器的bash
shell里面,应该不会退出。
或者如果退出发生在 docker-compose
期间,请使用
command: bash -c "MY_COMMAND --wait"
正如其他两个答案已经说明的那样(虽然没有明确提到 docker-compose,这就是为什么我仍然再次提到“等待”技巧)。