【问题标题】:Sharing a folder between Docker-Containers with precompiled files使用预编译文件在 Docker 容器之间共享文件夹
【发布时间】:2020-12-03 07:39:53
【问题描述】:

我使用 Github Actions 制作了一个 php-fpm Docker 容器,其中包含 Laravel 和预编译的 Docker Compose 文件。 CSS 和 JS 文件是用 npm 制作的。这个 Docker 容器然后被推送到我的 Docker Regestry。

我想检查这个容器并让它与 Docker-Compose 一起运行,并且一个 nginx 容器使用这个配置运行:

server {
    listen 80;
    index index.php index.html;
    error_log  /var/log/nginx/error.log;
    access_log /var/log/nginx/access.log;
    root /var/www/public;
    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass app:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
    location / {
        try_files $uri $uri/ /index.php?$query_string;
        gzip_static on;
    }
}

所以 PHP 部分运行完美,但 CSS 和 JS 部分不工作,因为 app Container 有这些文件。我如何在这两个容器之间进行复制、共享或其他操作?

您不能从主机放入卷,因为卷将只包含主机上的内容,而不是容器中的内容......它必须指向另一个方向。

【问题讨论】:

  • 问题是,我想在主机系统上保持原样的环境。来自 Docker 的镜像在 Github Actions 中构建,然后传输到我的 Docker Regestry。我不想在我的 Live System 上拥有构建上下文。

标签: laravel docker npm docker-compose composer-php


【解决方案1】:

您应该使用完全符合您需求的命名卷

volumes:
  assets:

services:
  nginx:
    ...
    volumes:
      - assets:/var/www/public/:ro

  app:
    ...
    volumes:
      - assets:/your/npm/output/folder

您的 JS/CSS 文件将在您的 2 个容器之间正确共享

【讨论】:

    【解决方案2】:

    您必须在 docker 构建时定义一个 docker 卷,然后设置您的预编译文件,然后将此命名卷挂载到两个系统。

    问题是您试图挂载已经在 docker 映像中的东西,而不是 docker 卷。 在 docker 运行时没有办法做到这一点。这不是哲学。

    总而言之,您的做法(错误):

    1. /your_dir中的预编译文件创建docker buildimage1
    2. 正如您所说的那样,您不能从主机挂载到 docker-image1:/your_dir 的目录,因为它会覆盖它。
    3. 没有从 docker-image2docker-image1 的优雅访问方式。

    良好做法:

    1. 例如创建名为 myvolume 的 docker NAMED 卷。
    2. 创建docker buildimage1,将你的预编译保存在myvolume
    3. 创建容器 docker run -t image1... yourCssDocker 安装 myvolume
    4. 创建容器docker run -t image2...yourNginxDocker,挂载myvolume

    这就是继续的方式。请注意,您应该通过其名称访问 myvolume,而不是通过绑定卷(主机路径)。

    您可以仅使用 1 个 docker-compose.yml 文件(使用 css-precomp 作为命名的 docker 卷名)完成所有步骤(来自良好实践的 4 个)

    volumes:
      css-precomp:
    
    services:
      my-service:
        build:
          - context: .
          - dockerfile: Dockerfile
        volumes:
          - css-precomp:/your_dir
        ...
    

    最后,你可以在Dockerfile中检查你的数据是否正确生成,检查/var/lib/docker/volumes/css-precomp/_data

    【讨论】:

      【解决方案3】:

      Dockerfile COPY 指令允许您将文件从一个映像复制到另一个映像。如果您已经构建了 PHP 应用程序映像,则可以使用其中的静态文件构建 nginx 映像,例如:

      FROM nginx:latest
      COPY --from=my/php-app /usr/src/app /usr/share/nginx/html
      COPY nginx.conf /etc/nginx
      

      您现在将拥有两个独立的图像。如果 PHP 映像中的内容发生更改,那么您可以重建 nginx 映像以在那里获取更新的内容。 (如果您按照其他问题的建议使用命名卷,则必须手动删除包含静态资产的卷以更新其内容。)此设置也适用于更高级的设置,其中每个组件可能运行多个副本不同的系统(Docker Swarm、Amazon ECS、Kubernetes)。

      如果直接从后端服务提供静态资产并仅将 nginx 用作反向代理是合理的,则可以显着简化此部署顺序。不过,使用 PHP-FPM 设置可能无法做到这一点。

      【讨论】:

      • 是的,但这不是一个好的做法,因为它让您有可能在两个 docker 中拥有不同的预编译版本,当其中一个更新而另一个不更新时。可以按照您描述的方式进行,但我的拙见不推荐。
      • 换句话说,你的目的更倾向于单体实现而不是 docker 实现。第二个更一致,如果你让我建议的话。这与 docker 哲学相去甚远
      • 我觉得 Docker 哲学的一个重要部分是图像应该是自包含的,而在容器之间共享文件实际上并不能实现这一点。卷方法也没有更新策略(“第一次创建容器时卷将自动填充”在更新映像时对您没有帮助),并且在 Kubernetes 等集群环境中效果不佳。
      • 我同意这一点,但我只是根据问题回答。最好的方法是尝试使用所有独立的图像,但不幸的是,如果你失去一致性,那不是起点。最好的方法是达到两个条件:第一个,一致性和第二个自包含。如果你想要两者,你必须改变架构,设计并回答第一个问题“不要那样做”。最后,如果我必须在牺牲两个条件之一之间做出决定,我更喜欢一致的系统。考虑一下卷共享理念是 k8s 使用 configmap 来参数化部署的原理,例如。无论如何,谢谢
      猜你喜欢
      • 1970-01-01
      • 2019-12-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-19
      • 1970-01-01
      相关资源
      最近更新 更多