Dockerfile的ENTRYPOINT和CMD

Dockerfile的ENTRYPOINT和CMD都是用来定义命令的执行入口。

  1. 定义ENTRYPOINT
$ cat Dockerfile 
FROM oraclelinux
ADD ./docker-entry.sh   /docker-entry.sh
ENTRYPOINT /docker-entry.sh

$ cat docker-entry.sh
#!/usr/bin/env bash
echo "Entry of ENTRYPOINT, ARGS[#]=$#"
for ((i = 0; i <= $#; i++ )); do
  echo "ENTRYPOINT ARGS[${i}]=[${!i}]"
done

$ docker build -t testimage

$ docker run --rm testimage
Entry of ENTRYPOINT, ARGS[#]=0

在docker run的时候ENTRYPOINT指定的命令被调用了。

  1. 定义CMD
$ cat Dockerfile 
FROM oraclelinux
ADD ./docker-cmd.sh   /docker-cmd.sh
CMD /docker-cmd.sh

$ cat docker-cmd.sh
#!/usr/bin/env bash
echo "Entry of CMD, ARGS[#]=$#"
for ((i = 0; i <= $#; i++ )); do
  echo "CMD ARGS[${i}]=[${!i}]"
done

$ docker build -t testimage

$ docker run --rm testimage
Entry of CMD, ARGS[#]=0

这里看起来,ENTRYPOINT和CMD的行为是一样的,没有啥区分。

  1. 同时定义ENTRYPOINT和CMD
$ cat Dockerfile 
FROM oraclelinux
ADD ./docker-cmd.sh   /docker-cmd.sh
ADD ./docker-entry.sh   /docker-entry.sh
CMD        /docker-cmd.sh
ENTRYPOINT /docker-entry.sh

$ docker build -t testimage

$ docker run --rm testimage
Entry of ENTRYPOINT, ARGS[#]=0
  • 同时定义了ENTRYPOINT和CMD时,CMD被忽略。
  1. ENTRYPOINT和CMD的两种写法

4.1 SHELL
格式:<ENTRYPOINT|CMD> executable param1 param2 ...
4.2 EXEC
格式:<ENTRYPOINT|CMD> ["executable", "param1", "param2", ...]

  1. 使用EXEC的方式重新执行上面三个case

5.1 定义ENTRYPOINT

$ docker run --rm testimage
Entry of ENTRYPOINT, ARGS[#]=0

5.2 定义CMD

$ docker run --rm testimage
Entry of CMD, ARGS[#]=0

5.3 同时定义ENTRYPOINT和CMD

Entry of ENTRYPOINT, ARGS[#]=1
ENTRYPOINT ARGS[0]=[/docker-entry.sh]
ENTRYPOINT ARGS[1]=[/docker-cmd.sh]

看到没有5.3这里和前面使用SHELL格式的有重大不一样,CMD的内容被作为参数传递给了ENTRYPOINT,虽然目前ENTRYPOINT没有用到,但是我们知道就可以用了。

  1. 使用run自带命令

6.1 ENTRYPOINT + SHELL格式

$ docker run --rm testimage date
Entry of ENTRYPOINT, ARGS[#]=0
ENTRYPOINT ARGS[0]=[/docker-entry.sh]

6.2 CMD + SHELL格式

$ docker run --rm testimage date
Sun Dec 30 04:44:33 UTC 2018

6.3 ENTRYPOINT + CMD + SHELL格式

$ docker run --rm testimage date
Entry of ENTRYPOINT, ARGS[#]=0
ENTRYPOINT ARGS[0]=[/docker-entry.sh]

6.4 ENTRYPOINT + EXEC格式

$ docker run --rm testimage date
Entry of ENTRYPOINT, ARGS[#]=1
ENTRYPOINT ARGS[0]=[/docker-entry.sh]
ENTRYPOINT ARGS[1]=[date]

6.5 CMD + EXEC格式

$ docker run --rm testimage date
Sun Dec 30 04:47:12 UTC 2018

6.6 ENTRYPOINT + CMD + EXEC格式

$ docker run --rm testimage date
Entry of ENTRYPOINT, ARGS[#]=1
ENTRYPOINT ARGS[0]=[/docker-entry.sh]
ENTRYPOINT ARGS[1]=[date]
  1. 总结

7.1. ENTRYPOINT和CMD都可以用来指定容器的入口命令。
7.2 ENTRYPOINT具有优先权

  • 如果定义了ENTRYPOINT,那么执行ENTRYPOINT,忽略CMD
  • 如果没有定义ENTRYPOINT,那么执行CMD;如果CMD也没有则失败。

7.3 在EXEC模式下,CMD会被作为ARG[1]传递给ENTRYPOINT

  • 这样ENTRYPOINT可以决定是否调用CMD的内容。
  • 在SHELL模式下则不会。
  • 如果没有ENTRYPOINT,如前所述,则CMD直接被执行了。

7.3 docker run的时候如果后面指定命令,那么这个命令是CMD的替换。

  • 规则遵从CMD的处理流程。

7.4 因此建议ENTRYPOINT和CMD均采用EXEC的调用方式

  • 这样CMD的内容可以被ENTRYPOINT调用,而且
  • 原始CMD的内容可以在命令行被替换。

完整例子:

$ cat Dockerfile
FROM oraclelinux

ADD ./docker-cmd.sh     /docker-cmd.sh
ADD ./docker-entry.sh   /docker-entry.sh

ENTRYPOINT  [ "/docker-entry.sh" ]
CMD         [ "/docker-cmd.sh" ]

$ docker build . -t testimage

$ docker run --rm testimage
Entry of ENTRYPOINT, ARGS[#]=1
ENTRYPOINT ARGS[0]=[/docker-entry.sh]
ENTRYPOINT ARGS[1]=[/docker-cmd.sh]
$@=[/docker-cmd.sh]
Entry of CMD, ARGS[#]=0
CMD ARGS[0]=[/docker-cmd.sh]

$ docker run --rm testimage date
Entry of ENTRYPOINT, ARGS[#]=1
ENTRYPOINT ARGS[0]=[/docker-entry.sh]
ENTRYPOINT ARGS[1]=[date]
$@=[date]
Sun Dec 30 05:03:34 UTC 2018

$ docker run --rm testimage date "+%s"
Entry of ENTRYPOINT, ARGS[#]=2
ENTRYPOINT ARGS[0]=[/docker-entry.sh]
ENTRYPOINT ARGS[1]=[date]
ENTRYPOINT ARGS[2]=[+%s]
$@=[date +%s]
1546146222
  1. EXEC模式的缺陷

8.1 EXEC不能使用环境变量

例如在SHELL模式下:

$ cat Dockerfile
FROM oraclelinux

ADD ./docker-entry.sh   /docker-entry.sh

ENV VAR Hello

ENTRYPOINT  "/docker-entry.sh" "${VAR}"

$ docker run --rm testimage
Entry of ENTRYPOINT, ARGS[#]=1
ENTRYPOINT ARGS[0]=[/docker-entry.sh]
ENTRYPOINT ARGS[1]=[Hello]
$@=[Hello]

而同样的功能如果在EXEC模式下:

$ cat Dockerfile
FROM oraclelinux

ADD ./docker-entry.sh   /docker-entry.sh

ENV VAR Hello

ENTRYPOINT  [ "/docker-entry.sh", "${VAR}" ]

$ docker run --rm testimage
Entry of ENTRYPOINT, ARGS[#]=1
ENTRYPOINT ARGS[0]=[/docker-entry.sh]
ENTRYPOINT ARGS[1]=[${VAR}]
$@=[${VAR}]

这个环境变量$VAR没有被替换掉,而是源文本的方式穿下去了。

解决这个问题的办法使用"bash -c"来调用ENTRYPOINT指令:

$ cat Dockerfile
FROM oraclelinux

ADD ./docker-entry.sh   /docker-entry.sh

ENV VAR Hello

ENTRYPOINT  [ "/bin/bash", "-c", "/docker-entry.sh ${VAR}" ]

$ docker run --rm testimage
Entry of ENTRYPOINT, ARGS[#]=1
ENTRYPOINT ARGS[0]=[/docker-entry.sh]
ENTRYPOINT ARGS[1]=[Hello]
$@=[Hello]
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,458评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,030评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,879评论 0 358
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,278评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,296评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,019评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,633评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,541评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,068评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,181评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,318评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,991评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,670评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,183评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,302评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,655评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,327评论 2 358

推荐阅读更多精彩内容

  • Dockerfile 有两个启动配置, CMD 和 ENTRYPOINT , 可以在 Dockerfile 中来配...
    JaeGwen阅读 12,898评论 1 1
  • 透过别人的故事,看自己。首先,这个别人得是自己所欣赏的人,不然就没有写下去的意义了。 今天白杨师姐在“百人百天陪伴...
    颜妍陪你坚持阅读 545评论 2 2
  • 一首歌的时间,做一个“逃兵”。走过的路、读过的书、身体所经历过的疼痛,他们全都算数。细腻的心、乱飞的思绪,没心没肺...
    醬醬子阅读 235评论 0 0
  • 辛弃疾怀诗。 岳鹏举志词。 看宋朝、又上愁眉。 可叹未江山一统, 偏安地,国分离。 古史尽闻悲。 今人当谨思。 洞...
    西山有晴雪阅读 1,720评论 31 65
  • 让品清告诉大家为什么️这么爱三草这个品牌,并3年如一日坚持着我的热爱,坚持着我的分享❤️ 三草两木发展史️ 蟹老板...
    品微阅读 202评论 0 0