如何挂载在Docker映像构建期间创建的目录?

时间:2020-05-25 21:59:25

标签: docker docker-compose dockerfile

我的docker-compose文件如下:

version: "3"

services:
  db:
    image: postgres
    environment:
      POSTGRES_PASSWORD: qwerty
      POSTGRES_USER: qwerty
    volumes:
      - /data/db:/var/lib/postgresql/data

  backend:
    build:
      context: .
      dockerfile: dockerfile_backend
    image: backend:dev1.0.0
    entrypoint: ["sh", "-c"]
    command: python manage.py runserver
    ports:
      - "4000:4000"

在我的dockerfile_backend中,我有一个git clone语句,该语句从git repo中克隆项目。有一个名为configs的文件夹,它是git clone的一部分。我需要将此文件夹安装为卷(类似于postgres卷安装点)。必须安装configs,因为在运行时文件夹的内容会被修改或更新,这些更改不应丢失。

如何挂载映像构建创建的文件夹?

我尝试在backend服务下按如下方式添加卷:

    volumes:
      - /data/configs:/git_folder/configs

这里的问题是挂载点(/data/configs)最初是空的,因此映像文件夹(/git_folder/configs)也变空了。

1 个答案:

答案 0 :(得分:1)

如何挂载映像构建创建的文件夹?

最直接的方法是完全避免使用此路径:从主机运行git clone命令。从构建的映像中复制数据并不是那么容易,并且如果构建过程的重要部分是将内容传递到主机上,那么您将无法利用Dockerfile进行所有操作。

如果您要处理的数据实际上是配置数据(顾名思义),则使用docker-compose.yml文件将文件检入(副本)到存储库是一种合理的方法。如果您也控制该存储库,通常会将这些文件包含在应用程序存储库本身中。然后,您可以像平常一样将目录绑定安装:

backend:
  build: .
  ports:
    - "4000:4000"
  volumes:
    - ./configs:/git_folder/configs

如果是应用程序数据,则可以将其存储在命名卷中。您将无法从主机直接访问它。 Docker将使用映像中的内容填充卷,但仅当您首次运行容器时:如果更改映像,则卷将保持不变。

version: '3'
volumes:
  configs:
services:
  backend:
    build: .
    ports:
      - "4000:4000"
    volumes:
      - configs:/git_folder/configs

第三种方法是让容器的启动程序检测数据目录是否为空,如果是,则填充它。您以postgres图像为例,这就是该图像的功能(如果不存在已知文件,请运行PostgreSQL的initdb命令)。您可以编写如下脚本:

#!/bin/sh
# Create the `configs` directory if it's empty
if [ -f /git_folder/configs/some_file ]; then
  cp -a /git_folder/configs_base/* /git_folder/configs
fi
# Run the main container command
exec "$@"

在您的Dockerfile中,将此脚本设为ENTRYPOINT。您必须使用JSON数组语法调用它。请勿覆盖entrypoint:中的docker-compose.yml(尤其是不要改变command:的常规shell命令含义)。

COPY entrypoint.sh /git_folder
RUN chmod +x /git_folder/entrypoint.sh
ENTRYPOINT ["/git_folder/entrypoint.sh"]
CMD python manage.py runserver