使用docker-compose构建公共依赖

dgtucam1  于 2023-04-20  发布在  Docker
关注(0)|答案(4)|浏览(208)

假设我有一组依赖于公共基础图像的图像:

  • base(这只是一组公共依赖项)
FROM ubuntu:16.04

ENV FOO 1
  • 儿童1
FROM mybaseimage  # where mybaseimage corresponds to base

CMD ["bar1_command"]
  • 儿童2
FROM mybaseimage  # where mybaseimage corresponds to base

CMD ["bar2_command"]

有没有可能创建docker-compose文件,在不运行它的情况下构建base?假设我有以下依赖项:

version: '2'
services:
    child1:
        build: ./path-to-child1-dockerfile
services:
    child2:
        build: ./path-to-child2-dockerfile
    depends_on:
        - child1

我希望构建base,即使它没有显式启动。这样的事情是否可能?或者我应该简单地使用外部Makefile来构建依赖项?

build_base:
    docker build -t mybaseimage mybaseimage  

build_all: build_base
    docker-compose build
nhn9ugyo

nhn9ugyo1#

这是可能的。有一种解决方法。您已经接近了,但是您缺少显式的图像标记(因此您几乎无法在子图像上声明您从哪个图像继承)。

version: '3.2'
services:
  base:
    image: mybaseimage
    build: ./path-to-base-dockerfile
  child1:
    build: ./path-to-child1-dockerfile
    depends_on:
      - base
  child2:
    build: ./path-to-child2-dockerfile
    depends_on:
      - base

假设您没有构建映像。您运行docker-compose up。将发生以下情况:

  • docker-compose看到child 1和child 2服务依赖于base。因此它将首先部署base。
  • docker-compose看到你还没有将任何图像标记为mybaseimage。它知道如何构建mybaseimage(你给了它一个构建路径),所以它现在将构建它,并将其标记为mybaseimage
  • docker-compose部署base服务。
  • 理想情况下,您应该设计base,以便它立即退出,或者没有入口点。
  • docker-compose考虑部署child 1和child 2
  • docker-compose看到你还没有将任何图像标记为child1。它知道如何构建child1(你给了它一个构建路径),所以它现在将构建它,并将其标记为child1
  • docker-compose部署child1服务
  • 步骤顺序与child 2相同

下一个docker-compose up将更简单(我们已经标记了可用的图像,因此我们跳过所有构建步骤)。
如果您已经有标记的图像,并希望重建:使用docker-compose build告诉它构建所有映像(是的,基本映像和子映像都将被重建)。

t98cgbkg

t98cgbkg2#

使用Makefile。docker-compose不是为了构建图像链而设计的,它是为了运行容器而设计的。
你可能还对dobi感兴趣,这是一个构建自动化工具(如make),旨在处理docker镜像和容器。
免责声明:我是dobi的作者

o4tp2gmn

o4tp2gmn3#

我建议将你的dockerfile构建为多阶段构建:

FROM ubuntu as builder
...

FROM builder as my_target_1
...
CMD my_cmd_1

FROM builder as my_target_2
...
CMD my_cmd_2

如果你的builder非常大,但你只需要它的几个文件,你也可以这样做:

FROM ubuntu as builder
...

FROM alpine as my_target_1
COPY --from=builder /path/to/exec /root/exec
...
COM my_cmd_1

然后,在你的docker compose文件中,你可以这样做:

services:
    my_target_1:
        build:
            dockerfile: path/to/Dockerfile
            target: my_target_1
    my_target_2:
        builder:
            dockerfile: path/to/Dockerfile
            target: my_target_2

如果你真的希望builder也是你的dockerfile的一部分(例如,推送到注册表)而不运行它,你可以添加一个profiles标签,这将为目标分配一个配置文件:

servies:
    builder:
        build:
            dockerfile: path/to/Dockerfile
            target: builder
        profiles: ["do-not-run"]

这将使builder成为do-not-run配置文件的一部分,这意味着:

  • 如果您只执行docker compose up,它将不会运行
  • 你可以通过执行docker compose up --profile=do-not-run来运行它

在任何情况下(无论您的docker-compose.yml中是否有builder),都可以使用

docker compose build
6gpjuf90

6gpjuf904#

对于这个问题,你不需要单独的图像-只需要使用一个环境变量:

FROM ubuntu:16.04

ENV PROGRAM

CMD ${PROGRAM}

然后对于容器1,将环境变量PROGRAM设置为bar1_command。对容器2、3、...、N执行相同的操作。

相关问题