问题描述
正在使用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:
在上面的示例中,我们定义了三个服务:jekyll
、busybox
和nginx
。jekyll
服务使用Jekyll镜像,并将当前目录下的site
目录挂载到容器的/srv/jekyll
目录。busybox
服务使用busybox镜像,并将static-site
卷挂载到容器的/srv/static-site
目录。然后,我们使用cp
命令将Jekyll生成的站点复制到static-site
卷中。最后,nginx
服务使用Nginx镜像,并将static-site
卷挂载到容器的/usr/share/nginx/html
目录,以便Nginx可以提供站点。
请注意,上述示例仅供参考,您可能需要根据自己的需求进行适当的修改。
希望这些解决方案对您有所帮助!