Docker with make: build image on Dockerfile change



我在玩Docker,制作实用程序,并尝试编写规则,该规则仅在Dockerfile更改时重建Docker映像
我的项目结构看起来像:

 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的情况下创建简单的ubuntu映像,并从共享目录中运行脚本。

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

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

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

如何在Dockerfile发生更改时才强制make执行构建任务?

编写时:

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

在makefile中,make期望该配方将创建一个名为run的文件。make将根据其先决条件文件的时间戳检查该文件的时间标记,以确定下次是否需要运行该配方。

与makefile中的build目标类似。

build: Dockerfile
        docker build -t app-server .

然而,这两个配方都不会创建具有目标名称的文件。这意味着make不能使用该文件的时间戳来确定是否需要重新运行配方。因此,make必须假设它需要重新运行配方(因为如果不这样做,则意味着规则永远不会运行)。

如果你运行make -rRd,你会看到make的想法,你应该看到我刚才说的内容。

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

只需向每个目标添加touch $@(可选地以@为前缀,以使其运行的命令的默认make回显静音)就足以让它为您工作。

话虽如此,如果您不希望stamp文件也作为root拥有,那么将sudo放在每个需要它的配方行上可能是有意义的,而不是使用sudo运行make

为了记录在案,这在GNU Make手册中作为4.8 Empty Target Files to Record Events节进行了讨论。

您的"目标"default runbuild是"虚假"目标。这是一个抽象的概念,而不是一个真实的文件。这种虚假的目标,不应该有一个配方(因为你做不到)。相反,它们应该依赖于真实的文件,或者其他虚假的目标,等等,但一切最终都必须只依赖于真实文件。

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

.PHONY: default run build

另一方面,真正的目标应该有一个配方——配方就是目标。

因此,首先,在没有配方的情况下,将你的虚假目标依赖于真实目标。

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

我在上发布了一些指南makefile强制库依赖排序

最新更新