探索Docker在前端开发中的应用一:背景

Docker with node

Docker是一项具有划时代意义的开源项目,它在服务端开发以及部署中大放异彩,本着对优秀技术的不断学习态度,非常建议将Docker作为你下一项学习的技术。

本文作为Docker在前端中应用的背景篇章,会对Docker及其优势做精简的介绍,然后列举一些前端开发、测试、部署过程中遇到的问题,希望可以借助Docker优雅地解决。

场景

一、在开发过程中,有没有遇到过以下场景:

  1. 需要自己配置proxy解决跨域请求问题
  2. 接手一个新项目之后,想要跑起来,并没有想象中的那么流畅,除了前端依赖,还要配置若干系统内容
    • npm i
    • npm start
    • Error XXX服务未配置
  3. 一个Node服务(比如SSR、打印服务、普通的数据处理服务),在部署的时候,脚本控制权并不在前端手中,容易出现一些配合问题
  4. 后端项目需要在本地运行,你需要安装全部的后端环境,然后这些环境在你开发下一个项目的时候,你还在考虑如何能清理干净。
    • MySql
    • MongoDb
    • Java
    • PHP
    • Redis
    • Nginx

二、在搭建团队基础服务过程中,有没有遇到过以下场景:

  1. 需要在服务器上部署一个项目要安装若干的基础服务
  2. 你发现系统上已经存在了旧版本的服务,你不确定升级该服务,会影响系统上的哪些应用,但是不升级,你的应用不支持安装

三、在学习过程中,是否有过以下场景:

  1. 搭建一个普通的博客,都需要花费大量时间安装一些基础服务:
    • PHP环境
    • Apache
    • 各种数据库服务
  2. 如果有一天你不需要了,还要花费时间去清理
  3. 项目开发完之后,还要考虑服务端的环境问题
  4. 你的一个Demo项目,希望在任何服务器都能快速部署

需求总结

我们将我们的需求汇总一下,我们希望的功能有:

  1. 开发所需的非前端环境一键配置
  2. 所需的服务方便配置、简单移除
  3. 项目开发配置完成后,方便部署在不同平台并且运行效果一致
  4. 其他人接手项目后,能够快速搭建好环境,并且运行起项目

Docker介绍

Docker的官方化介绍,可以在其官网[1]中了解到,对于我们来说Docker就是一个将项目运行所需所有环境打包到一个虚拟化容器中的工具,
同时,借助Docker,我们也可以非常方便的获取所需的依赖环境。

举个例子:我的项目需要在本地安装MySQL服务。

只需要在命令行使用Docker使用mariadb镜像启动一个容器即可。

1
2
3
4
docker run \
--name some-mariadb --rm \
-p 3306:3306 -e MYSQL_ROOT_PASSWORD=password \
mariadb:latest

使用用户名root,密码:password即可成功连接MySQL。

docker mysql

如果想停止,直接按下Ctrl+\,服务又从电脑中移除,非常干净。

备注:为何这里不是Ctrl+C来终止命令,可以参阅本文[3]

该命令中有几个参数具体分享一下:

  • –rm 容器结束时,移除container,与之相对的有-d
  • -p 映射容器端口到主机端口,主机端口:容器端口
  • -e Env 环境变量
  • -d –detach 后台运行,和–rm不能同时使用
  • -v 挂载数据卷,bind的方式

接着启动数据库的例子,我们会发现,在结束掉服务后,下次再启动会发现数据全没了,我们如果希望将自己的数据保存在本地,那么可以增加-v参数。

1
2
3
4
5
docker run \
--name some-mariadb --rm \
-p 3306:3306 -e MYSQL_ROOT_PASSWORD=password \
-v /you/data/path:/var/lib/mysql
mariadb:latest

这样本地路径/you/data/path就会将MySQL产生的数据持久化保存了,每次启动MariaDB都会还原之前的数据了。

以上我们便体验了Docker的一大特点快速部署,即快速将MySQL服务部署到你的电脑上,无论是Windows/OSX/Linux系统,都是一段命令搞定,大大节省了时间和精力。

这样在我们的开发服务器上,只需要存储一些配置和数据文件,执行文件完全交由Docker管理。

举个例子:我需要使用Nginx做一个接口转发

我们需要在开发中需要用到该接口:https://yapi.thisjs.com/mock/21/antd/games,我需要使用nginx对其进行一些代理配置,这样我们只需要创建一个.conf文件,然后使用Docker启动一个Nginx挂载该conf文件到conf.d/目录下即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
# proxy.conf

server {
listen 8080;
location / {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header Cache-Control private;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
proxy_pass https://yapi.thisjs.com/mock/21/antd/;
}
}

在配置目录下执行该命令

1
2
3
4
5
docker run \
--name proxy-server \
-v "$(pwd)/proxy.conf":/etc/nginx/conf.d/proxy.conf:ro \
-d -p 8080:8080 \
nginx

这时候,我们即可访问 http://localhost:8080/games,即可获取到所需要的数据。

当我们开发/调试结束后,如果需要将nginx容器停止并移除可以参考以下命令。

1
2
3
4
5
6
# 查看正在运行中的container
docker ps
# 停止名称为 proxy-server 的container
docker stop proxy-server
# 删除名称为 proxy-server 的container
docker container rm proxy-server

至此,Docker已经基本满足了我们的两个需求:

  1. 开发所需的非前端环境一键配置
  2. 所需的服务方便配置、简单移除

但是还没有完全达到,我们希望所需环境一键配置,而不是一键又一键的配置,因此希望能在下一个篇章里介绍Docker更轻松维护服务的相关内容。

安装Docker

看到这,你可能还没有安装Docker,其实Docker安装非常的简单。比如Mac,只需要下载镜像然后直接安装即可:

安装Docker

其他系统的Docker安装都非常的简单,可以参考这篇文章介绍:

安装 Docker

安装完之后

安装完之后,不如尝试启动一个普通的前端项目。

1
2
3
4
docker run \
-p 80:80 --name react-demo \
--rm \
mrxf/craantdbasic:latest

这是一个基于create react app的前端项目,启动之后直接访问 localhost即可看到页面。

结语

不能为了用Docker而用Docker,否则会出现Docker也成了我们开发中的一项没有必要的服务。遇到问题,还是要以前端的方式解决。

以下以2个场景进行分析:

1.开发中的代理请求

如果是单一的代理请求来解决跨域问题的场景,那么最佳方案是以前端的方案解决

在现代前端框架脚手架中都集成了非常方便的proxy方案,以Create React App[2]为例,就提供了http和https代理功能,在未eject的项目的package.json文件中增加一项配置即可。

1
"proxy": "http://url.to.poxy",

Creact React App在执行eject之后,与其他基于Webpack的项目都可以通过配置webpack.config.js,在devServer中新增proxy即可。

1
2
3
4
5
6
proxy: {
'/api': {
target: 'http://localhost:3000',
pathRewrite: {'^/api' : ''}
}
}

只有在遇到比较特殊的情况下,我们才会去配置Nginx

  1. 项目请求多个URL,我们需要将某些地址做转发,以阻止其访问原来的地址。
  2. 直播数据流地址

对于场景1,我们需要Nginx + Hosts的配合来实现。首先修改Hosts将原来的访问地址转发到本地,然后使用nginx来将其指向目标地址。

1
2
3
4
5
6
7
8
{
listen 80;
server_name api.serverurl.com;
location / {
...其他配置...
proxy_pass http://127.0.0.1:4300;
}
}

2.前端项目部署问题

前端线上部署到底要不要用Docker?纯静态前端项目完全不需要,因为前端项目更依赖网络资源和浏览器资源,因此常规场景下,CDN才是纯静态项目的部署方案。

附录

[1]Docker: Empowering App Development for Developers

[2]Proxying API Requests in Development

[3]Ctrl+C does not kill mysqld