【问题标题】:Dockerized Nginx: Can static assets be updated without stopping the container?Dockerized Nginx:可以在不停止容器的情况下更新静态资产吗?
【发布时间】:2020-05-01 21:41:27
【问题描述】:

我设置了一个为静态网站提供资产的 Nginx 容器。这个想法是让网络服务器始终保持运行,并在重新编译时覆盖资产。目前 docker 设置如下所示:

docker-compose.yml:

version: '3'
services:
  web:
    build: ./app
    volumes:
      - site-assets:/app/dist:ro
  nginx:
    build: ./nginx
    ports:
      - 80:80
      - 443:443
    volumes:
      - site-assets:/app:ro
      - https-certs:/etc/nginx/certs:ro
    depends_on:
      - web

volumes:
  site-assets:
  https-certs:

Web(资产构建器)Dockerfile:

FROM node:latest
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY ./ .
RUN npm run generate

Nginx Dockerfile:

FROM nginx:latest
RUN mkdir /app
COPY nginx.conf /etc/nginx/nginx.conf

certbot 容器是单独管理的,与我遇到的问题无关,但 Nginx 容器确实需要能够挂载 https-certs 卷。

这个设置似乎很好,直到我意识到站点资产卷在第一次创建后不会更新。需要在每个应用程序部署上销毁并重新创建卷才能使其正常工作,需要停止 Nginx 容器以卸载卷。这种方法就这么多。

有没有办法在不关闭 Nginx 容器的情况下管理此设置中的应用程序数据?最好,我希望使用 docker-compose 文件以声明方式执行此操作,避免使用 multiple application instances,因为这不需要扩展,并避免使用 docker inspect 在文件系统上查找卷并直接修改它。

我希望除了“这是一个静态站点,你为什么不使用 Netlify 或 GitHub Pages?”之外,还有一个理智的答案。 :)

【问题讨论】:

  • 您能否说明您希望如何更新资产?在构建期间,该卷不可用。您希望在运行时执行此操作。这当然是可能的(我可能可以分享一个例子)。但目前尚不清楚您目前是如何尝试的。一些命令可能有助于说明。
  • @AndyShinn docker-compose -H ssh://myserver build; docker-compose -H ssh://myserver up -d 暂时,虽然我可能会设置一个 CD 管道来处理这个提交。

标签: docker nginx docker-compose static-site


【解决方案1】:

这是一个示例,可以将您的 npm run generate 从映像构建时间转移到容器运行时间。这是一个最小的示例,说明如何将进程移至运行时使卷在启动时对正在运行的容器和运行时的未来容器都可用。

以下docker-compose.yml

version: '3'
services:
  web:
    image: ubuntu
    volumes:
      - site-assets:/app/dist
    command: bash -c "echo initial > /app/dist/file"
    restart: "no"
  nginx:
    image: ubuntu
    volumes:
      - site-assets:/app:ro
    command: bash -c "while true; do cat /app/file; sleep 5; done"
volumes:
  site-assets:

我们可以在终端中使用docker-compose up 启动它。我们的nginx 服务器最初会丢失数据,但最初的web 服务将启动并生成我们的资产(内容为initial):

❯ docker-compose up  
Creating network "multivol_default" with the default driver
Creating volume "multivol_site-assets" with default driver
Creating multivol_web_1   ... done
Creating multivol_nginx_1 ... done
Attaching to multivol_nginx_1, multivol_web_1
nginx_1  | cat: /app/file: No such file or directory
multivol_web_1 exited with code 0
nginx_1  | initial
nginx_1  | initial
nginx_1  | initial
nginx_1  | initial

在另一个终端中,我们可以更新我们的资产(您的npm run generate 命令):

❯ docker-compose run web bash -c "echo updated > /app/dist/file"

现在我们可以看到我们的nginx 服务提供更新的内容:

❯ docker-compose up  
Creating network "multivol_default" with the default driver
Creating volume "multivol_site-assets" with default driver
Creating multivol_web_1   ... done
Creating multivol_nginx_1 ... done
Attaching to multivol_nginx_1, multivol_web_1
nginx_1  | cat: /app/file: No such file or directory
multivol_web_1 exited with code 0
nginx_1  | initial
nginx_1  | initial
nginx_1  | initial
nginx_1  | initial
nginx_1  | updated
nginx_1  | updated
nginx_1  | updated
nginx_1  | updated
^CGracefully stopping... (press Ctrl+C again to force)
Stopping multivol_nginx_1 ... done

希望这有助于说明在容器运行时利用卷安装的方法。

【讨论】:

  • 太棒了!在运行时生成是我的解决方案。由于静态站点生成器 (Nuxt) 抛出了 EBUSY: resource busy or locked, rmdir '/app/dist' 错误,因此我确实需要进行一些调整。为了解决这个问题,我为挂载的卷创建了一个单独的/live 目录,然后在创建后复制生成的资产。最终的 Web 命令是 command: bash -c "npm run generate; cp -r /app/dist/* /app/live/"
  • vuejs也有同样的问题,有没有办法避免重复目录?
  • 更新:如果您使用 Vue.js 获得 EBUSY: resource busy or locked, rmdir '/app/dist',@Tetra 会显示修复。原因是您无法删除包含静态资产/站点的共享 dist 文件夹。使用@Tetra 修复,您将添加新资产,但旧资产将保留。如果你想解决这个问题,在运行他的 npm run generate 之后,你应该运行 cd /app/live; rm -r *; cd - 删除所有旧资产
猜你喜欢
  • 1970-01-01
  • 2013-09-22
  • 2013-06-03
  • 1970-01-01
  • 2013-11-10
  • 1970-01-01
  • 1970-01-01
  • 2021-11-10
  • 2015-08-26
相关资源
最近更新 更多