Dockerfile的ENTRYPOINT和CMD都是用來定義命令的執(zhí)行入口象踊。
- 定義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指定的命令被調(diào)用了谨究。
- 定義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的行為是一樣的咕痛,沒有啥區(qū)分麻惶。
- 同時定義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被忽略宪拥。
- ENTRYPOINT和CMD的兩種寫法
4.1 SHELL
格式:<ENTRYPOINT|CMD> executable param1 param2 ...
4.2 EXEC
格式:<ENTRYPOINT|CMD> ["executable", "param1", "param2", ...]
- 使用EXEC的方式重新執(zhí)行上面三個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]
看到?jīng)]有5.3這里和前面使用SHELL格式的有重大不一樣仿野,CMD的內(nèi)容被作為參數(shù)傳遞給了ENTRYPOINT,雖然目前ENTRYPOINT沒有用到她君,但是我們知道就可以用了脚作。
- 使用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]
- 總結(jié)
7.1. ENTRYPOINT和CMD都可以用來指定容器的入口命令。
7.2 ENTRYPOINT具有優(yōu)先權(quán)
- 如果定義了ENTRYPOINT缔刹,那么執(zhí)行ENTRYPOINT球涛,忽略CMD
- 如果沒有定義ENTRYPOINT,那么執(zhí)行CMD校镐;如果CMD也沒有則失敗亿扁。
7.3 在EXEC模式下,CMD會被作為ARG[1]傳遞給ENTRYPOINT
- 這樣ENTRYPOINT可以決定是否調(diào)用CMD的內(nèi)容鸟廓。
- 在SHELL模式下則不會从祝。
- 如果沒有ENTRYPOINT,如前所述引谜,則CMD直接被執(zhí)行了牍陌。
7.3 docker run的時候如果后面指定命令,那么這個命令是CMD的替換员咽。
- 規(guī)則遵從CMD的處理流程毒涧。
7.4 因此建議ENTRYPOINT和CMD均采用EXEC的調(diào)用方式
- 這樣CMD的內(nèi)容可以被ENTRYPOINT調(diào)用,而且
- 原始CMD的內(nèi)容可以在命令行被替換贝室。
完整例子:
$ 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
- EXEC模式的缺陷
8.1 EXEC不能使用環(huán)境變量
例如在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}]
這個環(huán)境變量$VAR沒有被替換掉契讲,而是源文本的方式穿下去了。
解決這個問題的辦法使用"bash -c"來調(diào)用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]