所以我一直在努力部署dockerized应用程序。该应用程序包含一个React前端和一个Express API。
我的开发环境docker-compose.yml
如下所示:
version: '3'
services:
# Express Container
backend:
build: ./backend
expose:
- ${BACKEND_PORT}
env_file:
- ./.env
environment:
- PORT=${BACKEND_PORT}
ports:
- ${BACKEND_PORT}:${BACKEND_PORT}
volumes:
- ./backend:/backend
command: npm run devstart
links:
- mongo
# React Container
frontend:
build: './frontend'
expose:
- ${REACT_APP_PORT}
env_file:
- ./.env
environment:
- REACT_APP_BACKEND_PORT=${BACKEND_PORT}
ports:
- ${REACT_APP_PORT}:${REACT_APP_PORT}
volumes:
- ./frontend/src:/frontend/src
- ./frontend/public:/frontend/public
links:
- backend
command: npm start
mongo:
image: mongo
ports:
- "27017:27017"
但是我一直在努力构建用于生产的结构。
我已经看到基本上有3种选择:
我当时想使用选项3,因为它可以使开发和生产环境保持相似。 (如果结构不好,请告诉我,此应用程序有望收到大量流量。)
我是否应该忘记docker-compose并创建一个使用多阶段构建复制前端和后端代码的多阶段dockerfile?这样我可以部署一个Docker容器吗?
我的文件夹结构如下:
app/
.env
docker-compose.yml
docker-compose.prod.yml
.gitignore
frontend/
Dockerfile
... react stuff
backend
Dockerfile
.. express stuff
我会把这一切弄错吗?您如何将带有docker-compose的应用程序部署到生产环境中(最好在kubernetes上)。
我可以找到大量有关如何使这些东西在开发中运行的知识,但是当涉及到部署这种类型的堆栈的方向时,我就迷失了。
答案 0 :(得分:1)
您可能首先阅读Kubernetes documentation,并了解什么是简单的,什么不是简单的。您对部署和服务以及Ingress最感兴趣。具有关联的持久状态的MongoDB设置将更加复杂,您可能会看到预打包的解决方案,例如the stable/mongodb Helm chart或MongoDB's official operator。
请注意,Kubernetes设置的重要部分是几乎总是有多个Node,并且您对Pod将放置在哪个Node上没有太多控制。特别是,这意味着您显示的Docker Compose volumes:
在Kubernetes环境中无法正常工作-除了完成所有正常的Kubernetes部署工作之外,您还需要将应用程序源代码复制到每个节点。这是相同部署工作的两倍。通常,您会希望所有应用程序代码都包含在Docker映像中,并且典型的基于Node的Dockerfile看起来像
FROM node:10
WORKDIR /app
COPY package.json yarn.lock ./
RUN yarn install
COPY ./ ./
RUN yarn build
EXPOSE 3000
CMD yarn start
仅在docker-compose.yml
文件中显示:
volumes:
使您的容器与生产环境中的容器大不相同;删除它们。
不要打扰使容器内部端口可配置。在普通Docker,Docker Compose和Kubernetes中,您可以在部署时将容器内部端口重新映射到任意外部可访问端口。您可以在此处选择固定数字,这很好。
您显示的几个详细信息(例如,容器expose:
和要运行的默认command:
的端口)是映像的正确组成部分(每次运行映像时,它们都会相同),因此将它们移到Dockerfile中。
links:
这些天是多余的,您可以删除它们。在Docker Compose中,您始终可以通过其他服务的服务块名称来获得其名称。
在不同的环境中,其他相关服务的名称将有所不同。例如,当您实际在Docker之外开发应用程序时,MongoDB可能位于localhost
上,您显示的配置中为mongo
,在Kubernetes中为mongo.myapp.svc.cluster.local
,或者您可以选择运行它完全不在Docker之外。通常,您通常希望使用环境变量来配置它们。
这使您的docker-compose.yml
文件更像是:
version: '3'
services:
backend:
build: ./backend
environment:
- MONGO_URL: 'mongo://mongo'
ports:
- 3000:3000
frontend:
build: './frontend'
environment:
- BACKEND_URL: 'http://backend'
ports:
- 8000:8000
mongo:
image: mongo
ports:
- "27017:27017"
正如@frankd在他们的答案中暗示的那样,使用Webpack之类的工具将React应用程序预编译为一组静态文件也很普遍。取决于您实际部署的方式,可以提前运行此编译步骤,然后将那些已编译的Javascript和CSS文件推送到其他静态托管服务,然后将其完全从Docker / Kubernetes中删除。>
答案 1 :(得分:0)
我将前端和后端保持为完全独立的应用程序。他们每个人都在自己的GitHub存储库中,拥有自己的测试套件,Dockerfiles,Jenkins构建,所有内容。这使我们能够独立地对它们进行版本控制,从而允许更频繁的迭代。规模较小,风险较低的部署;更快,更高效的开发。
所有对后端的调用都在/ API /路径上,该路径由nginx入口控制器处理(非常简单),并适当地路由到后端服务。
答案 2 :(得分:0)
我喜欢选项1而不是3,因为它使前端和后端保持分离。一个巨大的优势是您可以将前端托管在AWS S3 with a CloudFront CDN之类的东西上。因此,所有静态内容都分发到世界各地的边缘服务器。这样可以很快将繁重的项目(图像,大型js库,css等)提供给最终用户,并使您的应用程序运行更快。