Docker with make:在Dockerfile上构建映像更改

时间:2014-09-30 10:15:52

标签: makefile docker

我玩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执行构建任务?

2 个答案:

答案 0 :(得分:10)

当你写:

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

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

与makefile中的build目标类似。

build: Dockerfile
        docker build -t app-server .

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

如果你运行make -rRd,你会看到make think会发生什么,你应该看到我刚才所说的内容。

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

只需添加touch $@(可选地以@为前缀,以使其运行的命令的默认回显)应该足以使其适用于您。

据说,如果你不想要邮票,那么将sudo放在需要它的每个食谱行上而不是用make运行sudo可能是有意义的文件也将作为root拥有。

对于记录,这在GNU制作手册中作为4.8 Empty Target Files to Record Events部分进行了讨论。

答案 1 :(得分:6)

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

你的虚假目标应该标记为

.PHONY: default run build

另一方面,真正的目标应该有一个配方 - 配方制定目标。

所以,首先要将你的虚假目标,没有食谱,放在真正的目标上。

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

我已经发布了一些指南 makefile enforce library dependency ordering