0

我遇到的问题是all目标依赖于设置变量的其他目标,然后运行匹配的依赖项。

结果- 它将运行第一个依赖项然后停止。

预期- 运行两个依赖项,在每次运行之间正确设置变量

是否make足够聪明,可以看到pull并且build已经运行并且依赖目标本身没有执行,因此它认为所有依赖都是完整的?还是我只是make以不应该使用的方式滥用?

makefile

repo=rippio
image=default

pull:
    @docker pull $(repo)/$(image):latest

build: pull
    @sed -e 's/{{repo}}/$(repo)/' -e 's/{{image}}/$(image)/' Dockerfile.in > Dockerfile && \
    docker build -t=$(repo)/$(image):custom .
    @rm -f Dockerfile

node: image=node
node: | pull build

jdk8: image=jdk8
jdk8: | pull build

all: | node jdk8

TLDR

它用于:

  1. 拉取最新的 docker 镜像
  2. 对它运行一个通用设计的 Dockerfile 来定制它
  3. 将其标记为 :custom 供内部使用

以通用方式自定义图像非常方便,无需管理许多Dockerfiles.

Dockerfile 模板 ( Dockerfile.in),如果有兴趣:

FROM {{repo}}/{{image}}:latest

... super secret sauce

更新(答案)

感谢@GM,最终得到:

IMAGE_NAMES := node jdk8
TARGETS     := $(patsubst %,build-%,$(IMAGE_NAMES))

repo=rippio

all: $(TARGETS)

build-%: pull-%
        @$sed -e 's/{{repo}}/$(repo)/' -e 's/{{image}}/$*/' Dockerfile.in > Dockerfile-$* && \
        $docker build -f=Dockerfile-$* -t=$(repo)/$*:custom .
        @rm -f Dockerfile-$*

pull-%:
        @$docker pull $(repo)/$*:latest

这允许:

  • 轻松维护不断增长的“所有”目标
  • 通过并行运行make -j(注意Dockerfile-$*文件模式)
  • 比以前漂亮多了
4

2 回答 2

2

如果您长期绘制依赖关系图,您会发现有多个路径从andallpulland build—— 通过nodeand中的每个路径jdk8。但是,通过一条路径make到达/更新后,将假定它们都是最新的,因此,无需费心进一步更新它们——无论对目标特定变量的任何更改。pullbuild

我认为使用模式规则可能更容易实现您正在尝试做的事情(假设我理解正确)。

IMAGE_NAMES := node jdk8
TARGETS     := $(patsubst %,build-%,$(IMAGE_NAMES))

repo=rippio

all: $(TARGETS)

build-%: pull-%
        @$sed -e 's/{{repo}}/$(repo)/' -e 's/{{image}}/$*/' Dockerfile.in > Dockerfile && \
        $docker build -t=$(repo)/$*:custom .
        @rm -f Dockerfile

pull-%:
        @$docker pull $(repo)/$*:latest

注意: 您当前的所有build配方都使用相同的输入/输出文件DockerFile。如果您想使用并行构建,这将导致问题 -make -j等等。如果可能的话,使用模式规则匹配的词干来唯一标识输出文件可能是明智的。

于 2018-06-22T09:41:30.770 回答
1

通常,如果您使用以下命令调用 make:

make all

如果pull, build, node,jdk8都不是现有文件,则 make 应该构建pullbuild. 如果您只看到pull正在制作,那可能是因为您在没有指定目标的情况下调用了 make。在这种情况下, make 构建它在 Makefile 中找到的第一个目标(pull在您的情况下)。

无论如何,你的 Makefile 中有几个奇怪的方面:你对看起来像假目标的东西使用了仅订单的先决条件,而这些假目标没有被声明为这样。

我不确定我是否完全理解您正在尝试做的事情,但也许这样的事情会是一个很好的起点:

repo=rippio
image=default

.PHONY: all build node jdk8

all: node jdk8

node: image = node
jdk8: image = jdk8

build node jdk8:
    @docker pull $(repo)/$(image):latest && \
    sed -e 's/{{repo}}/$(repo)/' -e 's/{{image}}/$(image)/' Dockerfile.in > Dockerfile && \
    docker build -t=$(repo)/$(image):custom . && \
    rm -f Dockerfile

注意:如果不build命名默认目标default,您甚至可以进一步简化:

repo=rippio

.PHONY: all default node jdk8

all: node jdk8

default node jdk8:
    @docker pull $(repo)/$@:latest && \
    sed -e 's/{{repo}}/$(repo)/' -e 's/{{image}}/$@/' Dockerfile.in > Dockerfile && \
    docker build -t=$(repo)/$@:custom . && \
    rm -f Dockerfile
于 2018-06-22T08:35:05.987 回答