RUN
RUN有两种形式:
RUN<command>
(shell形式,命令会在shell中被执行,在Linux中默认为/bin/sh -c
,或者cmd /S /C
在Windows当中)RUN ["executable", "param1", "param2"]
(exec形式)
RUN
命令会执行任何指令在镜像的最上层并提交结果。产生的镜像会用在Dockerfile
的下一步
分层进行RUN
并且提交是Docker的核心思想,这样Docker可以从历史的任何一点进行创建容器,就像源代码控制一样。
exec形式可以避免shell下面的字符串混乱,这种形式同样可以去RUN
一下基础镜像的shell中不支持的指令。
默认的shell形式的shell可以通过SHELL
指令替换。
在shell形式中你可以利用\
(backslash)去继续编写一个多行的RUN指令。考虑下面的例子:
RUN /bin/bash -c 'source $HOME/.bashrc; \
echo $HOME'
与上面的两行相同的效果
RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME'
注意:如要使用其他形式的shell,而不是‘/bin/sh’。用exec形式传递你想要的shell进去。例子:RUN ["/bin/bash", "-c", "echo hello"]
注意:exec形式会被解析为一个JSON数组,意味着你需要使用双引号而不是单引号来指定指令。
注意:exec形式不同于shell形式,他不会启动一个命令行。意味着一般的shell处理是不会发生的。例如,RUN [ "echo", "$HOME" ]
的HOME
是不会发生变量替换的。如果你希望通过shell去处理一些事情时,你可以使用shell形式的RUN
或者直接执行一个shell,RUN [ "sh", "-c", "echo $HOME" ]
。当使用exec形式直接执行一个shell时和shell形式一样,他会是环境变量扩展的shell,而不是docker的。
注意:在JSON表单中,需要避免反斜杠。特别是在Windows系统当中,反斜杠是路径分隔符。下面的那行代码会被当做是一个shell形式的指令,因为不是一个合法的JSON串,并且会以不被期待的方式失败。RUN ["c:\windows\system32\tasklist.exe"]
这个示例的正确写法是:RUN ["c:\\windows\\system32\\tasklist.exe"]
。
在下一次build的时候RUN
指令的缓存是不会被自动清除的。一些指令的缓存,类似于RUN apt-get dist-upgrade -y
会在下次build的时候再次使用。如果你想要让他自动清除cache的话,使用--no-cache
标记,例如docker build --no-cache
。
可以看Dockerfile的最佳实践来获取更多信息。
RUN
指令产生的cache,可以被ADD指令所清除,想了解更多细节请看下面。