如何组织多个Dockerfile,docker-compose.yaml and .docker忽略
How to organize multiple Dockerfiles, docker-compose.yaml and .dockerignore
查看 How to name Dockerfiles 上的答案后,我仍然有很多问题。
就我而言,我至少需要两个 Dockerfile
,一个 docker-compose.yaml
和一个 .dockerignore
。听起来使用 <purpose>.Dockerfile
或 Dockerfile.<purpose>
等扩展名的缺点是失去了在 hub.docker.com.
处使用自动生成器的功能
所以其他人建议您将每个 Dockerfile
保存在一个目录中并从那里构建。
所以可能是这样的:
dockerfiles/
--python_consumer/
-----Dockerfile
--python_producer/
-----Dockerfile
--docker-compose.yaml
--.dockerignore
在这种情况下,.dockerignore 是否会在全球范围内对所有 dockerfiles 起作用?以这种方式构建有什么大的缺点吗?
我的示例 docker-compose.yaml
没有单独的目录和一个组合的 consumer/production 上下文图像。
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 设置中,这是在 build: { context: }
设置中命名的目录。 .dockerignore
file 必须在那个确切的目录中,而不是在其他任何地方。它的实际效果是导致文件从构建上下文中排除,这可以导致更快的构建序列。
构建上下文的另一个重要作用是所有 Dockerfile COPY
指令都被认为是相对于该目录的;您不能从父目录或同级目录中 COPY
。因此,如果文件在项目之间共享,则必须将上下文目录设置为将包含的所有文件的某个祖先目录,并且 COPY
指令将相对于该目录(即使 Docker文件位于每个项目目录中)。另见 How to include files outside of Docker's build context?
如果您的项目是完全独立的:可能有一个前端项目和一个后端项目,或者在您的情况下,生产者和消费者共享一种消息格式但是没有任何实际代码。那么在这种情况下:
- 在每个项目子目录
中放置一个 Docker 文件,命名完全 Dockerfile
- 在每个项目子目录下放一个
.dockerignore
文件(不能在父目录下)
COPY
指令是相对于项目子目录
COPY requirements.txt ./
- 在 Compose 文件中,您可以使用 shorthand
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 数据结构。在这种情况下:
- 在每个项目子目录
中放置一个 Docker 文件,命名完全 Dockerfile
- 将单个
.dockerignore
文件放入项目根目录
COPY
指令是相对于项目根目录
COPY python_producer/requirements.txt ./
- 在 Compose 文件中,您需要指定
context: .
和 dockerfile:
指向每个组件 Docker 文件
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
查看 How to name Dockerfiles 上的答案后,我仍然有很多问题。
就我而言,我至少需要两个 Dockerfile
,一个 docker-compose.yaml
和一个 .dockerignore
。听起来使用 <purpose>.Dockerfile
或 Dockerfile.<purpose>
等扩展名的缺点是失去了在 hub.docker.com.
所以其他人建议您将每个 Dockerfile
保存在一个目录中并从那里构建。
所以可能是这样的:
dockerfiles/
--python_consumer/
-----Dockerfile
--python_producer/
-----Dockerfile
--docker-compose.yaml
--.dockerignore
在这种情况下,.dockerignore 是否会在全球范围内对所有 dockerfiles 起作用?以这种方式构建有什么大的缺点吗?
我的示例 docker-compose.yaml
没有单独的目录和一个组合的 consumer/production 上下文图像。
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 设置中,这是在 build: { context: }
设置中命名的目录。 .dockerignore
file 必须在那个确切的目录中,而不是在其他任何地方。它的实际效果是导致文件从构建上下文中排除,这可以导致更快的构建序列。
构建上下文的另一个重要作用是所有 Dockerfile COPY
指令都被认为是相对于该目录的;您不能从父目录或同级目录中 COPY
。因此,如果文件在项目之间共享,则必须将上下文目录设置为将包含的所有文件的某个祖先目录,并且 COPY
指令将相对于该目录(即使 Docker文件位于每个项目目录中)。另见 How to include files outside of Docker's build context?
如果您的项目是完全独立的:可能有一个前端项目和一个后端项目,或者在您的情况下,生产者和消费者共享一种消息格式但是没有任何实际代码。那么在这种情况下:
- 在每个项目子目录 中放置一个 Docker 文件,命名完全
- 在每个项目子目录下放一个
.dockerignore
文件(不能在父目录下) COPY
指令是相对于项目子目录COPY requirements.txt ./
- 在 Compose 文件中,您可以使用 shorthand
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
Dockerfile
如果您的项目共享代码或其他文件: 在您的示例中,您可能为共享代码中的消息格式定义了 Python 数据结构。在这种情况下:
- 在每个项目子目录 中放置一个 Docker 文件,命名完全
- 将单个
.dockerignore
文件放入项目根目录 COPY
指令是相对于项目根目录COPY python_producer/requirements.txt ./
- 在 Compose 文件中,您需要指定
context: .
和dockerfile:
指向每个组件 Docker 文件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