使用docker compose将文件添加到标准图像

使用docker compose将文件添加到标准图像,docker,docker-compose,Docker,Docker Compose,我不确定是有什么明显的东西逃过了我的视线,还是根本不可能,但我正试图用docker hub的图像组成一个完整的应用程序堆栈 其中之一是mysql,它支持通过卷添加自定义配置文件,并从装载的目录运行.sql文件 但是,我在运行docker compose的机器上有这些文件,而不是在主机上。在运行entrypoint/cmd之前,是否无法指定要从本地计算机复制到容器中的文件?我真的必须为这种情况创建所有内容的本地图像吗?选项A:包括图像中的文件。这不太理想,因为您正在将配置文件与映像混合(它实际上应

我不确定是有什么明显的东西逃过了我的视线,还是根本不可能,但我正试图用docker hub的图像组成一个完整的应用程序堆栈

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


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

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

此选项是通过使用docker compose构建映像实现的,该构建将从构建目录向远程docker引擎发送任何文件。您的
docker compose.yml
如下所示:

version: '2'

services:
  my-db-app:
    build: db/.
    image: custom-db
FROM mysql:latest
COPY ./sql /sql
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
而db/Dockerfile将如下所示:

version: '2'

services:
  my-db-app:
    build: db/.
    image: custom-db
FROM mysql:latest
COPY ./sql /sql
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
入口点/cmd将保持不变。如果映像已经存在并且需要更改sql文件,则需要运行
docker compose-up--build


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

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: '2'

services:
  my-db-app:
    build: db/.
    image: custom-db
FROM mysql:latest
COPY ./sql /sql
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
,这就是我对卷的处理方式:

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

作为对这个问题的最新更新:例如,使用托管在Amazon上的docker swarm,您可以定义一个卷,该卷可以由服务共享,并且可以跨swarm的所有节点使用(使用驱动程序,而驱动程序又具有持久性的基础)


我认为您必须在撰写文件中执行以下操作:

volumes:
 - src/file:dest/path

如果无法使用卷(需要无状态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环境(从enywhere else获取)加载它:

要获取容器的原始入口点命令,请执行以下操作:

docker container inspect [container] | jq --raw-output .[0].Config.Cmd
要调查要修改的文件通常会起作用,请执行以下操作:

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

我提供了两种将数据从本地计算机复制到主机(本地或远程)的方法。请参见此处,一般情况下,您希望将数据远离图像。这使您的映像可以在不同的环境(开发/测试/生产、clientA、clientB等)中重用。是的,
docker cp
可以工作,但不是docker compose的一部分,这是一个单独的步骤。最好不要仅仅为了实现这一点而将docker compose包装在shell脚本中。不幸的是,docker compose是有限的。随着您的使用变得更加具体,您将无法避免在某些情况下使用shell脚本。Compose甚至不适用于新的swarm模式。我通常要做的是创建Docker映像以进行配置。我在带有Dockerfile的CVS中有这些文件,并且我构建了一个版本化的Docker映像(从头开始)。稍后,我启动了compose,其中包含一个卷,用于指示此“文件容器”。当shell_脚本驻留在与远程docker服务器不同的主机上时,这不起作用。对于我来说,仅使用
卷:-./:/config/path/in/container
将文件从项目根目录装载到容器中也有效。我批准此答案,因为它至少适用于小文件。好把戏。我必须覆盖该图像的默认入口点,但这很好。