在项目中构建镜像时,构建目录令人头大,docker-compose里的目录和DockerFile的目录是什么关系,docker-compose存放目录不同,这些目录也不一样,本文从底层原理来带你了解他们之间的关系。
案例介绍
我们以上图的案例为例,backend为我们的python后端,我们通过docker-compose把它构建为一个镜像,我们把docker相关的文件都放在docker目录下,
docker构建容器原理
要弄清楚这些目录之间的关系,我们需要先清楚docker 构建镜像的原理。
Docker 构建上下文(Build Context)是指构建镜像时,Docker CLI 发送给 Docker Daemon 的一组文件和目录。这个上下文中包含了 Dockerfile 和上下文目录的内容。构建过程中,Docker Daemon 使用这个上下文来执行 Dockerfile 中的指令。
1. Dockerfile 和上下文目录:
Dockerfile: Dockerfile 是构建镜像的指令脚本,定义了从基础镜像开始如何构建新镜像的步骤。
上下文目录: 上下文目录是 Dockerfile 所在的目录及其子目录的内容。Docker CLI 在构建时将整个上下文目录发送给 Docker Daemon。
2. 传输到 Docker Daemon:
Docker CLI 在构建命令中指定了 Dockerfile 的位置和上下文目录。例如:
docker build -f path/to/Dockerfile context_directory
这个命令中,-f 参数指定 Dockerfile 的位置,context_directory 指定上下文目录。
3. 缓存和构建效率:
由于构建上下文包含 Dockerfile 和上下文目录的内容,Docker 使用这个上下文来执行指令。在构建时,Docker Daemon 会检查每个指令的依赖项是否发生变化。如果 Dockerfile 中的某个指令及其依赖项未发生变化,Docker 将使用缓存而不重新执行这个指令,从而提高构建效率。
4. 文件过滤和.dockerignore:
在传输上下文到 Docker Daemon 之前,Docker CLI 会应用文件过滤。这是通过 .dockerignore 文件实现的,类似于 .gitignore。.dockerignore 中列出的文件和目录将被排除在构建上下文之外,以减小传输的大小。
5. 理解构建上下文的重要性:
构建上下文包含了构建所需的全部信息,因此要保持足够小,以减少构建时间和网络传输的开销。
需要谨慎处理构建上下文,确保只包含必要的文件,而不包含大量不相关或不需要的文件。
理解和优化 Docker 构建上下文有助于提高构建效率、减小镜像大小,并且在使用 .dockerignore 等方式时能够更好地控制构建的内容。
案例解释
1. 首先我们要确定docker-compose中
version: "3" services: backend: container_name: ${PRE_FIX}_${BACKEND_NAME} build: context: ../ dockerfile: ./docker/backend/Dockerfile args: BACKEND_DIR: ${BACKEND_DIR}
* !backend/requirements.txt !docker/backend/Dockerfile
2. Dockerfile文件, 在此文件中, 目录都是相对我们上一步中的临时目录, 目录结构跟保存一致, 这里的WORKDIR变量是上一步通过args传过来的, 如果在忽略文件中忽略.env那么Dockerfile是不是可以直接使用呢, 大家可以试一下
FROM python:3.9 ARG BACKEND_DIR WORKDIR ${BACKEND_DIR} COPY ./backend/requirements.txt ./ RUN python -m pip install --upgrade pip & pip install --no-cache-dir -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
3. 其它文件
.env文件
# DOCKER START # GLOBAL SUBNET=172.10.0.0/24 GATEWAY=172.10.0.1 PRE_FIX=blog BACKEND_DIR=/opt/blog # BACKEND BACKEND_NAME=backend BACKEND_PORT=38080 BACKEND_IP_ADDR=172.10.0.3 # DOCKER END
docker-compose 文件
version: "3" services: backend: container_name: ${PRE_FIX}_${BACKEND_NAME} build: context: ../ dockerfile: ./docker/backend/Dockerfile args: BACKEND_DIR: ${BACKEND_DIR} ports: - "${BACKEND_PORT}:5000" working_dir: ${BACKEND_DIR} volumes: - ../backend:${BACKEND_DIR} - /etc/localtime:/etc/localtime:ro command: ["python", "manage.py", "admin"] networks: blog: ipv4_address: ${BACKEND_IP_ADDR} logging: driver: "json-file" options: max-size: "30m" max-file: "10" privileged: true restart: always networks: blog: driver: bridge ipam: config: - subnet: ${SUBNET} gateway: ${GATEWAY}
练习
如果把docker-compose直接放在最外层, 你知道怎么改了吗
查看原文:项目中docker-compose构建镜像目录问题
关注公众号 "字节航海家" 及时获取最新内容