如何检测容器中的交互式标志?

kes*_*Him 6 docker dockerfile

首先,这个问题是不是问题的副本在这里。我目前正在学习 docker,并且需要创建一个在容器开始时使用以下命令dockerfile安装tomcat和运行它的entrypoint命令:

以下是我的内容dockerfile

FROM ubuntu:latest

LABEL MAINTAINER="kesarling"

RUN apt update
RUN apt upgrade -y
RUN apt install apt-utils -y
RUN apt install maven gradle -y
RUN apt install wget tar zip unzip openjdk-14-jdk -y

RUN mkdir /usr/local/apache-tomcat-v8.5.55
RUN wget http://www-us.apache.org/dist/tomcat/tomcat-8/v8.5.55/bin/apache-tomcat-8.5.55.tar.gz -O /tmp/apache-tomcat-v8.5.55.tar.gz
RUN cd /tmp && tar xvfz apache-tomcat-v8.5.55.tar.gz
RUN cp -Rv /tmp/apache-tomcat-8.5.55/* /usr/local/apache-tomcat-v8.5.55/

RUN mkdir /usr/local/spring-v5.2.6
RUN wget https://repo.spring.io/release/org/springframework/spring/5.2.6.RELEASE/spring-5.2.6.RELEASE-dist.zip -O /tmp/spring-v5.2.6.zip
RUN cd /tmp && unzip spring-v5.2.6.zip
RUN cp -Rv /tmp/spring-framework-5.2.6.RELEASE/* /usr/local/spring-v5.2.6/



RUN cd ~
RUN touch server-start.sh
RUN echo "#!/bin/sh" | cat > server-start.sh
# start of condition
RUN echo 'bash -c "/usr/local/apache-tomcat-v8.5.55/bin/catalina.sh run&"' | cat >> server-start.sh
RUN echo "/bin/bash" | cat >>server-start.sh
# end of condition
RUN chmod +x server-start.sh

EXPOSE 8080

ENTRYPOINT [ "./server-start.sh" ]
Run Code Online (Sandbox Code Playgroud)

当服务器作为后台进程启动时,只有当我给出-it标志时它才能正常运行。否则,正如预期的那样,容器在我分离它的那一刻就退出了。


所以,简而言之:

docker container run -it -p 8080:8080 <mydockername>
Run Code Online (Sandbox Code Playgroud)

有效但:

docker container run -dp 8080:8080 <mydockername>
Run Code Online (Sandbox Code Playgroud)

没有(如预期的那样)。这就是条件出现的地方。简而言之,我需要它来检测 docker 是在后台运行还是在交互模式下运行。


condition提到的blockdockerfile需要如下:

如果我使用-it标志执行它:

RUN echo 'bash -c "/usr/local/apache-tomcat-v8.5.55/bin/catalina.sh run&"' | cat >> server-start.sh
RUN echo "/bin/bash" | cat >>server-start.sh
Run Code Online (Sandbox Code Playgroud)

否则,如果我使用 -d 标志执行:

RUN echo 'bash -c "/usr/local/apache-tomcat-v8.5.55/bin/catalina.sh run"' | cat >> server-start.sh
Run Code Online (Sandbox Code Playgroud)

(注意/bin/bash已删除)


我该怎么做?

PS 这是我进入 docker 的第一周,所以请耐心等待我的 dockerfile :P

哦,更不用说搜索detect if the container has been run with an interactive flag没有带来任何有用的信息Google

BMi*_*tch 3

在构建时,您不会知道运行时环境会是什么样子。因此,无法RUN根据-it标志或缺少标志来修改语句,我们没有时间旅行来展望未来,并且同一图像可以使用不同的标志多次运行。

您可以在入口点脚本中执行此操作。/dev/stdin映射到交互式容器的哪个将根据您是否有、或两者都没有/proc/self/fd/0指向不同的事物:-i-it

$ docker run -it --rm busybox ls -al /dev/stdin
lrwxrwxrwx    1 root     root            15 Jun 18 14:43 /dev/stdin -> /proc/self/fd/0

$ docker run -it --rm busybox ls -al /proc/self/fd/0
lrwx------    1 root     root            64 Jun 18 14:43 /proc/self/fd/0 -> /dev/pts/0

$ docker run -i --rm busybox ls -al /proc/self/fd/0
lr-x------    1 root     root            64 Jun 18 14:50 /proc/self/fd/0 -> pipe:[9858991]

$ docker run --rm busybox ls -al /proc/self/fd/0
lrwx------    1 root     root            64 Jun 18 14:43 /proc/self/fd/0 -> /dev/null
Run Code Online (Sandbox Code Playgroud)

因此,如果您统计该链接以查看它/dev/null是否会出现,这将为您提供所问问题的答案。


旁注,如果您只关心-t,则可以运行另一个检查 shell,[ -t 0 ]例如:

$ docker run -it --rm busybox /bin/sh -c 'if [ -t 0 ]; then echo tty; else echo no tty; fi'
tty

$ docker run -i --rm busybox /bin/sh -c 'if [ -t 0 ]; then echo tty; else echo no tty; fi'
no tty

$ docker run --rm busybox /bin/sh -c 'if [ -t 0 ]; then echo tty; else echo no tty; fi'
no tty
Run Code Online (Sandbox Code Playgroud)

然而,docker 的最佳实践是在前台运行应用程序本身,作为 pid 1。如果您需要进入容器在开发环境中进行调试,请使用docker exec它。然后你的入口点变成:

ENTRYPOINT [ "/usr/local/apache-tomcat-v8.5.55/bin/catalina.sh", "run" ]
Run Code Online (Sandbox Code Playgroud)

通过这样做,您可以避免 pid 1 中出现额外的 shell,该 shell 可能会阻止容器停止信号正常停止应用程序。

然后要进行调试,您可以在运行后使用容器名称执行:

docker container run -dp 8080:8080 -n tomcat-app <mydockername>
docker container exec -it tomcat-app /bin/sh
Run Code Online (Sandbox Code Playgroud)