docker-compose named volume with one file: ERROR: Cannot create container for service, source is not directory

docker-compose named volume with one file: ERROR: Cannot create container for service, source is not directory

我正在尝试使容器 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 is not directory

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

编辑: 我也注意到 web 容器内的 /usr/local/bin/wkhtmltopdf 是目录而不是文件 如我所料

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

如果您查看 Docker Hub page for the php image you can see that php:7.4-apache is an alias for (currently) php:7.4.15-apache-buster, where "Buster" is the name of a Debian release. You can then search on https://packages.debian.org/ to discover that Debian has a prepackaged 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 启动之前完成)但它可能不会是一个实际问题。