【问题标题】:How to organize multiple Dockerfiles, docker-compose.yaml and .dockerignore如何组织多个 Dockerfile,docker-compose.yaml 和 .dockerignore
【发布时间】:2021-12-02 07:33:29
【问题描述】:

在查看How to name Dockerfiles 上的答案后,我还有很多问题。

就我而言,我至少需要两个Dockerfiles,一个docker-compose.yaml 和一个.dockerignore。听起来像使用 <purpose>.DockerfileDockerfile.<purpose> 之类的扩展程序的缺点是失去了在 hub.docker.com 上使用 autobuilder 的功能。

所以其他人建议您将每个 Dockerfile 保存在一个目录中并从那里构建。

所以可能是这样的:

dockerfiles/
--python_consumer/
-----Dockerfile
--python_producer/
-----Dockerfile
--docker-compose.yaml
--.dockerignore

在这种情况下 .dockerignore 会在全局范围内适用于所有 dockerfile 吗?这种结构有什么大的缺点吗?

我的示例 docker-compose.yaml 没有单独的目录和一个组合的消费者/生产图像作为上下文。

version: '3.8'
services:
  standalone:
    hostname: standalone
    container_name: standalone
    image: apachepulsar/pulsar:2.8.1
    ports:
      - 8080:8080 # exposed would be a better practice
      - 6650:6650 # exposed would be a better practice
    command: bin/pulsar standalone
    healthcheck:
      test: ["CMD", "nc", "-vz", "localhost", "6650"]
      interval: 20s
      timeout: 5s
      retries: 5
    networks:
      - conprod
  conprod:
    hostname: conprod
    container_name: conprod
    build:
      context: .
      dockerfile: ./Dockerfile
    restart: on-failure # best practice is probably "unless-stopped"
    depends_on:
      - standalone
    networks:
      - conprod
networks:
  conprod:

【问题讨论】:

  • docker-compose.yml 是什么样的;子目录是否可用作独立的构建上下文?如果是这样,那么您应该将.dockerignore 放在Dockerfiles 旁边。
  • 我已经添加了我的docker-compose.yaml 以获取上下文。目前我的Dockerfile 位于带有.dockerignoredocker-compose.yaml 的根目录中。但是我需要两个 Dockerfiles 来为两个不同的 python 应用程序构建两个容器。
  • .dockerignore filebuild: { context: } 目录中读取;它不会在其他任何地方产生影响。
  • 所以要编辑以上内容,我的context: 将更改为./dockerfiles

标签: docker docker-compose dockerfile naming-conventions


【解决方案1】:

当你构建一个镜像时,你会向 Docker 守护进程发送一个构建上下文;在您的 Compose 设置中,这是在 build: { context: } 设置中命名的目录。 .dockerignore file 必须在那个确切的目录中,而不是其他任何地方。它的实际效果是使文件从构建上下文中排除,从而可以加快构建序列。

构建上下文的另一个重要影响是所有 Dockerfile COPY 指令都被认为是相对于该目录的;您不能从父目录或兄弟目录中COPY。因此,如果文件在项目之间共享,则必须将上下文目录设置为将包含的所有文件的某个祖先目录,并且COPY 指令将相对于该目录(即使 Dockerfiles 位于每个项目的目录中) )。另见How to include files outside of Docker's build context?

如果您的项目是完全独立的:可能有一个前端和一个后端项目,或者在您的情况下,生产者和消费者共享一种消息格式但没有任何实际代码。那么在这种情况下:

  • 在每个项目子目录中放置一个准确命名为Dockerfile 的Dockerfile
  • 在每个项目子目录下放一个.dockerignore文件(不能在父目录下)
  • COPY 指令是相对于项目子目录的
    COPY requirements.txt ./
    
  • 在 Compose 文件中,您可以使用简写 build: directory 语法,因为您有标准(默认)dockerfile: 名称
    version: '3.8'
    services:
       producer:
         build: ./python_producer
         environment:
           - RABBITMQ_HOST=rabbitmq
       consumer:
         build: ./python_consumer
         environment:
           - RABBITMQ_HOST=rabbitmq
       rabbitmq:
         image: rabbitmq:3
         hostname: rabbitmq # RabbitMQ is very unusual in needing to set this
    

如果您的项目共享代码或其他文件:在您的示例中,您可能为共享代码中的消息格式定义 Python 数据结构。在这种情况下:

  • 在每个项目子目录中放置一个准确命名为Dockerfile的Dockerfile
  • 将单个.dockerignore 文件放在项目根目录中
  • COPY 指令是相对于项目根目录的
    COPY python_producer/requirements.txt ./
    
  • 在 Compose 文件中,您需要指定 context: .dockerfile: 指向每个组件的 Dockerfile
    version: '3.8'
    services:
       producer:
         build:
           context: .
           dockerfile: python_producer/Dockerfile
         environment:
           - RABBITMQ_HOST=rabbitmq
       consumer:
         build:
           context: .
           dockerfile: python_consumer/Dockerfile
         environment:
           - RABBITMQ_HOST=rabbitmq
       rabbitmq:
         image: rabbitmq:3
         hostname: rabbitmq # RabbitMQ is very unusual in needing to set this
    

【讨论】:

  • 不错的答案,大卫!我只是想推荐在dockerfile: 属性中也使用./。它可以防止对名称文件夹的误解。
  • 要明确@JuanFontes 你推荐'./python_producer/Dockerfile'和'./python_consumer/Dockerfile'?
猜你喜欢
  • 1970-01-01
  • 2021-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多