首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >前端研发需要知道的Docker

前端研发需要知道的Docker

原创
作者头像
brzhang
发布2023-11-27 22:46:18
5610
发布2023-11-27 22:46:18
举报
文章被收录于专栏:玩转全栈玩转全栈

作为一名前端开发者,你可能会说,Docker和我有啥关系,我又用不到,因为它看起来更像是后端或者DevOps的领域。但实际上,Docker对前端开发同样有很多好处,比如:

  • Docker可以帮助你在本地环境中快速搭建和模拟生产环境。你知道,有时候在本地开发环境中一切正常,但代码一到生产环境就出问题了。使用Docker,你可以创建一个与生产环境尽可能接近的容器,这样就可以减少“在我机器上可是好的”这类问题。
  • 简化团队协作。想象一下,新同事加入项目,他们需要配置本地环境。传统方式可能需要安装各种依赖、设置数据库等等,这既费时又可能出错。但有了Docker,他们只需要拉取一个镜像,运行一个容器,所有环境就配置好了,可以立即开始工作,这极大的降低了新同事介入工作的成本。所以用上了Docker,你再也不用写一篇文档来告知如何配置本地开发环境,巴拉巴拉一大堆。
  • 前端项目通常会依赖后端API或数据库等服务,甚至有时候还需要配置代理来解决本地开发跨域的问题,这些真的很头疼。使用Docker Compose,你可以定义一个多容器的应用,其中包括前端应用、API服务器、数据库等,一键启动整个应用栈。

简单的理解Docker的原理

Docker是基于Linux容器(LXC)技术,但提供了更高层次的抽象和更简单的工具链。Docker使用容器来运行应用,容器是一种轻量级的、可执行的软件包,其中包含了运行某个软件所需的代码、运行时、系统工具、库和设置。这种实现与虚拟机不同,它们不需要包含操作系统的完整副本,而是与宿主机共享内核,只包含应用程序及其依赖,因此它们更加轻量级和快速。Docker使用镜像来创建容器,镜像是一个轻量级、可移植、自给自足的软件运行环境的模板。你可以把它想象成一个快照,任何时候基于这个镜像启动的容器,都会是一个一模一样的环境。

Docker的工作流程通常包括构建、运输和运行。你首先在本地构建一个Docker镜像,然后可以将它推送到Docker Hub或其他注册中心,最后在任何安装了Docker的机器上运行这个镜像,就可以启动一个一致的容器环境。

就此打住,废话不宜过多,但是考虑到前端研发同学可能有些并没接触过docker,还是有点点必要科普一下。

基于Docker开发前端应用

学以致用,假社我们就是奔着统一环境的目的来的,解决新同学加入团队需要配置一堆本地开发环境的痛点,此时我们采取使用Docker的开发方式是如何的呢?

再次假设,如我们需要使用react来开发前端应用,此时,我们的第一步,依然是创建一个 react应用,npx create-react-app my-app-docker完了之后,随后就有一些不同了,我们要多追加一个Docker描述文件Dockerfile,其内容如下,然后竟就是打包镜像,启动容器,剩下的开发体验和本地启动服务完全一样。

# 使用官方Node.js作为基础镜像
FROM node:latest

# 设置工作目录
WORKDIR /app

# 复制package.json和package-lock.json(如果有)
COPY package*.json ./

# 安装项目依赖
RUN npm install

# 复制项目文件到工作目录
COPY . .

# 暴露容器的端口号
EXPOSE 3000

# 运行前端服务
CMD ["npm", "start"]

随后,我们执行 docker build -t my-app-docker .来打一个镜像出来。这个命令的解析是:

  • docker build: Docker CLI命令,用于构建Docker镜像。
  • t my-frontend-appt标志指定要创建的镜像的名称(在这里是my-frontend-app)。这个名称可以在后续的docker run命令中使用。
  • .: 指定Dockerfile所在的路径。在这个例子中,.表示当前目录。

执行的过程如下所示。

打镜像完毕之后,我们可以看到Docker的管理段中,Images里面会多一个镜像,就是我们刚才打的镜像。

此时,有了这个镜像,我们就可以启动这个镜像了,你可以直接使用界面的方式启动,就是点击那个play按钮,出来后:

这里面有一些配置参数,映射端口号容器名字映射目录环境变量等。但是我更加推荐你使用命令的方式来,表示用习惯了会更加快。

启动镜像

docker run -p 3000:3000 my-frontend-app,这个命令的含义如下:

  • docker run: 运行一个Docker容器的命令。
  • p 3000:3000p标志将容器内部的端口映射到宿主机的端口。3000:3000的意思是将容器的3000端口映射到宿主机的3000端口。
  • my-frontend-app: 这是你之前构建的镜像的名称。

好了之后,你应该可以在 http://localhost:3000 看到你的react应用了。

如何实现文件同步呢?

我们不可能在开发的过程中变更一样代码,就打一个镜像,这样做效率也太低了,有什么办法吧本地变更的文件同步到容器中呢?答案就是我们使用界面方式启动时,里面看到的那个 Volumes。命令来执行就是:

docker run -p 3000:3000 -v $(pwd):/app my-frontend-app

-v $(pwd):/app-v标志用于挂载卷。$(pwd)是当前工作目录的路径,/app是容器内的路径。这意味着你的工作目录将被挂载到容器的/app目录,从而实现文件同步。

我们试着改变一下本地的文件,从命令行里面可以看到,容器的环境中同步到了变化,开始编译了。

这就意味着,你的本地的变更,将会同步反应到容器中,实现本地代码变更,热更新到界面上,和本地开发无任何不同。

镜像太大,有没有办法变小?

我们可以使用比较小的基础镜像,以改用node:alpine,因为Alpine Linux版本的镜像通常更小。

可以看到,我们的镜像直接就小了一半。从1.64G压缩到了 735M。有人会讲了,这依然很大啊,还有办法更小吗?

所以,除此之外,还有更加进一步的优化办法吗?当然,方法还不仅仅如此,比如,我们还可以尝试多阶段构建,因为,react最终的产物就是一堆html+css+js。所以,我们这么玩,分两个阶段。

# 第一阶段:构建
FROM node:alpine as build-stage
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

# 第二阶段:运行
FROM nginx:alpine
COPY --from=build-stage /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

但是,我们发现,这个似乎只建议在生成环境打镜像的时候用,开发的时候,并不合适,因为我们要做目录映射,要做热更新。

更上一层楼

如果,我们需要依赖某几个后端服务,怎么办呢?答案是,我们可以使用**Docker Compose,**这个compose的意思就可以简单的理解为组合。比如一个简单的:

version: '3'  # 指定了使用的Compose文件版本
services:  # 定义了多个服务(容器),可以相互协作
  frontend:  # 定义了名为“frontend”的服务
    build: .  # 指定Dockerfile所在的目录(当前目录),用于构建镜像
    ports:
      - "3000:3000"  # 将容器的3000端口映射到宿主机的3000端口
    volumes:
      - .:/app  # 将当前目录挂载到容器的/app目录,实现代码同步
    depends_on:
      - backend  # 表示“frontend”服务依赖于“backend”服务

  backend:  # 定义了名为“backend”的服务
    image: "my-go-service"
		ports:
		  - "5000:5000"  # 将容器的5000端口映射到宿主机的5000端口,这样你就可以通过宿主机的端口访问后端服务。

这个docker-compose.yml文件定义了两个服务:一个前端服务和一个后端服务。前端服务会构建一个Docker镜像(基于当前目录下的Dockerfile),注意,因为我们frontend这个服务里面有build字段,所以才会构建,并且将宿主机的当前目录挂载到容器内部的/app目录,以便实现实时同步。后端服务则直接使用一个已经存在的镜像,他不需要构建。一个docker-compose.yml可以只方一个服务都是OK的。

docker-compose up 命令到底做了些啥

简单的讲,当你在包含docker-compose.yml文件的目录中运行docker-compose up命令时,Docker Compose会执行以下操作:

  1. 读取配置:Docker Compose首先读取docker-compose.yml文件,解析里面定义的服务、网络、卷等配置。
  2. 构建镜像:对于那些需要构建的服务(如我们的例子里面,frontend),Docker Compose会根据Dockerfile构建镜像。构建的镜像会被存储在本地的Docker镜像库中。
  3. 拉取镜像:对于直接指定了镜像名称的服务(如backend),如果本地没有这个镜像,Docker Compose会从Docker Hub或其他指定的镜像仓库拉取镜像,本地有当然就直接用本地的了。
  4. 创建网络:Docker Compose会创建一个默认的网络,使得定义在docker-compose.yml文件中的服务可以互相通信。
  5. 启动容器:Docker Compose会根据配置启动服务对应的容器。如果有depends_on配置,Docker Compose会先启动依赖的服务。
  6. 应用卷映射:对于定义了卷映射的服务,Docker Compose会将指定的宿主机目录或文件挂载到容器内的相应位置。
  7. 端口映射:Docker Compose会将容器的端口映射到宿主机的端口,使得可以从宿主机访问容器内部的应用。
  8. 日志输出:默认情况下,Docker Compose会捕获并输出所有容器的stdout和stderr到终端,让你可以实时看到输出。
  9. 运行状态:除非你在命令后添加了d参数来让服务在后台运行,否则Docker Compose会保持在前台,并且当你按下Ctrl+C时停止所有服务。

通过这个过程,Docker Compose简化了多容器Docker应用的管理,你不需要手动执行一系列的docker builddocker run命令来启动你的应用。所有的配置都可以在docker-compose.yml文件中声明,使得整个过程更加简洁。

因此,我们看到,实际上在前端开发上,也可以使用docker,docker这个技术针对的不仅仅是后端各种服务,他更加像是一种思想,万物皆容器。

我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!

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

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简单的理解Docker的原理
  • 基于Docker开发前端应用
    • 启动镜像
      • 如何实现文件同步呢?
        • 镜像太大,有没有办法变小?
        • 更上一层楼
          • docker-compose up 命令到底做了些啥
          相关产品与服务
          容器镜像服务
          容器镜像服务(Tencent Container Registry,TCR)为您提供安全独享、高性能的容器镜像托管分发服务。您可同时在全球多个地域创建独享实例,以实现容器镜像的就近拉取,降低拉取时间,节约带宽成本。TCR 提供细颗粒度的权限管理及访问控制,保障您的数据安全。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档