如何在构建步骤中填充Docker卷以供其他容器使用

54次阅读
没有评论

问题描述

正在使用Docker Compose构建一个基于Nginx的Web应用程序,该应用程序使用Nginx作为反向代理,将流量转发到Flask和Grafana的Docker实例。现在的任务是将一个静态站点生成器(SSG)(如Jekyll)集成到这个设置中。
最直接的方法是:
1. 使用Jekyll容器持续运行并通过Nginx重定向(jekyll serve)来提供站点的静态部分。
2. 在Jekyll Docker镜像中运行构建命令,并通过Docker卷与Nginx共享输出。
3. 在Nginx容器中生成站点。

前两种方法的缺点是它们创建了一个只使用一次然后持久存在的Jekyll Docker实例。在第一种情况下,Nginx可以直接处理服务。在第三种情况下,Jekyll和Nginx之间没有分离。这对于将流量路由到其他Docker实例的Nginx也是有用的。

问题是,是否有一种方法可以通过Jekyll的Dockerfile来填充Docker卷,然后由Nginx挂载它?具体步骤如下:
1. docker-compose build:构建站点并填充static-site卷。
2. docker-compose up -d:Nginx挂载static-site卷并提供它。

这种方法是否有意义?

解决方案

请注意以下操作注意版本差异及修改前做好备份。

方案1

根据回答1,docker-compose build命令无法填充卷。卷是在Docker镜像/容器之外的主机系统上的存储空间。docker build从不写入主机系统,并且在docker build期间无法挂载卷。docker-compose build只是为您运行docker build,并且也无法在主机上运行或写入任何内容。

因此,您可以通过以下方式修改您的Compose文件:
1. 在一个Docker容器中运行生成器(写入命名卷),在另一个容器中运行服务器(如Nginx),并将同一个命名卷挂载到服务器容器中。这将是您的第二种情况。
2. 使用docker-compose up命令启动这两个容器。第一个容器将填充静态文件,第二个容器将提供服务。第一个容器在完成后将保持运行,您可以忽略它,但这肯定不太美观。不幸的是,您不能使用类似docker-compose up --rm的命令自动删除不必要的Jekyll容器。

因此,您最好的选择是自己启动Jekyll容器(docker run --rm jekyll:xyz -v ...:...),--rm选项将在容器完成后删除容器。然后使用实际的服务器运行docker-compose up命令。

方案2

回答1中提到了一种使用busybox容器的解决方案。您可以首先运行Jekyll(SSG),将其输出的HTML站点通过busybox容器复制到一个命名卷中,然后挂载该卷。以下是相关代码的示例:

version: '3'
services:
  jekyll:
    image: jekyll/jekyll:latest
    volumes:
      - ./site:/srv/jekyll
  busybox:
    image: busybox:latest
    volumes:
      - static-site:/srv/static-site
    command: cp -r /srv/jekyll/_site/* /srv/static-site/
  nginx:
    image: nginx:latest
    volumes:
      - static-site:/usr/share/nginx/html
    ports:
      - 80:80

volumes:
  static-site:

在上面的示例中,我们定义了三个服务:jekyllbusyboxnginxjekyll服务使用Jekyll镜像,并将当前目录下的site目录挂载到容器的/srv/jekyll目录。busybox服务使用busybox镜像,并将static-site卷挂载到容器的/srv/static-site目录。然后,我们使用cp命令将Jekyll生成的站点复制到static-site卷中。最后,nginx服务使用Nginx镜像,并将static-site卷挂载到容器的/usr/share/nginx/html目录,以便Nginx可以提供站点。

请注意,上述示例仅供参考,您可能需要根据自己的需求进行适当的修改。

希望这些解决方案对您有所帮助!

正文完