博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
如何向 Docker 容器传递参数
阅读量:2435 次
发布时间:2019-05-10

本文共 2387 字,大约阅读时间需要 7 分钟。

原文:

我们在运行 docker 镜像时希望能用下面的命令向容器传递命令行参数

docker run <image-name> <command> arg1 arg2

docker run <image-name> arg1 arg2

其实只有第一种形式,紧随镜像名后那个总是一个命令,其后才是参数。如果要向 docker 容器传递参数时,Dockerfile 该如何写,这就有必要稍稍了解一下 Dockerfile 中  CMD 和 ENTRYPOINT 这两个指令,并且它们有 exec 和 shell 两种格式的写法。详情请见上篇 。

对于一个 docker 镜像,我们可以这么来理解  ENTRYPOINT 与 CMD 的关系

  1. 如果没有定义 ENTRYPOINT, CMD 将作为它的 ENTRYPOINT
  2. 定义了 ENTRYPOINT 的话,CMD 只为 ENTRYPOINT 提供参数
  3. CMD 可由 docker run <image> 后的命令覆盖,同时覆盖参数

对于 #1 和  #2 更精致的理解是容器运行的最终入口由 ENTRYPOINT 和实际的 CMD 拼接而成。ENTRYPOINT 和 CMD 需转换为实际镜像中的 exec 格式来拼接,合并后的第一个元素是命令,其余是它的参数。

举四个例子进行说明

一, 未定义 ENTRYPOINT, 定义了 CMD

#ENTRYPOINT []

CMD ["echo", "hello"]

实际入口是它们拼接后还是 CMD 本身,["echo", "hello"]

二, 定义了 ENTRYPOINT 和 CMD

ENTRYPOINT ["echo", "hello"]

CMD ["echo", "world"]

实际入口是它们拼接起来,形成 ["echo", "hello", "echo", "world"], 执行 docker run test 显示为 hello echo world

三, 定义了 ENTRYPOINT, CMD 由 docker run 提供

ENTRYPOINT  ["echo", "hello"]

执行命令 docker run <image> rm -rf /, 实际入口是由 ["echo", "hello"] 与 ["rm", "-rf", "/"] 拼接而成的 ["echo", "hello", "rm", "-rf", "/"], 输出为 hello rm -rf /。看到 rm -rf / 也不用担心,用 ENTRYPOINT 就是让人放心

注:ENTRYPOINT 同样可以被覆盖,如 docker run --entrypoint ls test -l /,将会执行 ls -l / 命令。

四, 如果 ENTRYPOINT 用 shell 格式定义的

ENTRYPOINT java -jar /app.jar

CMD ["hello", "world"]

通过 docker inspect 命令看到镜像中实际的 ENTRYPOINT 是

ENTRYPOINT ["/bin/sh", "-c", "java -jar /app.jar"]

所以与 CMD 连接起来的入口就是 ["/bin/sh", "-c", "java -jar /app.jar", "hello", "world"], "bin/sh" 直接忽略掉后面的 "hello" 与 "world",这就是为什么  shell 命令方式无法获取参数。

有了以上几点概念,以及四个实例作为感观认识后,想要怎么往容器传递参数应该很容易确定了。

未定义 ENTRYPOINT

没有定义 ENTRYPOINT 的镜像想怎么来就怎么来,docker run <image> 后面的输入你自己作主。

有定义 ENTRYPOINT

定义了 ENTRYPOINT 的镜像,则是 CMD 或 docker run <image> 后的输入作为  ENTRYPOINT 中命令的附加参数。再次提醒 shell 格式的 ENTRYPOINT 和 CMD  务必要转换为相应 exec  格式来理解。

shell 格式的 ENTRYPOINT

如果是复杂的 shell 命令不容易拆解出一个个参数,而希望用  shell 格式来定义 ENTRYPOINT 的话,也有办法。shell 格式的 ENTRYPOINT 是由 "/bin/sh -c" 启动的,而它是可以解析变量的。另一方面 CMD 或 docker run <image> 的输入第一个元素存成了 $0,其他剩余元素存为 $@, 所以 shell 格式的 ENTRYPOINT 可以这么写

ENTRYPOINT echo hello $0 $@

注:shell 中 $0 表示命令本身,$@ 为所有参数

这样执行下面 docker 命令将可获得所有的参数输入

$ docker run test world and China

hello world and China

如果只是按常规 shell 脚本来对待,想当然的写成

ENTRYPOINT echo hello $@

效果将是

$ docker run test world and China

hello and China

第一个参数将被丢失,docker run <image> 后第一个输入通常是一个命令,所以是 $0, 而 ENTRYPOINT 又希望它是一个普通参数,因此$0 $@ 要同时写上。

直接用 docker inspect <container-id> 查看

最简单且准确的方式就是直接用 docker inspect <container-id> 查看实际启动的命令及参数

转载地址:http://lslmb.baihongyu.com/

你可能感兴趣的文章
Cookie对象入门详解
查看>>
HashMap的remove()方法详解
查看>>
单例模式-分解步骤,逐步解析
查看>>
通过Form表单一次性拿到json格式数据,及后台接收
查看>>
## EL表达式与JSTL标签用法解读
查看>>
Mybatis异常:The content of elements must consist of well-formed.......(一般出现在写分页/带大于小于号的SQL)
查看>>
Mybatis光速入门(配置文件模块)
查看>>
关于Oracle的主键自增如何设置
查看>>
手撕HashMap的resize()方法源码渗透解析+图解
查看>>
Mybatis常见异常类型Could not set parameters for mapping离不开这个原因!
查看>>
Thymeleaf中一个页面怎么嵌套另一个页面,关于页面嵌套,标签告诉你应该知道的
查看>>
JAVA如何实现短信验证码--阿里云接口,新手式图文教学,个人项目有这一篇就够了
查看>>
Java中大小数BigDecimal的加减乘除用法及场景的详细介绍,看完不信你还会报Syntax error on token “+/-/*“, invalid AssignmentOperat异常
查看>>
UVa 10917 Dijkstra
查看>>
CF403B/CF402D
查看>>
CF402E / 403C
查看>>
cf404b
查看>>
cf404c
查看>>
cf404d
查看>>
武大网络预赛 Problem 1545 - I - Twenty-four
查看>>