前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >利用Docker轻松搭建全栈开发环境

利用Docker轻松搭建全栈开发环境

原创
作者头像
老码小张
发布2023-12-08 18:55:57
9746
发布2023-12-08 18:55:57
举报
文章被收录于专栏:玩转全栈

我在上篇文章里面,前端研发需要知道的Docker 这篇文章里面提到过,Docker这种容器化的思路,不仅仅是后端研发同学需要掌握的利器,前端研发同学也需要学会使用,有时候前端同学也不可避免的会做一些全栈的项目,此时如果用到 MySQL,Redis,这样的一些组件的话,如果能有一个配置将其串起来,清晰的管理,那将会极大的增加代码的可维护性,以及在后续引导其他新同学参与项目研发的话,那也将非常的便捷。

为了方便咋们了解Docker的好处,我列举一下两种方式的优劣势对比,没有对比就没以后伤害。

特性

使用 Docker

不使用 Docker

环境一致性

Docker 容器确保了开发、测试和生产环境的一致性,减少了“在我机器上能运行”的问题。

环境可能因机器配置差异而不一致,需要手动确保各个环境相似。

依赖管理

所有依赖都打包在容器中,与宿主机隔离。

依赖需要在每台机器上手动管理,可能会与系统其他部分发生冲突。

部署速度

容器可以快速启动,部署速度快。

部署可能需要复杂的安装和配置过程。

可移植性

容器可以在任何支持 Docker 的机器上运行,提高了应用的可移植性。

应用的移植可能受限于操作系统和环境配置。

开发流程

Docker 可以简化开发流程,例如使用 docker-compose 一键启动所有服务。

开发流程可能涉及多个步骤,需要手动启动各个服务。

资源隔离

容器提供了资源隔离,有助于保证应用稳定运行。

应用直接运行在宿主机上,可能会受到其他应用或系统进程的影响。

我们可以看到,在使用Docker的情况下,我们的维护行是大大的加强,下面,我将使用一个具体点的demo,当时是一个非常简单的例子来串一下一个全栈项目 ,项目的结构我打算做成这个样子。

代码语言:javascript
复制
/myapp
|-- /backend
|   |-- Dockerfile
|   |-- package.json
|   |-- server.js
|-- /frontend
|   |-- Dockerfile
|   |-- package.json
|   |-- /src
|   |-- /public
|-- docker-compose.yml

这个项目将会使用到:

  • koa提供的后端接口服务
  • MySQL提供数据支持,持久化
  • redis提供数据换成,提升我们接口性能
  • react作为前端,简单做一个请求数据的例子

前端里面只做一个简单的示例,就是通过接口获取数据,但是获取数据的话,有一个特性,如果redis里面已经有了,直接从redis中返回,如果没有,先去查MySQL,查到了,缓存到Redis里面,然后返回,例子比较僵硬,但是他基本上串起了一个简单而又复杂的全栈项目给串起来了。下面是我们这个项目的业务流程图,方便你直观的了解这个架构。

实现方案剖析

这里,我们后端需要链接MySQL,Redis等服务,按照我们常规的思路,我们需要在本地启动一个MySQL服务器,启动一个Redis服务,那么,使用Docker的方式,我们又该如何处理呢?我们使用docker-compose的方式,然后利用依赖关系,即,整个架构是前端依赖后端,后端有依赖 MySQL,和Redis,然后整个docker-compose我们就可以进行编写了。

代码语言:javascript
复制
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 来启动这个服务:

代码语言:javascript
复制
# 参与这个项目的同学只需要一个这样的命令,就可以进入开发了,不需要单独去启动MySQL,启动后端,启动Redis
docker-compose up  --build

一些细节注意

这里,我们的前端项目frontend 可以直接使用 react 生成脚手架来生成:

代码语言:javascript
复制
npx create-react-app frontend

随后我们添加 Dockerfile,因为我们的前端项目在docker-compose.yml 里面描述是需要build,因为这个镜像是咋们自己的。同理后端项目也是需要build的,等会也会给出后端项目的 Dockerfile,我们注意到 db和cache没有build,因为这些镜像我们可以直接从docker hub拖下来用,这就很强大了,这意味着我们根本不需要在本地启动什么MySQL,Redis服务,开箱即用。

代码语言:javascript
复制
FROM node:14

WORKDIR /app

COPY package*.json ./

RUN npm install

COPY . .

EXPOSE 3000

CMD ["npm", "start"]

然后后端的Dockerfile是:

代码语言:javascript
复制
FROM node:14

WORKDIR /app

COPY package*.json ./

RUN npm install

COPY . .

EXPOSE 4000

CMD ["npm", "start"]

可以看到,几乎和前端完全一样,只是 暴露的端口不一样而已。

另外一个细节,我们使用 volume做了目录映射,在 frontend,backend以及MySQL 服务的配置中都有,那么,有什么作用呢?

  • frontend和backend中做目录映射就是方便我们做本地开发,我们本地修改的会迅速反应到容器的目录中,实现热更新。
  • MySQL上做的目录映射的作用是,我们可以MySQL数据的同步,下次我们启动容器的时候,数据还在,如下图。

进一步思考

这种方式就真的合理吗?我们为了演示docker的优势,而生搬硬套做了这么一个全栈项目,使用docker-compose的方式串了起来,但是在实际的项目中,有没有更加优雅的方式。

实际上,你项目的基础建设,或者需求决定了你可以选择的优雅方式,如果你想快速验证一个业务模型,我认为这个方式会非常快速,但是如果你考虑做一个3年乃至更长的业务,这样的方式是很危险的,前后端分离应该是更好的方式。

如,MySQL可以接入腾讯云上的MySQL服务Redis也是可以使用腾讯云上的服务,注意在使用这些服务的时候,一定不要将自己的密钥等明文写在代码里面,最好是通过环境变量的方式。

Dockerfile指定环境变量的方式很简单

代码语言:javascript
复制
docker run --env-file ./env.list -d my-node-app
docker-compose --env-file [development|production].env up

docker-compose.yml 里面直接指定环境变量的方式也很简单

代码语言:javascript
复制
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套环境,开发和线上,这样似乎有返璞归真了,前端就安安心心的做前端就好了,至于其他的,交给云服务吧。

我正在参与2023腾讯技术创作特训营第四期有奖征文,快来和我瓜分大奖!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 实现方案剖析
    • 一些细节注意
      • 进一步思考
      相关产品与服务
      云数据库 MySQL
      腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档