AWS Batch如何覆盖容器命令?Bazel构建镜像命令覆盖异常
问题场景
用Bazel的py_image规则构建Docker镜像,指定了py_binary作为目标镜像的默认执行程序。将该镜像部署到AWS Batch时,尝试通过设置command = ["python"]覆盖默认命令,却出现错误:main.py: error: unrecognized arguments: python。但本地执行docker run --entrypoint python image:latest完全正常,这说明AWS Batch的命令覆盖逻辑和docker run --entrypoint不一样,想明确AWS Batch实际是怎么处理容器命令的。
参考的Bazel配置如下:
py_binary( name = "main", srcs = ["main.py"], data = [ ":config_files", ], deps = [ "//src/library/function", ], ) py_image( name = "image", binary = ":main", )
AWS Batch的命令处理逻辑
AWS Batch的command参数不是替换容器的ENTRYPOINT,而是追加到镜像默认ENTRYPOINT的后面作为参数。
Bazel的py_image构建出的镜像,其ENTRYPOINT指向的是封装好的main二进制脚本(本质是自动生成的、调用python main.py的启动脚本),镜像的CMD字段为空。所以当你在AWS Batch中设置command = ["python"]时,实际执行的命令是:
<镜像默认ENTRYPOINT> python
等价于本地执行:
docker run image:latest python
而非用--entrypoint替换入口的命令。这就导致main.py把python当成了额外的命令行参数,从而抛出未识别参数的错误。
本地用docker run --entrypoint python是直接替换了镜像的ENTRYPOINT,执行的是纯python命令,不会带上原来的main.py,因此没有问题。
解决办法
方法1:用AWS Batch的
entryPoint参数替换入口
AWS Batch支持单独配置entryPoint参数,把它设置为["python"],就能达到和本地docker run --entrypoint一样的效果,直接替换镜像默认的ENTRYPOINT,执行python交互环境或自定义脚本。方法2:修改Bazel的py_image配置,调整ENTRYPOINT和CMD
自定义py_image的entrypoint和cmd属性,把镜像的ENTRYPOINT设为["python"],CMD设为["main.py"]。修改后的配置示例:py_image( name = "image", binary = ":main", entrypoint = ["python"], cmd = ["main.py"], )此时镜像默认执行
python main.py,在AWS Batch中设置command参数会替换掉镜像的CMD值:比如设置command = ["custom_script.py"],实际执行python custom_script.py;如果要直接进入python交互环境,可设置entryPoint = ["python"]且command = []。方法3:在main.py中兼容参数逻辑(不推荐)
修改main.py的命令行解析逻辑,比如检测到特定参数时启动python交互环境。但这种方式耦合性高,仅适合特殊场景。
内容的提问来源于stack exchange,提问作者zhanga

