我正在寻找更好的解决方案来在通过 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 install,这是多余的。
所以我当前的想法是使用专用的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 卷的事情需要记住:
Dockerfile 中的所有内容都发生在考虑
docker-compose.yml
文件中的任何卷或环境变量之前。如果您的目标是填充卷,则无法在 Dockerfile 中执行此操作(通常这在 Docker 中很尴尬;请改用 native 主机工具)。如果将卷挂载到容器目录中,它会完全隐藏已有的内容。我看到很多有关 Dockerfile 的问题,这些文件只能在容器本地
/app
目录中工作,然后在该目录上绑定(bind)挂载本地源代码树;这基本上使 Dockerfile 成为无操作。如果您的 Dockerfile 中有
VOLUME
指令,则您无法再对镜像中的该目录进行任何更改。 (在您的问题中,在VOLUME
指令之后运行composer
将不会产生任何影响。)您可以将卷装载到容器中的任何目录中,无论它是否被声明为
VOLUME
。我建议永远不要在 Dockerfile 中声明 VOLUME,尤其是对于包含代码的目录(您希望在删除容器时使用新的镜像代码更新这些目录,并且重新创建)。
关于docker - 在构建时从 docker 访问已安装的卷以进行 Composer/npm 安装?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53998567/