我是如何用docker进行前端开发的

370 阅读6分钟

前言

嗨,大家好,我是一名前端开发。当我在进行项目开发时,总是遇到一些问题,不知道屏幕外的你是否也有同感

  • 开发、生产、测试环境不一致,开发环境下可用的服务挪到生产上不可用
  • 每个开使用的设备可能不一致,mac,window。就算一致,每个人的设备上具体的开发环境也不一致,可能会导致代码在我的电脑上能跑,在其他人的电脑上不能跑的现象。 那么,有什么好的工具可以解决这个问题吗?它就是docker 我们想要的是:在每个平台上,代码都以相同的环境运行,启动

基础环境

docker,docker-compose docs.docker.com/get-docker/ 你可以通过docker-compose -v来检查是否安装成功,docker-compose一般会随着docker一起被下载到本地

打破传统思维

我们是不是可以打破传统前端开发的思维呢,让我们往下看一看

传统开发

我相信有90%的前端同学,在新接收一份前端项目代码时,都会这样做

  • git clone xxx,clone新代码
  • npm i 安装依赖并全局安装一些软件,我曾经就因为本地python版本的原因浪费了一个上午去看问题
  • npm run dev 启动本地服务器 这样的流程没问题。但是,就像我上文说的,可能因为某个环境而导致项目不能启动,难道你没有遇到过吗

换个思路

那我们是不是可以通过docker启动项目呢,答案是肯定的,这样的好处是什么呢

  • 不用考虑每个人的设备情况,我们的项目一般FROM node-xxx,所以我们每个人的基础镜像都是linux无论你使用的设备是mac还是windows

    Alpine Linux is a Linux distribution built around musl libc and BusyBox. The image is only 5 MB in size and has access to a package repository that is much more complete than other BusyBox based images. This makes Alpine Linux a great image base for utilities and even production applications. Read more about Alpine Linux here and you can see how their mantra fits in right at home with Docker images.

  • 不用考虑本级的环境,我们可以把所有需要的环境,都通过Dockerfile声明好(不仅仅是node_modules)。所以到这里我们每个人的开发环境一定是和生产环境是一致的了,再也不会出现,我本地是ok的,线上不ok的现象了

进入实战

  • mkdir node-docker && cd node-docker
  • 初始化npm,npm init -y
  • vim index.js,并贴入下列代码
var express = require('express')
var app = express()

// respond with "hello world" when a GET request is made to the homepage
app.get('/', function (req, res) {
  res.send('hello world')
})
app.listen(8111)

传统开发

  • npm i express --save
  • package.json中的script中插入代码"dev": "node ./index.js"
  • 执行npm dev,访问localhost:8111,返回hello world

docker开发

  • 删除本地node_modules文件夹
  • 增加Dockerfile文件
FROM node:16-alpine

WORKDIR /usr/src

COPY package*.json ./

RUN npm install

WORKDIR /usr/src/app

COPY . .

EXPOSE 8111
  • 字段解析
    • FROM: 继承的基础镜像,这里使用了体积更小的node:16-alpine
    • WORKDIR /usr/src, 这里在容器中使用了/usr/src目录,如果没有则会创建,相当于mkdir -p /usr/src && cd /usr/src
    • package.json package-lock.jsoncopy 到当前目录,也就是上一步骤的/usr/src目录
    • RUN npm install 在当前目录安装依赖node_modules
    • WORKDIR /usr/src/app 切换目录为WORKDIR /usr/src/app,并将本地代码全部copy到/usr/src/app中,这里你可能要问,为什么node_modules要在源代码上级目录?因为我会在docker-compose中做文件映射,将源代码映射到容器的/usr/src/app目录,如果你本地没有node_modules,根据node npm的规则,它会向上一目录寻找node_modules中的模块
    • COPY . .,将当前目录的源代码copy到usr/src/app目录
    • EXPOSE 8111,将容器肿的8111端口导出,也就是我们node监听的端口
  • 增加docker-compose.yml文件
version: '3.1'
services:
    widget:
        build:
            context: .
            dockerfile: Dockerfile
        image: node-docker 
        container_name: node-docker 
        volumes: 
            - .:/usr/src/app
            - /usr/src/app/node_modules
        restart: always
        ports:
            - "8111:8111"
        command: npm run dev
  • 字段解析
    • 通过build参数,使用当前目录下的Dockerfile构建镜像
    • 镜像名称为node-docker,可以通过docker image ls查看
    • container_name,容器名称,可以通过docker container ls查看
    • volumes,重点,将当前目录下代码全部映射到/usr/src/app下,并删除/usr/src/app/node_modules,因为我们期望node_modules是上一步通过Dockerfile文件安装的,这样我们才可以保证在开发时和生产环境的依赖是一致的
  • 在根目录执行docker compose up你就可以看到镜像打包和容器启动的过程了
  • 可以在当前目录,通过执行docker-compose ps查看容器状态
  • 打开浏览器,访问localhost:8111

遇到问题

  • 我们做了本地代码到容器的映射,但是为什么我修改本地代码的时候,刷新页面不生效呢?这个时候要使用nodemon,关于nodemon的作用我们可以看看它的官网www.npmjs.com/package/nod…

nodemon is a tool that helps develop node.js based applications by automatically restarting the node application when file changes in the directory are detected.

简单来说,就是当文件变化时,可以重新启动服务,展示最新的服务。所以我们使用nodemon来重新修改package.json中的script命令 - npm i nodemon --save-dev - 修改package.json,"dev": "node ./index.js" -> "dev": "nodemon ./index.js", - 执行docker-compose up --build重新构建image,并启动容器 - 这个时候我们进行文件的修改,将hello wordl -> hello docker,刷新页面就是生效的了

总结

  • 我们可以通过docker启动项目,保持生产环境,开发环境环境一致
  • 通过对Dockerfile docker-compose.yml文件的编写,降低开发同学上手项目的难度
  • 对于没有前端环境的同学(运营,测试,运维),我们只需要把docker image扔给他就好了
  • 方便ci/cd
  • 本文只提到了在开发时,如何更好的使用docker。在生产环境时的用法感兴趣的同学可以留言,如果有需要的话,我会写一份结合ci/cd,生产环境的docker使用方法
  • 这里仅用一个很简单的项目做的例子,开发前端项目也是一样的,其中Dockerfile文件我们可以对他做很多优化,感兴趣的同学请留言。
  • 我们还可以创建.dockerignore文件来减少image的体积,我通常的做法是cp .gitignore .dockerignore简单暴力有效