前言
嗨,大家好,我是一名前端开发。当我在进行项目开发时,总是遇到一些问题,不知道屏幕外的你是否也有同感
开发、生产、测试环境不一致,开发环境下可用的服务挪到生产上不可用。- 每个开使用的设备可能不一致,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- nodejs image :hub.docker.com/_/node
- 随便打开一个nodejs的
Dockerfile,你会发现如下代码FROM alpine:3.14,也就是说node的基础镜像是alpine - 我们在打开 hub.docker.com/_/alpine,发现…
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监听的端口
- FROM: 继承的基础镜像,这里使用了体积更小的
- 增加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简单暴力有效