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
run
和build
是“假的”目标。 这是一个抽象的概念,而不是一个真实的文件。 这种虚假的目标,不应该有一个配方(因为你不能让他们)。 他们应该依靠真实的文件,或者其他的假目标等等,但是所有的东西最终都只能依赖真实的文件。
你的假目标应该被标记为这样
.PHONY: default run build
另一方面,真正的目标应该有一个配方 – 配方使目标。
所以,首先取决于你的虚假目标,没有配方,在一个真正的目标(S)。
然后有真正的目标有食谱。
我已经在makefile强制库依赖性sorting中发布了一些指导