我在上篇文章里面,前端研发需要知道的Docker 这篇文章里面提到过,Docker这种容器化的思路,不仅仅是后端研发同学需要掌握的利器,前端研发同学也需要学会使用,有时候前端同学也不可避免的会做一些全栈的项目,此时如果用到 MySQL,Redis,这样的一些组件的话,如果能有一个配置将其串起来,清晰的管理,那将会极大的增加代码的可维护性,以及在后续引导其他新同学参与项目研发的话,那也将非常的便捷。
为了方便咋们了解Docker的好处,我列举一下两种方式的优劣势对比,没有对比就没以后伤害。
特性 | 使用 Docker | 不使用 Docker |
---|---|---|
环境一致性 | Docker 容器确保了开发、测试和生产环境的一致性,减少了“在我机器上能运行”的问题。 | 环境可能因机器配置差异而不一致,需要手动确保各个环境相似。 |
依赖管理 | 所有依赖都打包在容器中,与宿主机隔离。 | 依赖需要在每台机器上手动管理,可能会与系统其他部分发生冲突。 |
部署速度 | 容器可以快速启动,部署速度快。 | 部署可能需要复杂的安装和配置过程。 |
可移植性 | 容器可以在任何支持 Docker 的机器上运行,提高了应用的可移植性。 | 应用的移植可能受限于操作系统和环境配置。 |
开发流程 | Docker 可以简化开发流程,例如使用 docker-compose 一键启动所有服务。 | 开发流程可能涉及多个步骤,需要手动启动各个服务。 |
资源隔离 | 容器提供了资源隔离,有助于保证应用稳定运行。 | 应用直接运行在宿主机上,可能会受到其他应用或系统进程的影响。 |
我们可以看到,在使用Docker的情况下,我们的维护行是大大的加强,下面,我将使用一个具体点的demo,当时是一个非常简单的例子来串一下一个全栈项目 ,项目的结构我打算做成这个样子。
/myapp
|-- /backend
| |-- Dockerfile
| |-- package.json
| |-- server.js
|-- /frontend
| |-- Dockerfile
| |-- package.json
| |-- /src
| |-- /public
|-- docker-compose.yml
这个项目将会使用到:
前端里面只做一个简单的示例,就是通过接口获取数据,但是获取数据的话,有一个特性,如果redis里面已经有了,直接从redis中返回,如果没有,先去查MySQL,查到了,缓存到Redis里面,然后返回,例子比较僵硬,但是他基本上串起了一个简单而又复杂的全栈项目给串起来了。下面是我们这个项目的业务流程图,方便你直观的了解这个架构。
这里,我们后端需要链接MySQL,Redis等服务,按照我们常规的思路,我们需要在本地启动一个MySQL服务器,启动一个Redis服务,那么,使用Docker的方式,我们又该如何处理呢?我们使用docker-compose的方式,然后利用依赖关系,即,整个架构是前端依赖后端,后端有依赖 MySQL,和Redis,然后整个docker-compose我们就可以进行编写了。
version: '3.8'
services:
frontend:
build: ./frontend
ports:
- "3000:3000"
volumes:
- ./frontend/src:/app/src
depends_on:
- backend
backend:
build: ./backend
ports:
- "4000:4000"
volumes:
- ./backend:/app
depends_on:
- db
- cache
db:
image: mysql:5.7
#初始化数据库,创建一些表
command: --init-file /data/application/init.sql
#注意这里的环境变量最好是定义在 .env 里面,不要直接写在这里,我这里纯粹为了演示
environment:
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_DATABASE: myapp
MYSQL_USER: user
MYSQL_PASSWORD: password
ports:
- "3306:3306"
volumes:
- ./backend/db-data:/var/lib/mysql
- ./backend/init.sql:/data/application/init.sql
cache:
image: redis:alpine
ports:
- "6379:6379"
这里,我们主要看 这个 docker-compose.yml 文件中 depends_on: 项目,前端依赖后端,后端依赖了MySQL服务和Redis这个 cache 服务。
最终,我们会使用 docker-compose up
来启动这个服务:
# 参与这个项目的同学只需要一个这样的命令,就可以进入开发了,不需要单独去启动MySQL,启动后端,启动Redis
docker-compose up --build
这里,我们的前端项目frontend 可以直接使用 react 生成脚手架来生成:
npx create-react-app frontend
随后我们添加 Dockerfile,因为我们的前端项目在docker-compose.yml 里面描述是需要build,因为这个镜像是咋们自己的。同理后端项目也是需要build的,等会也会给出后端项目的 Dockerfile,我们注意到 db和cache没有build,因为这些镜像我们可以直接从docker hub拖下来用,这就很强大了,这意味着我们根本不需要在本地启动什么MySQL,Redis服务,开箱即用。
FROM node:14
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "start"]
然后后端的Dockerfile是:
FROM node:14
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 4000
CMD ["npm", "start"]
可以看到,几乎和前端完全一样,只是 暴露的端口不一样而已。
另外一个细节,我们使用 volume做了目录映射,在 frontend,backend以及MySQL 服务的配置中都有,那么,有什么作用呢?
这种方式就真的合理吗?我们为了演示docker的优势,而生搬硬套做了这么一个全栈项目,使用docker-compose的方式串了起来,但是在实际的项目中,有没有更加优雅的方式。
实际上,你项目的基础建设,或者需求决定了你可以选择的优雅方式,如果你想快速验证一个业务模型,我认为这个方式会非常快速,但是如果你考虑做一个3年乃至更长的业务,这样的方式是很危险的,前后端分离应该是更好的方式。
如,MySQL可以接入腾讯云上的MySQL服务,Redis也是可以使用腾讯云上的服务,注意在使用这些服务的时候,一定不要将自己的密钥等明文写在代码里面,最好是通过环境变量的方式。
Dockerfile指定环境变量的方式很简单
docker run --env-file ./env.list -d my-node-app
docker-compose --env-file [development|production].env up
docker-compose.yml
里面直接指定环境变量的方式也很简单
version: '3'
services:
webapp:
image: my-webapp:latest
ports:
- "5000:5000"
env_file:
- webapp.env
database:
image: postgres:latest
env_file:
- database.env
那么,这样一来,我们将会简化为,只有一个frontend,和backend,不在依赖MySQL和Redis了,而是将MySQL和Redis转移到云上了。同样的道理,backend何尝不是也可以通过这个方式转移呢,我们灵活点,比如我们可以将其转移到 Serverless上去。server less去做2套环境,开发和线上,这样似乎有返璞归真了,前端就安安心心的做前端就好了,至于其他的,交给云服务吧。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。