我正在寻找一种更好的解决方案,以在通过docker-compose挂载的主机卷中安装composer或npm软件包。

在我的docker-compose.yml中,我有:

volumes:
  - ./app:/var/www/app
  ...

在我的dockerfile中,我想使用此卷来安装东西:
VOLUME ["/var/www/app"]
RUN composer install -d /var/www/app

但是据我了解,从dockerfile构建容器时,在docker-compose中安装的卷尚不可用。

因此,我的下一个尝试是在容器启动时执行此操作:
CMD bash -c "composer install -d /var/www/app && /usr/sbin/apache2ctl -DFOREGROUND"

至少可以,但是每次运行容器时,它都会调用composer安装,这是多余的。

因此,我目前的想法是使用专用的 Composer 镜像,将composer.json挂载到其中进行安装,然后将完成的供应商从 Composer 容器复制到容器中的某个位置,并在需要的地方链接。像这样:
FROM composer as composer
COPY ./app/composer.json /app
COPY ./app/composer.lock /app
RUN composer install --ignore-platform-reqs --no-scripts

FROM library/ubuntu:jessie
# ... do other stuff with the main image ...

COPY --from=composer /app/vendor /var/www/composer/vendor
CMD bash -c "ln -s /var/www/composer/vendor /var/www/app/vendor  && /usr/sbin/apache2ctl -DFOREGROUND"

但是对于这样一个普通的问题,仍然感觉有点变通方法。是否有更好的方法可以解决此问题或任何已知的良好做法?

最佳答案

我认为最佳实践以及我的专业工作是在这种情况下根本不使用卷。在构建时,我的Dockerfile COPY在应用程序代码中。我有一个有效的主机开发设置(唯一的真正主机依赖项是Node本身;其他所有内容都在node_modules目录中),因此如果遇到问题,可以在本地环境中对其进行复制,调试和编写测试。只有在这种情况下,我才能回到Docker。

FROM ???
WORKDIR /var/www/app
COPY app/composer.json app/composer.lock ./
RUN composer install --ignore-platform-reqs --no-scripts
COPY app/ ./
...
CMD ["apache2ctl", "-DFOREGROUND"]

否则,这里需要记住有关Docker卷的几件事情:
  • 甚至在不考虑docker-compose.yml文件中的任何卷或环境变量之前,都会发生Dockerfile中的所有事情。如果您的目标是填充卷,则不能在Dockerfile中执行此操作(这在Docker中通常很尴尬;请改用本机宿主工具)。
  • 如果将卷装载到容器目录中,它将完全隐藏已经存在的内容。我看到了很多关于Dockerfile的问题,这些问题仅在容器本地的/app目录中起作用,然后在该目录上绑定(bind)挂载本地源代码树。基本上使Dockerfile成为无人操作。
  • 如果Dockerfile中有一个VOLUME指令,则无法再对该镜像中的该目录进行任何更改。 (在您的问题中,在composer指令之后运行VOLUME将无提示地无效。)
  • 可以将卷挂载到容器中的任何目录中,无论是否将其声明为VOLUME。我建议您不要在Dockerfiles中声明VOLUME,特别是对于包含代码的目录(尤其是当您删除并重新创建容器时,要使用新的图像代码更新它们)时尤其如此。
  • 关于docker - 在构建时从docker访问composer/npm的已安装卷吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53998567/

    10-14 19:36
    查看更多