【问题标题】:docker-compose named volume with one file: ERROR: Cannot create container for service, source is not directorydocker-compose 带有一个文件的命名卷:错误:无法为服务创建容器,源不是目录
【发布时间】:2021-02-05 12:21:33
【问题描述】:

我正在尝试使来自容器wkhtmltopdf 的二进制文件/bin/wkhtmltopdfweb 容器中可用。我尝试使用命名卷来实现这一点。

我的docker-compose.yml 中有以下 docker 容器设置:

services:
    web:
        image: php:7.4-apache
        command: sh -c "mkdir -p /usr/local/bin && touch /usr/local/bin/wkhtmltopdf"
        entrypoint: sh -c "exec 'apache2-foreground'"
        volumes:
            - wkhtmltopdfvol:/usr/local/bin/wkhtmltopdf
            
    wkhtmltopdf:
        image: madnight/docker-alpine-wkhtmltopdf
        command: sh -c "touch /bin/wkhtmltopdf"
        entrypoint: sh -c "tail -f /dev/null"  # workaround to keep container running
        volumes: 
            - wkhtmltopdfvol:/bin/wkhtmltopdf

volumes:
    wkhtmltopdfvol:

但是,在运行docker-compose up 时出现以下错误:

ERROR: for wkhtmltopdf  Cannot create container for service wkhtmltopdf:
source /var/lib/docker/overlay2/42e7082b8024ae4ebb13a4f0003a9e17bc18b33ef0677431dd002da3c21dde88/merged/bin/wkhtmltopdf is not directory

.../bin/wkhtmltopdf 不是目录

这是否意味着我不能在容器之间共享一个文件,而只能通过命名卷共享目录?我如何做到这一点?

编辑:我还注意到web 容器内的/usr/local/bin/wkhtmltopdf是一个目录,而不是一个文件,正如我所料。

【问题讨论】:

    标签: docker docker-compose wkhtmltopdf docker-volume


    【解决方案1】:

    像这样在容器之间共享二进制文件可能会很棘手。卷可能不是您要寻找的机制。

    如果您查看Docker Hub page for the php image,您会发现php:7.4-apache 是(当前)php:7.4.15-apache-buster 的别名,其中“Buster”是 Debian 版本的名称。然后您可以搜索 https://packages.debian.org/ 以发现 Debian 有一个预先打包的 wkhtmltopdf 软件包。您可以使用自定义 Dockerfile 安装它:

    FROM php:7.4-apache
    RUN apt-get update \
     && DEBIAN_FRONTEND=noninteractive \
        apt-get install --assume-yes --no-install-recommends \
          wkhtmltopdf
    # COPY ...
    # Base image provides EXPOSE, CMD
    

    那么你的docker-compose.yml文件需要构建这个镜像:

    version: '3.8'
    services:
      web:
        build: .
        # no image:, volumes:, or command: override
    

    就这样共享二进制文件的机制而言,当二进制文件需要目标容器中不存在的共享库时,您可能会遇到麻烦。 apt-get install 机制为您处理这个问题。如果容器具有不同的共享库生态系统(尤其是基于 Alpine 的容器),或者使用来自不同操作系统的主机二进制文件,也会存在潜在的问题。


    您展示的 Compose 文件以一种实际上不起作用的方式混合了多个概念。命名卷始终是一个目录,因此尝试将其挂载到第二个容器中的 /bin/wkhtmltopdf 文件会导致您看到的错误。哪个容器首先启动并创建卷存在依赖性问题。一个容器只运行一个命令,如果您同时拥有entrypoint:command:,则该命令将作为额外参数传递给入口点(如果入口点是sh -c ... 调用,则有效地忽略)。

    如果你真的想尝试这种方法,你应该使用web: {depends_on: [wkhtmltopdf]} 来强制依赖顺序。第二个容器应该将卷安装在其他地方,它可能不应该有entrypoint:,它应该做类似command: cp -a /bin/wkhtmltopdf /export 的事情。 (一旦这个cp 完成,它将立即退出,但这不重要。)然后第一个容器可以将卷安装在/usr/local/bin 上,而不是专门设置command:entrypoint:。仍然会有轻微的竞争条件(不能保证 cp 命令会在 Apache 启动之前完成),但这可能不是一个实际问题。

    【讨论】:

    • 感谢您的澄清!你是对的,因为它的依赖关系,共享这样的二进制文件并不是很聪明......我找不到任何官方文档说命名卷只允许目录......你有那个链接吗?
    猜你喜欢
    • 2020-03-30
    • 1970-01-01
    • 2016-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多