在开发工作流中使用 Docker 可以极大提高生产力,它消除了"它在我机器上都可以运行"
这类典型的错误,在不同的机器上运行也只需要一个 Docker 守护进程,而不需要其他组件。
什么是 Docker
Docker 是一个可以运行容器平台,为了运行这些容器,Docker 使用了操作系统级的虚拟化技术,你可以把容器看作是一个轻量级版本的虚拟机。
你在 Docker 平台上运行的所有容器都是相互隔离的。要启动一个容器,你需要一个 Docker 镜像,这个镜像是你的容器的模板,你可以从 Docker Hub 中获取已经预定义的镜像,或者通过编写 Dockerfile 文件来配置自己的镜像。
为什么要 Docker 化开发工作流
上面我已经提到了在你的开发环境中使用 Docker 的好处。这是一个事实,它摆脱了典型的"它在我的机器上可以工作"的问题,除此之外,还有其他一些好处:
- 让团队成员之间的开发工作流程更加标准化
- 如果你也使用 Docker 进行部署,则减少了针对生产环境的 bug(生产和开发之间的配置可以很相似)。
开始
首先创建一个新的文件夹,将我们的项目放在其中,然后我创建一个 Dockerfile 文件:
代码语言:javascript复制$ mkdir node-docker && cd node-docker
$ touch Dockerfile
我们将在 Dockerfile 中配置一个 express 应用,内容如下所示:
代码语言:javascript复制FROM node:latest
WORKDIR /usr/src/app
COPY package*.json ./
ENV PORT 5000
RUN npm cache clear --force && npm install
FROM 是告诉 Docker 从 Docker Hub 获取一个名为 node(版本:latest)的镜像。
WORKDIR 设置所有即将执行的命令的目录。
COPY 的作用就是复制文件到 WORDIR 中来。
ENV 在容器中设置一个环境变量,名称为 PORT,值为 5000
RUN 执行我们传递进来的命令,在这里会清除 npm 缓存,然后安装package.json
中的所有依赖项。
ENTRYPOINT 会在 Docker 容器启动的时候执行你在这里插入的命令。
现在,我们已经准备好了我们的 Dockerfile 文件,我们需要一个简单的 express 应用,可以在容器内运行。为此,我们创建两个新的文件。
代码语言:javascript复制$ touch server.js package.json
package.json
文件中新增两个依赖关系,一个是 express,另外一个是nodemon。
{
"name": "node-docker",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"start": "nodemon server.js"
},
"author": "Jakob Klamser",
"license": "MIT",
"dependencies": {
"express": "^4.17.1"
},
"devDependencies": {
"nodemon": "^2.0.4"
}
}
express 应用在点击主页面时,返回一个简单的 HTML。对应的 server.js 内容如下所示。
代码语言:javascript复制const express = require('express');
const app = express();
const PORT = process.env.PORT || 5000;
app.get('/', (req, res) => {
res.send(`
<h1>Express Docker</h1>
<span>This projects runs inside a Docker container</span>
`);
});
app.listen(PORT, () => {
console.log(`Listening on port ${PORT}!`);
});
在我们开始将 MongoDB 容器与我们的 express 容器一起设置之前,我们希望将一些文件从运行的容器中排除,这个时候就可以使用 .dockerignore
来进行配置,.dockerignore
文件的语法与 .gitignore
文件完全相同。
# Git
.git
.gitignore
# Docker
Dockerfile
docker-compose.yml
# NPM dependencies
node_modules
最后同样重要的是我们需要定义一个 docker-compose.yml
。这个文件将包含两个不同容器,同时运行 express 应用和 MongoDB,先创建这个文件。
$ touch docker-compose.yml
然后配置如下所示的该文件内容:
代码语言:javascript复制version: '3'
services:
api:
build: .
ports:
- "5000:5000"
depends_on:
- mongo
volumes:
- "./:/usr/src/app"
- "reserved:/usr/src/app/node_modules"
mongo:
image: "mongo"
ports:
- "27017:27017"
volumes:
reserved:
version: 定义了我们要使用的 docker-compose 的版本,版本3和版本2之间有不少差异,所以在选择版本时要注意!
services: 这是定义服务的部分,这里我们定义了 express api 和 mongo 两个服务。
build & image: build 告诉 Docker 从 Dockerfile 中构建一个镜像。在我们的例子中,我们希望它使用当前目录下的 Dockerfile,这就是为什么我们把.
作为一个参数,因为这定义了当前的目录。image 告诉 Docker 从 Docker Hub 中拉取一个已经存在的镜像。
ports & volumes: 如 ports 的名字所示,我们在这里定义端口,冒号是一个映射操作符,我们将容器的5000端口映射到主机系统的5000端口,在本例中,我们就可以在容器之外访问应用程序。同样的道理也适用于 MongoDB 的端口映射。volumes 也做类似的事情,我们将本地代码的目录映射到容器的 WORKDIR 中,这样一来,如果我们修改了源代码中的任何内容,容器就会立即做出反应。
reserved: 这是一个特殊的卷,如果本地的 node_modules 文件夹存在,则不会覆盖容器内部的 node_modules 文件夹。
然后现在我们可以运行如下所示的命令,Docker 将根据我们的 Dockerfile 文件配置创建一个镜像,然后同时运行两个容器(api和mongo)。
代码语言:javascript复制$ docker-compose up
如果你想停止这些容器,可以执行下面的命令:
代码语言:javascript复制$ docker-compose down
总结
这里我们只是介绍的一个简单的 Docker 开发环境配置,当然也可以很容易地进行扩展。如果你想改变数据库或添加一个 Nginx 来渲染你的前端,只需在 docker-compose.yml
中添加一个新的服务或改变一个现有的服务即可。当然同样地我们也可以很容易地对 .Net Core、Java 或者 Golang 应用进行 Docker 容器化。
原文链接:https://klamser.dev/dockerize-your-development-environment-for-nodejs
K8S进阶训练营,点击下方图片了解详情