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

kha*_*iuk 6 makefile docker

我玩Docker并制作实用程序并尝试编写仅在Dockerfile更改时重建docker镜像的规则.
我的项目结构如下:

 tree .
.
??? Dockerfile
??? Makefile
??? project
    ??? 1.js
Run Code Online (Sandbox Code Playgroud)

我的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"]
Run Code Online (Sandbox Code Playgroud)

它只是通过nodejs安装创建简单的ubuntu映像,并从共享目录运行脚本.

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

default: run 

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

build: Dockerfile
        docker build -t app-server .
Run Code Online (Sandbox Code Playgroud)

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

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

Eta*_*ner 11

当你写:

run: build
        docker run -v $(CURDIR)/project:/project app-server 
Run Code Online (Sandbox Code Playgroud)

在makefile中,make期望该配方将按名称创建一个文件run.然后,make将检查该文件的时间戳与其先决条件文件的时间戳,以确定下次是否需要运行该配方.

build您在makefile中的目标类似.

build: Dockerfile
        docker build -t app-server .
Run Code Online (Sandbox Code Playgroud)

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

如果你跑步,make -rRd你将会看到让人想到的是什么,你应该看到我刚刚说过的话.

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

只需添加touch $@(可选择加上@默认值,使其默认运行命令的回显)到每个目标应该足以让它适合您.

这就是说,如果你不希望邮票文件也被拥有为root ,那么放上sudo需要它的每个配方行而不是运行它可能是有意义的.makesudo

对于记录,这将在GNU Make Manual中作为部分进行讨论4.8 Empty Target Files to Record Events.


Mar*_*eck 7

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

您的虚假目标应该标记为这样

.PHONY: default run build
Run Code Online (Sandbox Code Playgroud)

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

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

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

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