Docker与Make:构buildDockerfile上的图像变化

我和Docker一起玩,并制作实用程序,并尝试编写仅在Dockerfile更改时重新创buildDocker镜像的规则。
我的项目结构如下所示:

tree . . ├── Dockerfile ├── Makefile └── project └── 1.js 

我的Dockerfile非常简单:

 FROM ubuntu RUN apt-get update RUN apt-get install -y curl RUN curl -sL https://deb.nodesource.com/setup | sudo bash - RUN apt-get update RUN apt-get install -y build-essential nodejs VOLUME ["/project"] ENTRYPOINT ["cat"] CMD ["project/1.js"] 

它只是使用nodejs安装创build简单的ubuntu镜像,并从共享目录运行脚本。

现在我想从Makefile运行这个图像。 当我更改Dockerfile时,我想重build图像。 Makefile看起来像:

 default: run run: build docker run -v $(CURDIR)/project:/project app-server build: Dockerfile docker build -t app-server . 

现在当我执行sudo make命令时,它每次都重build一个图像。

只有当Dockerfile发生变化时,我如何才能强制执行构build任务?

当你写:

 run: build docker run -v $(CURDIR)/project:/project app-server 

在一个makefile文件中,期望这个配方将会以run的名字创build一个文件。 make会根据文件的先决条件文件的时间戳来检查文件的时间戳,以确定下一次是否需要运行配方。

与您的makefile中的build目标类似。

 build: Dockerfile docker build -t app-server . 

但是这些食谱都不是用目标的名字来创build文件。 这意味着make不能使用该文件的时间戳来确定是否需要重新运行配方。 因为这样做必须假定它需要重新运行配方(因为否则将意味着规则永远不会运行)。

如果你运行make -rRd你会看到什么让思考进行,你应该看到我刚刚说的。

因此,解决您的问题的方法是在每个目标中创build标记文件。

简单地添加touch $@ (可选地,前缀为@以使默认的默认回显命令运行)到每个目标应该足以让你的工作。

也就是说,将sudo放在每个需要它的配方行上,而不是使用sudo运行make ,如果你不希望邮戳文件也作为root用户,这可能是有道理的。

为了logging,这在GNU Make手册中作为4.8 Empty Target Files to Record Events

你的“目标” default runbuild是“假的”目标。 这是一个抽象的概念,而不是一个真实的文件。 这种虚假的目标,不应该有一个配方(因为你不能让他们)。 他们应该依靠真实的文件,或者其他的假目标等等,但是所有的东西最终都只能依赖真实的文件。

你的假目标应该被标记为这样

 .PHONY: default run build 

另一方面,真正的目标应该有一个配方 – 配方使目标。

所以,首先取决于你的虚假目标,没有配方,在一个真正的目标(S)。

然后有真正的目标有食谱。

我已经在makefile强制库依赖性sorting中发布了一些指导