【问题标题】:Adding files to standard images using docker-compose使用 docker-compose 将文件添加到标准图像
【发布时间】:2016-09-08 10:44:45
【问题描述】:

我不确定是否有一些明显的东西让我无法理解,或者它是否不可能,但我正在尝试使用来自 docker hub 的图像组成整个应用程序堆栈。

其中之一是 mysql,它支持通过卷添加自定义配置文件并从已安装目录运行 .sql 文件。

但是,我在运行 docker-compose 的机器上拥有这些文件,而不是在主机上。在运行入口点/cmd之前,是否无法从本地机器指定文件复制到容器中?我真的必须为这种情况创建所有内容的本地图像吗?

【问题讨论】:

  • 我提供了两种将数据从本地计算机复制到主机(本地或远程)的方法。请参阅此处stackoverflow.com/a/39348811/1556338 通常,您希望将数据远离图像。这使您的图像可在不同的环境(开发/测试/产品、客户端 A、客户端 B 等)中重复使用。
  • 是的,docker cp 可以工作,但不能作为 docker-compose 的一部分,这是一个单独的步骤。为了实现这一点,最好不要将 docker-compose 包装在 shell 脚本中。
  • 不幸的是 docker compose 是有限的。随着您的使用变得更加具体,您将无法使用 shell 脚本来逃避某些事情。 Compose 甚至不适用于新的 swarm 模式。
  • 我通常用来解决这个问题的方法是创建 Docker 镜像进行配置。我在带有 Dockerfile 的 CVS 中有这些文件,并且我构建了一个版本化的 Docker 映像(来自 Scratch)。后来我用 volumes from 启动了这个“文件容器”。

标签: docker docker-compose


【解决方案1】:

选项 A:在图片中包含文件。这不太理想,因为您将配置文件与您的图像混合(实际上应该只包含您的二进制文件,而不是您的配置),但满足仅使用 docker-compose 发送文件的要求。

这个选项是通过使用 docker-compose 来构建你的镜像来实现的,并且该构建会将构建目录中的任何文件发送到远程 docker 引擎。你的 docker-compose.yml 看起来像:

version: '2'

services:
  my-db-app:
    build: db/.
    image: custom-db

db/Dockerfile 看起来像:

FROM mysql:latest
COPY ./sql /sql

入口点/cmd 将保持不变。如果图像已经存在并且您需要更改 sql 文件,则需要运行 docker-compose up --build


选项 B:使用卷来存储您的数据。这不能直接在 docker-compose 内部完成。但是,这是将图像外部的文件包含到容器中的首选方式。您可以使用 docker CLI 和输入重定向以及 tar 之类的命令在网络上填充卷,以打包和解压缩通过标准输入发送的文件:

tar -cC sql . | docker run --rm -it -v sql-files:/sql \
  busybox /bin/sh -c "tar -xC /sql"

通过脚本运行它,然后让相同的脚本反弹 db 容器以重新加载该配置。


选项 C: 使用某种网络附加文件系统。如果您可以在运行 docker CLI 的主机上配置 NFS,则可以使用以下选项之一从远程 docker 节点连接到这些 NFS 共享:

# create a reusable volume
$ docker volume create --driver local \
    --opt type=nfs \
    --opt o=addr=192.168.1.1,rw \
    --opt device=:/path/to/dir \
    foo

# or from the docker run command
$ docker run -it --rm \
  --mount type=volume,dst=/container/path,volume-driver=local,volume-opt=type=nfs,volume-opt=o=addr=192.168.1.1,volume-opt=device=:/host/path \
  foo

# or to create a service
$ docker service create \
  --mount type=volume,dst=/container/path,volume-driver=local,volume-opt=type=nfs,volume-opt=o=addr=192.168.1.1,volume-opt=device=:/host/path \
  foo

选项 D: 使用 swarm 模式,您可以在图像中包含文件作为配置。这允许配置文件(通常需要推送到 swarm 中的任何节点)按需发送到运行服务的节点。这使用 docker-compose.yml 文件来定义它,但 swarm 模式不使用 docker-compose 本身,因此这可能不符合您的特定要求。您可以运行单节点集群模式集群,因此即使您只有一个节点也可以使用此选项。此选项确实需要将每个 sql 文件作为单独的配置添加。 docker-compose.yml 看起来像:

version: '3.4'

configs:
  sql_file_1:
    file: ./file_1.sql

services
  my-db-app:
    image: my-db-app:latest
    configs:
      - source: sql_file_1
        target: /sql/file_1.sql
        mode: 444

然后,您将运行 docker stack deploy -c docker-compose.yml my-db-stack,而不是 docker-compose up

【讨论】:

    【解决方案2】:

    如果你不能使用卷(想要无状态的 docker-compose.yml 并使用远程机器),你可以通过命令编写配置文件。

    官方图片中的nginx配置示例:

    version: "3.7"
    
    services:
      nginx:
        image: nginx:alpine
        ports:
          - 80:80
        environment:
          NGINX_CONFIG: |
            server {
              server_name "~^www\.(.*)$$" ;
              return 301 $$scheme://$$1$$request_uri ;
            }
            server {
              server_name example.com
              ...
            }
        command:
          /bin/sh -c "echo \"$$NGINX_CONFIG\" > /etc/nginx/conf.d/redir.conf; nginx -g \"daemon off;\""
    

    环境变量也可以保存在 .env 文件中,您可以使用 Compose 的扩展功能或从 shell 环境(您从其他任何地方获取它)加载它:

    https://docs.docker.com/compose/compose-file/#env_file https://docs.docker.com/compose/compose-file/#variable-substitution

    获取容器的原始入口点命令:

    docker container inspect [container] | jq --raw-output .[0].Config.Cmd
    

    要调查修改哪个文件通常会起作用:

    docker exec --interactive --tty [container] sh
    

    【讨论】:

    • 我同意这个答案,因为它至少适用于小文件。好把戏。我将不得不覆盖该图像的默认入口点,但这很好。
    【解决方案3】:

    这就是我对卷的处理方式:

    services:
      my-db-app:
        command: /shell_scripts/go.sh
        volumes:
          - ./shell_scripts:/shell_scripts 
    

    【讨论】:

    • 当 shell_scripts 驻留在与远程 docker 服务器不同的主机上时,这不起作用。
    • 也对我有用,只需使用volumes: - ./:/config/path/in/container 将项目根目录中的文件挂载到容器中。
    【解决方案4】:

    我认为你必须在撰写文件中做:

    volumes:
     - src/file:dest/path
    

    【讨论】:

      【解决方案5】:

      作为此问题的最新更新:例如,使用托管在 Amazon 上的 docker swarm,您可以定义一个可由服务共享且可在 swarm 的所有节点上使用的卷(使用 cloudstor 驱动程序,它又具有AWS EFS 用于持久性的底层)。

      version: '3.3'
      services:
        my-db-app:
          command: /shell_scripts/go.sh
          volumes:
            shell_scripts:/shell_scripts 
      volumes:
          shell_scripts:
            driver: "cloudstor:aws"
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-08-29
        • 2023-01-22
        • 2017-09-27
        • 1970-01-01
        • 2020-11-14
        • 1970-01-01
        相关资源
        最近更新 更多