如何在 docker 入口点内 运行 导出命令?

How to run an export command within the docker entrypoint?

我正在尝试将 Datadog APM 跟踪和日志收集集成到 python 应用程序 运行ning Docker。 在 Docker 文件中,我需要激活 conda 虚拟环境并导出一个环境 DD_AGENT_HOST.

FROM continuumio/miniconda3

WORKDIR /app

COPY src ./src
COPY application.yaml .
COPY wsgi.py .
COPY gunicorn.conf.py .
COPY logging.ini .

RUN conda env create -f application.yaml

SHELL ["conda", "run", "-n", "dd_venv", "/bin/bash", "-c"]

ENTRYPOINT ["conda", "run", "--no-capture-output", "-n", "dd_venv", "ddtrace-run", "gunicorn", "-c", "gunicorn.conf.py", "wsgi:app", "--preload"]

我能够 运行 使用上述 Docker 文件的应用程序。但是,应用程序需要导出 env DD_AGENT_HOST 才能与 Datadog 连接,并且必须通过 HTTP 请求检索 DD_AGENT_HOST 的值。

ENTRYPOINT ["conda", "run", "--no-capture-output", "-n", "dd_venv", "export DD_AGENT_HOST=$(wget <ip_ddress>)", "ddtrace-run", "gunicorn", "-c", "gunicorn.conf.py", "wsgi:app", "--preload"]

我尝试将导出命令添加到 ENTRYPOINT,这导致 Docker 运行 失败并出现错误 “导出 DD_AGENT_HOST=:未找到命令:。

完成此任务的正确方法是什么?

由于您是 运行 通过激活的 Conda 环境,因此应该可以将激活脚本添加到包含该命令的环境中。例如,这样的文件:

/path/to/envs/dd_venv/etc/conda/activate.d/env_vars.sh

#!/bin/sh

export DD_AGENT_HOST=$(wget <ip_address>)

参见the documentation on Saving Environment Variables

请注意,对于静态环境变量(例如,您知道 先验 的字符串),这些可以直接集成到您的 application.yaml 文件。参见 the documentation on Setting Environment Variables

我可以通过使用 shell 形式的 CMD 并结合导出环境变量的命令和启动应用程序的命令来解决这个问题。

CMD export DD_AGENT_HOST=$(wget <ip_address>); ddtrace-run gunicorn -c gunicorn.conf.py wsgi:app --preload

我必须添加 --no-capture-output 和 SHELL 才能将日志写入 sdoutstderr

SHELL ["conda", "run", "--no-capture-output", "-n", "dd_venv", "/bin/bash", "-c"]

您正试图在 ENTRYPOINT 行中投入大量内容;我会把它分解一点。

首先,您尝试 运行 的实际命令位于该行的末尾,我将该命令设为 Dockerfile CMD:

CMD ["gunicorn", "-c", "gunicorn.conf.py", "wsgi:app", "--preload"]

拥有一个实际的 CMD 在这里很有价值,主要是因为它很容易更换。如果您想仔细检查应用程序是否确实 运行 正在 Conda 环境中,或者环境是否设置正确,您可以 docker run --rm ... sh -c 'echo $DD_AGENT_HOST' 并且该命令将替换 CMD,但是仍然 运行 通过 ENTRYPOINT.

ENTRYPOINT 里有什么?你现在想做两件事,你可以写在脚本里:

#!/bin/sh
# entrypoint.sh

# 1. Set a dynamic environment variable
export DD_AGENT_HOST=$(wget <ip_ddress>)

# 2. Run whatever the command is, in the Conda environment,
# with the tracing wrapper.
exec conda run \
  --no-capture-output \
  -n dd_venv \
  ddtrace-run \
  "$@"

该脚本可以是图像的 ENTRYPOINT

COPY entrypoint.sh .           # should be executable on the host already
ENTRYPOINT ["./entrypoint.sh"] # must be JSON-array syntax

通常,您可以在该脚本中放入任何内容,只要脚本以 exec "$@" 或其上的某些变体结尾,脚本中的所有内容 运行s 在它传递之前都是有序的控制权交给 CMD.