我目前正在研究 Docker Compose 设置,我想根据名为
ARG
的 CONTINUOUS_RUN
变量的值有条件地将 TTY(终端)分配给容器。具体来说,如果 CONTINUOUS_RUN
设置为 true
,我想分配一个 TTY (tty: true
),如果它设置为任何其他值或根本没有设置,我想禁用 TTY (tty: false
)。
这是我的 Docker Compose 文件的相关部分:
version: "3.8"
services:
my-service:
build:
context: .
dockerfile: Dockerfile
tty: ${CONTINUOUS_RUN:-false}
为了确保
CONTINUOUS_RUN
在需要时确实设置为 true
,我在 Dockerfile 中添加了一个验证步骤:
# Dockerfile
FROM python:3.11.5-alpine3.18
# Check if CONTINUOUS_RUN is true
ARG CONTINUOUS_RUN=true
我的期望是,此设置将根据
CONTINUOUS_RUN
的值有条件地分配 TTY,并且 Dockerfile 中的验证步骤将在需要时确认 CONTINUOUS_RUN
设置为 true
。
但是,我遇到了另一个问题:即使将
CONTINUOUS_RUN
设置为 true
,与分离容器 (-d
) 的交互模式也无法按预期工作。我无法与正在运行的容器交互。
即使
CONTINUOUS_RUN
设置为 true
,我的 Docker Compose 配置或 Dockerfile 中是否缺少某些内容,导致交互模式出现此问题?
运行容器时有两组不同的环境变量。像
tty:
这样的撰写设置仅考虑运行 .env
命令时主机的环境和主机 docker-compose
文件的内容;他们根本看不到图像的内容。相反,在容器内部,命令只能看到图像的 ENV
值以及 Compose environment:
和 env_file:
设置,而看不到主机环境。
Dockerfile
ARG
不进行任何类型的“验证”,并且它看不到主机环境的最终值是什么。在图像构建过程中,RUN
命令将看到一个环境变量CONTINUOUS_RUN
,它将有一个字符串值true
,除非Composebuild: { args: }
将其设置为不同的值。这一切都发生在考虑 build:
块之外的任何内容之前,并且很可能在有或没有附加 tty 的情况下运行同一个容器。
在问题的第一段中,您指定
CONTINUOUS_RUN
设置通过 Dockerfile ARG
内置到映像中。您无法像这样根据图像的内容真正设置 Compose 设置,并且通常在构建图像后很难读出 ARG
值。由于您正在描述两个单独的图像,因此您可能需要两个单独的 Compose 容器
services:
with-continuous-run:
build:
context: .
args:
CONTINUOUS_RUN: 'true'
tty: true
without-continuous-run:
build:
context: .
args:
CONTINUOUS_RUN: 'false'
您的容器也有可能直接检测是否存在 tty,而不将其构建到映像中。如果容器是使用 tty 启动的,则 shell 命令
test -t /dev/stdin
将返回 true(退出代码 0),否则返回 false(退出代码 1);您也许可以在代码中进行类似的测试。您可以在入口点包装脚本或程序设置中的某个位置执行此操作。这将允许您在两种情况下使用相同的图像,而无需特定的 ARG
。