Docker RUN命令:何时组命令,什么时候不?
我已经看到在Dockerfile
中使用RUN
命令的两种截然不同的方法,我将命名为v1和v2。
V1
每行一个命令
FROM ubuntu/latest ENV DEBIAN_FRONTEND noninteractive RUN apt-get update RUN apt-get -y install php5-dev RUN libcurl4-openssl-dev ...
V2
每行多个命令
FROM ubuntu/latest ENV DEBIAN_FRONTEND noninteractive RUN apt-get update && \ apt-get -y install \ php5-dev \ libcurl4-openssl-dev ...
两种方法都有其优点,使用caching的方法是最明显的。 还有什么其他原因可以使用另一种方法呢?
如果这个问题被认为太模糊或有意见,我会鞠躬社会的意愿; 不过,我把它张贴在这里,因为我认为有好的情况下组合命令,好的情况下不 – 我想知道他们是什么。
要回答这个问题,你必须首先理解“提交”的概念,以及Docker的caching。 最后,我提供一个经验法则供您使用。
提交
这是一个例子:
# Dockerfile FROM ubuntu/latest RUN touch /commit1 RUN touch /commit2
当你运行docker build .
,docker工作如下:
- 它从
ubuntu/latest
映像启动一个容器。 - 它运行容器中的第一个命令(
touch /commit1
),并创build一个新的图像。 - 它会重用#2中创build的映像来启动一个新的容器。
- 它运行第二个容器中的第二个命令(
touch /commit2
),并创build一个新的图像。
你需要在这里理解的是,如果你在一个单独的RUN
语句中分组命令,那么它们将全部在同一个容器中执行,并且将对应于单个提交。
相反,如果在单独的RUN
语句中将命令分解,则它们将不会在同一个容器中运行,以后的命令将重新使用先前命令创build的映像。
高速caching
当你运行一个docker build .
,docker工人重新使用之前创build的图像。 换句话说,如果你编辑了前面提到的Dockerfile,在最后包含了RUN touch /commit3
,并且运行了RUN touch /commit3
docker build .
,那么Docker会重用在#4中创build的映像。
这一点很重要,因为当你在你的Dockerfile中包含RUN apt-get update
,那么不能保证在RUN apt-get install php5
之前运行它几秒钟。
对于你所知道的, RUN apt-get update
的提交可能是在一个月前创build的。 APTcaching不再是最新的,但是Docker仍在重用这个提交。
经验法则
将所有内容分组在一个单独的RUN
命令中通常会比较容易,并且当您想要开始利用caching(例如,加速构build过程)时,就可以开始分解它们了。
当你这样做的时候,只要确保你不要分开必须在一定时间间隔内运行的命令(例如更新和升级)。
一个好的做法是避免命令的副作用(例如,在安装所需的软件包后清理APTcaching)。
结论
在你的例子中, v2
是正确的, v1
是错误的(因为cachingapt-get update
反作用)。
- 具有MACVLANnetworking的Docker Swarm容器得到错误的网关 – 没有互联网访问
- 如何获得Dockerrun.aws.json基于环境设置dynamicsourcePath?
- 我可以使用docker在Mac上安装ubuntu吗?
- Docker容器上的Spark包
- boot2docker – 运行docker version命令时尝试连接时发生错误
- 无法findTensorboard网站
- 主机客户端脚本从dockerized服务器脚本获取空string响应
- Docker:如何实现具有阶段性和生产性应用程序的工作stream程?
- 使用Postgresql Dockerizing Spring Boot应用程序