在 docker compose 中的服务之间共享动态文件的正确方法
Right way to share dynamic files between services in docker compose
我有以下 docker-compose 文件。我想与 nginx
和 web
服务
共享来自 react
服务的静态文件
version: '3.6'
services:
web:
image: shahrukh/learnup:web
networks:
- main
command: >
sh -c "python manage.py collectstatic --no-input
&& gunicorn learnup.wsgi:application --bind 0.0.0.0:8000 --reload"
volumes:
- static_cdn:/var/www/learnup/static_cdn
depends_on:
- react
react:
image: shahrukh/learnup:react
volumes:
- static_cdn:/app/Learnup-Frontend/learnup/export-build/static
nginx:
image: shahrukh/learnup:nginx
restart: always
ports:
- 80:80
command: nginx -g 'daemon off;'
volumes:
- static_cdn:/var/www/static
networks:
- main
depends_on:
- web
- react
networks:
main:
volumes:
static_cdn:
为此,我创建了一个命名卷 static_cdn
,将在其上执行以下步骤
- 来自
react
服务的我的 React 应用程序的构建文件夹将是
安装在这里
- 来自 django 的 collectstatic 命令的静态数据将被复制到这里
- 这与
nginx
共享,后者将提供它。
这是我面临的问题。
在使用最新版本更新我的 react
容器映像时,卷 static_cdn
没有最新的静态文件,因为在我使用后没有重新创建该卷docker-compose up -d
所以我的问题是 在这种情况下,在服务之间共享文件的最佳方式是什么? 以便它负责更新。
请注意,我知道首先使用 docker-compose down -v
停止并删除卷然后执行 docker-compose up -d
的解决方案。但这会导致我不希望在生产中出现停机时间。
同时执行 docker-compose pull react
以提取 react
的最新映像,然后执行 docker-compose -d
也没有用,因为卷没有更新。 Docker compose 目前不提供任何选项来强制在启动时重新创建卷。我也不能使用 docker volume rm ...
,因为卷正在使用中。
另外,请注意,我可以在启动时创建反应构建文件,而不是将其作为图像的一部分来解决问题。但是我做不到,因为我是 运行 系统上资源有限的应用程序 npm run build
就崩溃了。
您似乎想使用 docker-compose 进行生产。
docker-compose 不适用于生产用途。例如,它不会尝试重新启动失败的容器。它还会在重新创建容器之前销毁容器,从而导致停机。请考虑使用 docker-swarm(更简单)或 kubernetes(行业 de-facto 标准)。
这些工具知道如何执行更新、管理持久卷、处理硬件故障等。
在生产环境中处理静态文件
如果您的静态内容确实是代码,基本上是开发更改,您可能希望在出现错误时恢复并且使用 git 之类的版本进行版本控制,然后使用它创建一个容器并对其进行版本控制.
当您发布新版本并通知您的生产集群时,它会使用合理的更新策略自动更新您的所有生产节点。如果您发现新版本有问题,您可以回滚。
如果它真的是动态的,您可能需要为您的卷使用另一个驱动程序,例如映射到网络文件系统。
无论如何看看 docker-swarm 和 kubernetes 是如何工作的,它会阐明什么对生产环境有好处。
本地工作
在本地,使用-v选项删除容器并有几秒的停机时间是完全可以接受的。
通常,如果您正在构建 React 应用程序,您会希望将其编译为静态文件以进行部署。您将使用像 Webpack 这样的工具来生成一组构建的 HTML、Javascript 和 CSS 文件,然后您可以直接为那些使用 Nginx 的文件提供服务。如果您使用的是像 Create React App 这样的入门工具包,您通常可以 运行 类似
npm run build
它会创建一个包含构建文件的 dist
目录。
既然你已经有了一个Nginx容器,这意味着你不需要一个单独的React容器;你可以从 Nginx 容器中提供编译后的文件。此外,后端容器可能不需要直接访问构建的 front-end 代码,它只需要从 Nginx 代理提供服务。
这意味着您可以在单个 multi-stage 构建中使用构建的 React 应用程序构建 Nginx 代理映像。该 Dockerfile 看起来或多或少像:
FROM node:lts AS react
WORKDIR /app
COPY package*.json .
RUN npm install
COPY . .
RUN npm run build
FROM nginx
COPY --from=react /app/dist /usr/share/nginx/html
COPY default.conf.template /etc/nginx/templates/
# Base image includes a useful CMD
在 Compose 设置中,您不需要专用的 React 容器,如前所述;您不需要卷,因为您已经将应用程序构建到静态文件中;您不需要重述图像中已经声明的 command:
之类的内容;您可以使用 Compose 为您提供的 default
网络。这会给你一个 much-simplified docker-compose.yml
文件:
version: '3.6'
services:
web:
build: ./backend
image: shahrukh/learnup-web:latest
nginx:
build: ./frontend
image: shahrukh/learnup-nginx:latest
restart: always
ports:
- 80:80
depends_on:
- web
我有以下 docker-compose 文件。我想与 nginx
和 web
服务
react
服务的静态文件
version: '3.6'
services:
web:
image: shahrukh/learnup:web
networks:
- main
command: >
sh -c "python manage.py collectstatic --no-input
&& gunicorn learnup.wsgi:application --bind 0.0.0.0:8000 --reload"
volumes:
- static_cdn:/var/www/learnup/static_cdn
depends_on:
- react
react:
image: shahrukh/learnup:react
volumes:
- static_cdn:/app/Learnup-Frontend/learnup/export-build/static
nginx:
image: shahrukh/learnup:nginx
restart: always
ports:
- 80:80
command: nginx -g 'daemon off;'
volumes:
- static_cdn:/var/www/static
networks:
- main
depends_on:
- web
- react
networks:
main:
volumes:
static_cdn:
为此,我创建了一个命名卷 static_cdn
,将在其上执行以下步骤
- 来自
react
服务的我的 React 应用程序的构建文件夹将是 安装在这里 - 来自 django 的 collectstatic 命令的静态数据将被复制到这里
- 这与
nginx
共享,后者将提供它。
这是我面临的问题。
在使用最新版本更新我的 react
容器映像时,卷 static_cdn
没有最新的静态文件,因为在我使用后没有重新创建该卷docker-compose up -d
所以我的问题是 在这种情况下,在服务之间共享文件的最佳方式是什么? 以便它负责更新。
请注意,我知道首先使用 docker-compose down -v
停止并删除卷然后执行 docker-compose up -d
的解决方案。但这会导致我不希望在生产中出现停机时间。
同时执行 docker-compose pull react
以提取 react
的最新映像,然后执行 docker-compose -d
也没有用,因为卷没有更新。 Docker compose 目前不提供任何选项来强制在启动时重新创建卷。我也不能使用 docker volume rm ...
,因为卷正在使用中。
另外,请注意,我可以在启动时创建反应构建文件,而不是将其作为图像的一部分来解决问题。但是我做不到,因为我是 运行 系统上资源有限的应用程序 npm run build
就崩溃了。
您似乎想使用 docker-compose 进行生产。
docker-compose 不适用于生产用途。例如,它不会尝试重新启动失败的容器。它还会在重新创建容器之前销毁容器,从而导致停机。请考虑使用 docker-swarm(更简单)或 kubernetes(行业 de-facto 标准)。
这些工具知道如何执行更新、管理持久卷、处理硬件故障等。
在生产环境中处理静态文件
如果您的静态内容确实是代码,基本上是开发更改,您可能希望在出现错误时恢复并且使用 git 之类的版本进行版本控制,然后使用它创建一个容器并对其进行版本控制.
当您发布新版本并通知您的生产集群时,它会使用合理的更新策略自动更新您的所有生产节点。如果您发现新版本有问题,您可以回滚。
如果它真的是动态的,您可能需要为您的卷使用另一个驱动程序,例如映射到网络文件系统。
无论如何看看 docker-swarm 和 kubernetes 是如何工作的,它会阐明什么对生产环境有好处。
本地工作
在本地,使用-v选项删除容器并有几秒的停机时间是完全可以接受的。
通常,如果您正在构建 React 应用程序,您会希望将其编译为静态文件以进行部署。您将使用像 Webpack 这样的工具来生成一组构建的 HTML、Javascript 和 CSS 文件,然后您可以直接为那些使用 Nginx 的文件提供服务。如果您使用的是像 Create React App 这样的入门工具包,您通常可以 运行 类似
npm run build
它会创建一个包含构建文件的 dist
目录。
既然你已经有了一个Nginx容器,这意味着你不需要一个单独的React容器;你可以从 Nginx 容器中提供编译后的文件。此外,后端容器可能不需要直接访问构建的 front-end 代码,它只需要从 Nginx 代理提供服务。
这意味着您可以在单个 multi-stage 构建中使用构建的 React 应用程序构建 Nginx 代理映像。该 Dockerfile 看起来或多或少像:
FROM node:lts AS react
WORKDIR /app
COPY package*.json .
RUN npm install
COPY . .
RUN npm run build
FROM nginx
COPY --from=react /app/dist /usr/share/nginx/html
COPY default.conf.template /etc/nginx/templates/
# Base image includes a useful CMD
在 Compose 设置中,您不需要专用的 React 容器,如前所述;您不需要卷,因为您已经将应用程序构建到静态文件中;您不需要重述图像中已经声明的 command:
之类的内容;您可以使用 Compose 为您提供的 default
网络。这会给你一个 much-simplified docker-compose.yml
文件:
version: '3.6'
services:
web:
build: ./backend
image: shahrukh/learnup-web:latest
nginx:
build: ./frontend
image: shahrukh/learnup-nginx:latest
restart: always
ports:
- 80:80
depends_on:
- web