将参数传递给 Docker 容器中的 Python argparse

Posted

技术标签:

【中文标题】将参数传递给 Docker 容器中的 Python argparse【英文标题】:Pass arguments to Python argparse within Docker container 【发布时间】:2018-02-25 00:23:32 【问题描述】:

我正在着手第一次尝试使用 docker 容器。我有一个调用几个 API 并解析文件的 python 脚本。该脚本为 API 的服务器 URL、API 密钥和要解析的文件的文件路径获取参数。我使用 argparse 在脚本中处理这些。

如何将这些传递到 Docker?我不想硬编码任何东西,因为我希望将此脚本交给需要定期运行并根据结果采取行动的工程师。

感谢您的帮助。我一直在搜索,但似乎建议将内容硬编码到 dockerfile 中 - 我希望用户能够在运行时将它们放入。或者也许我已经找到了答案,只是不明白......

如果我的术语不正确,我深表歉意 - 这是我第一次尝试使用 Docker。

【问题讨论】:

【参考方案1】:

这个答案有点晚了,但对于任何未来的读者来说,我想让它更多地针对所提出的问题,即关于 argparse。

@Chris 指出的基本思想就是它。实现该解决方案的一种方法是将参数传递给 docker run 命令本身中的image。然后这些参数将传递给您的ENTRYPOINT,从而传递给 python 脚本。

这些文件通常看起来像这样..

文件.py

​​>
import argparse
parser = argparse.ArgumentParser(description='Process some integers.')
parser.add_argument('pos', type=str, help='Example Positional Argument') # will be accesible under args.POS
parser.add_argument('--opt', type=str , help='Example Optional Argument') # will be accesible with args.OPT

args = parser.parse_args()

# do something with pos and OPT

如果没有 docker,你会以 python file.py --opt opt_val pos_val 运行这个文件(假设它在 pwd 中)

Dockerfile

FROM python:<your_tag>
COPY ./file.py ./ # Assuming your Dockerfile and file.py are in the same directory

# some custom build steps

ENTRYPOINT ["python","./file.py"]

Docker 构建和运行命令

你用这个构建:docker build --tag example:0.0.1 &lt;dir&gt;

下面显示了多行(为了更好的可读性)运行命令,

Docker 运行

docker run --rm \
   --name example.container \
   example:0.0.1 \
   --opt=opt_val \
   POS=pos_value

Docker 运行(powershell)

docker run --rm `
   --name example.container `
   example:0.0.1 `
   --opt=opt_val `
   POS=pos_value

所以这里有几点要记住:

Argparse 支持添加位置参数和可选参数,应相应地传递给docker run 命令中的image。 上面指出的解决方案有效,但不如 id 通常那样灵活。最好使用环境变量并通过os.environ() 访问脚本内部。 使用此解决方案,您无需将任何内容“硬编码”到 Dockerfile 中

【讨论】:

【参考方案2】:

Dockerfile内部,我使用CMD这样的命令:

FROM python:3
COPY ./app /app
WORKDIR /app
RUN pip install --upgrade pip
RUN pip install --no-cache-dir -r req.pip
CMD ["python","start.py","(api-url) ","(api-key)","(file-path)"]

注意每个参数/参数,用逗号分隔

如果使用标志,则需要拆分

CMD ["python","start.py","-u","(api-url) ","-k","(api-key)","-f","(file-path)"]

【讨论】:

【参考方案3】:

您执行此操作的方式取决于您使用 docker 的方式。如果你想在已经运行的容器中运行你的脚本,你可以使用 exec:

docker exec <yourContainerName> python <yourScript> <args>

或者,如果您有一个 docker 映像,其中您的脚本是 ENTRYPOINT,则您传递给 docker run 命令的任何参数都将添加到入口点。

所以,如果你的 docker 文件看起来像这样:

FROM yourbase
....
ENTRYPOINT <yourScript>

然后你可以通过运行容器本身来运行脚本:

docker run --rm <yourImageName> <args>

根据您在下面的评论,您似乎想要此选项。您应该更改 dockerfile 以指定

ENTRYPOINT ["python","./script.py"]

(而不是使用 CMD) 然后您可以通过以下方式运行:

docker run --rm <yourImageName>  -a API_KEY - f FILENAME -o ORG_ID

【讨论】:

所以我的python脚本是容器的原因。我在 Dockerfile 中只有:"CMD ["python","./script.py"]" 但我想传递 "-a API_KEY -f FILENAME -o ORG_ID" 可能需要提一下,您需要使用 exec 形式 ENTRYPOINT ["python","./script.py"] 而不是 shell 形式 ENTRYPOINT python ./script.py 才能将参数传播到 python 中。 @naeschdy 是的,这就是困扰我的地方。你是对的【参考方案4】:

假设你的命令在下面

python app.py "URL" "APIKEY" "filepath"

所以你会把你的 Dockerfile 放在下面的时尚

FROM python:3.6
WORKDIR /app
COPY app.py .
ENTRYPOINT ["python", "app.py"]

然后运行 ​​docker 容器的人会像下面那样做

docker run -v /home/tarun/project/filetoparse.yaml:/config.yaml <yourimagename> "URL" "APIKEY" /config.yaml

如果您想提供更大的灵活性,您甚至可以使用环境变量

docker run -v /home/tarun/project/filetoparse.yaml:/config.yaml -e APIKEY="XYZ" <dockerimage> "URL" /config.yaml

然后在你的脚本中你可以使用os.environ['APIKEY']阅读它

【讨论】:

以上是关于将参数传递给 Docker 容器中的 Python argparse的主要内容,如果未能解决你的问题,请参考以下文章

使用 docker run 命令将参数传递给 Dockerfile 中的 CMD

如何通过 docker run 将参数传递给 Shell 脚本

将参数传递给build.gradle

将命令行参数传递给在 Docker 中运行的 Java 应用程序(Spring Boot)

将参数传递给 build.gradle

docker run 参数说明