AWS Batch 提供了简单有效的方式来运行 Docker 镜像,在单纯执行一个计算任务时比 ECS 使用起来要方便许多。AWS Batch 在提交任务时可以执行 command
, environment
和 parameters
, 那么它将如何传递那些参数给 Docker 容器呢?
首先看一下提交任务的脚本
1 2 3 4 5 |
aws batch submit-job \ --job-name test-job \ --job-queue test-job-queue \ --job-definition test-job-definition \ --container-overrides='command=echo,hello,environment=[{name=JAVA_OPTS,value=-Xmx4G}]' |
注:aws cli 命令参数中有 -
时需要用 --parameters='--name=Spring' 等号的格式
我们将用上面的脚本提交一个任务,然后用 docker inspect <container-id>
观察 Docker 容器收到了什么参数
也没什么意外的,inspect 容器后我们看到
1 2 3 4 5 6 7 8 9 10 |
"Config": { ....... "Env": [ ...... "JAVA_OPTS=-Xmx4G", ], "Cmd": [ "echo", "hello" ], |
这个 Cmd 将与我们定义的 ENTRYPOINT 构成完整的执行入口,也可以从容器的 inspect 中看到
1 2 3 4 5 6 7 |
"Path": "/bin/sh", "Args": [ "-c", "java $JAVA_OPTS -jar /app.jar $0 $@", "echo", "hello" ], |
基于我们在 Dockerfile 中是下面那么定义的 ENTRYPOINT
ENTRYPOINT java $JAVA_OPTS -jar /app.jar $0 $@
很明显,虽然 AWS Batch submitJob 有一个 --parameters
那样的参数(后面会讲到),但实际要向应用传递参数的办法还是必须依赖于 Job definition 的 Environment 中的 Command
或者是提交任务时定义在 --container-overrides='command=param1,param2
进 Job definition 中的 Command 进行覆盖。
那么提交任务的 --parameters
是什么呢?它其实与 Docker 容器本身没有关系,只是用来替换 Job definition 中的占位符,所以 --parameters
后的参数是一个 map。
关于 --parameters
的用法应该看官方的这两篇文章:Using Parameter Substitution 和 AWS Batch Parameters。大致介绍的是在 command 中使用 Ref::codec
作为占位符,然后传参的时候用
"parameters": {"codec": "mp4"}
用下面的脚本提交任务后
1 2 3 4 5 6 |
aws batch submit-job \ --job-name test-job \ --job-queue test-queue \ --job-definition test-definition \ --parameters='app_name=default_app,is_debug=false' \ --container-overrides='command=[Ref::app_name,debug=Ref::is_debug],environment=[{name=JAVA_OPTS,value=-Xmx4G}]' |
docker inspect <container-id>
看到片断
1 2 3 4 5 6 7 8 9 10 11 12 13 |
"Path": "/bin/sh", "Args": [ "-c", "java $JAVA_OPTS -jar /app.jar $0 $@", "default_app", "debug=Ref::is_debug" ], ....... "Cmd": [ "default_app", "debug=Ref::is_debug" ], |
从上面看到 Ref::app_name 被替换成了 default_app, 而 debug=Ref::is_debug
未被替换,所以参数的替换必须是 command 中的一个完整参数,而不能为局部。
都不奏效,把 command 部分移到 Job 定义中也没有用。不过初步来看,有 command 来向 ENTRYPOINT 传递参数就足够了。
或是在 Job Definition 中预定好 Command 为 --name= Ref::app_name debug=Ref::is_debug
注意 --name= Ref::app_name
等号后的空格会把 --name=
和 Ref::app_name
分割成两个独立的参数,--parameters
只针对一个完整参数的替换。
然后只覆盖 parameters
1 2 3 4 5 6 |
aws batch submit-job \ --job-name yanbin-test-job \ --job-queue yanbin-test-queue \ --job-definition yanbin-test-definition \ --parameters='app_name=my_app_name,is_debug=false' \ --container-overrides='environment=[{name=JAVA_OPTS,value=-Xmx4G}]' |
Docker 容器启动后 inspect 它,看到的 Cmd 替换后的结果
"Cmd": [
"--name=",
"my_app_name",
"debug=Ref::is_debug"
],
总结:
AWS Batch 任务的参数还是要靠 Cmd(command) 来传递, Dockerfile 的 ENTRYPOINT 可以写成 shell 或 exec 两种格式
ENTRYPOINT java $JAVA_OPTS -jar /app.jar $0 $@
或者
ENTRYPOINT ["java", "-jar", "/app.jar"]
提交任务时通过
--container-overrides='command=param1,param2,param3'
来向 ENTRYPOINT 提供附加的参数,或是用 $0, $@ 来拾取全部的 command 作为参数。
而 --parameters
并不是真正干这个事的,它是启动容器之前的替换行为。
补充(2018-04-06)
更为严格的的 $0
和 $@
使用方式是就应该用引号括起来,即最终效果是
ENTRYPOINT java $JAVA_OPTS -jar /app.jar "$0" "$@"
这参避免参数中含空格的问题,详细的解释请参见上一篇 如何向 Docker 容器传递参数 - 补充部分