# Docker 构建node服务

# 构建镜像

# 创建一个node应用

1. mkdir node-docker
2. cd node-docker
3. npm init -y
4. npm install ronin-server ronin-mocks
5. touch server.js
1
2
3
4
5

打开 server.js,输入下列内容,然后通过node server.js启动服务。


const ronin     = require( 'ronin-server' )
const mocks     = require( 'ronin-mocks' )

const server = ronin.server()

server.use( '/', mocks.server( server.Router(), false, true ) )
server.start()
1
2
3
4
5
6
7
8

通过下列命令测试服务的post请求


 curl --request POST \
  --url http://localhost:8000/test \
  --header 'content-type: application/json' \
  --data '{"msg": "testing" }'
1
2
3
4
5

通过下列命令测试服务的GET请求

curl http://localhost:8000/test
1

# 创建一个Dockerfile

Dockerfile是一个文本文档,其中包含用户可以在命令行上调用以组装镜像的所有命令, 当我们告诉Docker通过执行docker build命令来构建映像时,Docker读取这些指令并逐个执行它们,并创建一个Docker镜像。

node-docker 项目根目录下新建Dockerfile文件

输入下列内容,告诉Docker我们想要为应用程序使用node:12.18.1作为基本镜像

FROM node:12.18.1
1

输入下列内容,告诉node,使用production环境

ENV NODE_ENV=production
1

输入下面内容,这指示Docker使用此路径作为所有后续命令的默认位置。这样,我们不必键入完整的文件路径,而是可以根据工作目录使用相对路径。

WORKDIR /app
1

输入下列内容,将我们的package.json和package-lock.json文件放入镜像中,第一个参数是要复制的命令,第二个是要复制到哪里去

COPY ["package.json", "package-lock.json*", "./"]
1

输入下列内容,运行node项目的依赖安装

RUN npm install --production
1

输入下列内容,将我们的项目代码复制到镜像里面

COPY . .
1

输入下列内容,当我们运行容器的时候要执行的命令

CMD [ "node", "server.js" ]
1

最后我们的Dockerfile会有下列内容

FROM node:12.18.1
ENV NODE_ENV=production

WORKDIR /app

COPY ["package.json", "package-lock.json*", "./"]

RUN npm install --production

COPY . .

CMD [ "node", "server.js" ]
1
2
3
4
5
6
7
8
9
10
11
12

在当前目录下构建镜像

docker build --tag node-docker .
1

查看我们的镜像,此时会看到我们刚构建的node-docker 镜像

docker images
1

# 镜像tag

镜像名称由斜杠分隔的名称组成,名称组件可能包含小写字母,数字和分隔符。 分隔符定义为一个句点,一个或两个下划线或一个或多个破折号。 名称组件不能以分隔符开头或结尾。一个镜像可以有多个标签。接下来我们为镜像创建第二个标签,并查看其图层。

下面的命令为镜像新建一个tag,他并咩有创建新的镜像,标签指向相同的镜像。通过docker images可以看到他们有相同的id.

docker tag node-docker:latest node-docker:v1.0.0
1

使用下面命令移除我们刚创建的镜像tag

docker rmi node-docker:v1.0.0
1

# 运行容器

运行容器时,由于需要与外部进行交互,所以需要暴露容器内的端口,并映射到容器外部,所以使用--publish 该参数的第一个值是容器外部的值,第二个是容器内部的值。--publish 3000:8000。将容器内部的8000端口暴露给外部的3000

执行下面命令运行容器

docker run --publish 3000:8000 node-docker
1

请求测试


curl --request POST \
  --url http://localhost:3000/test \
  --header 'content-type: application/json' \
  --data '{"msg": "testing"}'
1
2
3
4
5

# 后台运行

执行下面命令,容器在后端执行,此时可以关闭控制台

docker run -d -p 8000:8000 node-docker
1

# 查看,停止,启动,命名 容器

docker ps 查看正在运行的容器
docker ps -all 查看所有的容器
docker stop <容器id或者容器名>
docker rm 容器id或者容器名1 容器id或者容器名2 容器id或者容器名3 ...  可以移除多个容器
docker run -d -p 8000:8000 --name rest-server node-docker 用rest-server 名启动容器
1
2
3
4
5

# 开发项目并连接数据库

# 设置数据存放目录

$ docker volume create mongodb
$ docker volume create mongodb_config
1
2

# 创建一个网络

现在,我们将创建一个网络,我们的应用程序和数据库将使用该网络相互通信。 该网络称为用户定义的桥接网络,它为我们提供了不错的DNS查找服务,可在创建连接字符串时使用该服务。

 docker network create mongodb
1

# 在容器中运行MongoDB

我们可以在容器中运行MongoDB,并将其附加到上面创建的卷和网络上。 Docker将从Hub提取映像并在本地为您运行。

docker run -it --rm -d -v mongodb:/data/db \
  -v mongodb_config:/data/configdb -p 27017:27017 \
  --network mongodb \
  --name mongodb \
  mongo
1
2
3
4
5

# 修改代码

将下列代码放入项目的 server.js

const ronin     = require( 'ronin-server' )
const mocks     = require( 'ronin-mocks' )
const database  = require( 'ronin-database' )
const server = ronin.server()
console.log(process.env.CONNECTIONSTRING,'---')
database.connect( process.env.CONNECTIONSTRING )
server.use( '/', mocks.server( server.Router(), false, false ) )
server.start()
1
2
3
4
5
6
7
8

执行依赖ronin-database安装

npm install ronin-database
1

# 重新运行容器

重新构建我们的node-docker镜像

docker build --tag node-docker .
1

重新运行我们的容器,这一次,我们需要设置CONNECTIONSTRING环境变量, 告诉应用程序使用哪个连接字符串来访问数据库。我们将在docker run命令中执行此操作。 如果报错就删除我们之前创建的rest-server容器

docker run \
  -it --rm -d \
  --network mongodb \
  --name rest-server \
  -p 8000:8000 \
  -e CONNECTIONSTRING=mongodb://mongodb:27017/yoda_notes \
  node-docker
1
2
3
4
5
6
7

使用下列命令测试我们的容器是否正常

curl --request POST \
  --url http://localhost:8000/notes \
  --header 'content-type: application/json' \
  --data '{
"name": "this is a note",
"text": "this is a note that I wanted to take while I was working on writing a blog post.",
"owner": "peter"
}'
1
2
3
4
5
6
7
8

# 使用Compose进行本地开发

新建docker-compose.dev.yml并粘贴下列内容

version: '3.8'

services:
 notes:
  build:
   context: .
  ports:
   - 8080:8080
   - 9229:9229
  environment:
   - SERVER_PORT=8080
   - CONNECTIONSTRING=mongodb://mongo:27017/notes
  volumes:
   - ./:/code
  command: npm run debug

 mongo:
  image: mongo:4.2.8
  ports:
   - 27017:27017
  volumes:
   - mongodb:/data/db
   - mongodb_config:/data/configdb
volumes:
 mongodb:
 mongodb_config:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

package.json中新增下列内容

 "debug": "nodemon --inspect=0.0.0.0:9229 server.js"
1

安装nodemon依赖


npm install nodemon

1
2
3

使用 docker-compose重启容器

docker-compose -f docker-compose.dev.yml up --build
1