Docker 部署 Node 项目

docker是一个开源的应用容器引擎,可以为我们提供安全、可移植、可重复的自动化部署的方式。

为什么要用 Docker 呢?这个文档一开始就说得很清楚了,这里只关注如何使用 Docker 部署一个 Node 项目。

创建 Node 项目

package.json

创建一个 package.json 文件,描述应用程序及其依赖:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"name": "docker_web_app",
"version": "1.0.0",
"description": "docker web app in nodejs",
"main": "index.js",
"scripts": {
"start": "node index.js"
},
"keywords": [
"docker"
],
"author": "ryoma",
"license": "ISC",
"dependencies": {
"express": "^4.16.4"
}
}

Demo 应用

index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const express = require("express");

// Constants
const PORT = 8080;
const HOST = "0.0.0.0";

// App
const app = express();
app.get("/", (req, res) => {
console.log("receiving request...");
res.send("Hello Docker!\n");
});

app.listen(PORT, HOST);
console.log(`Running on http://${HOST}:${PORT}`);

准备工作

请提前安装好 Docker

Dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
FROM node:8.9

# Create app directory
WORKDIR /usr/src/app

# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)
COPY package*.json ./

RUN npm install
# If you are building your code for production
# RUN npm ci --only=production

# Bundle app source
COPY . .

EXPOSE 8080
CMD [ "npm", "start" ]

现在来解释上面的定义:

  • FROM:指定基础镜像(必须是 Dockerfile 文件的第一个指令),如果镜像不存在默认从 Docker Hub 下载
  • WORKDIR:设置 Dockerfile 中的RUN、CMD 和 ENTRYPOINT 指令执行命令的工作目录;可以出现多次,如果使用相对路径则为相对于WORKDIR上一次的值,
  • RUN:会在一个新的容器中执行任何命令,然后把执行后的改变提交到当前镜像
  • EXPOSE:告诉 Docker 这个容器在运行时会监听哪些端口
  • CMD:CMD指令中指定的命令会在镜像运行时执行,在 Dockerfile 中只能存在一个,如果使用了多个 CMD 指令,则只有最后一个 CMD 指令有效。
    • 当出现 ENTRYPOINT 指令时,CMD 中定义的内容会作为 ENTRYPOINT指令的默认参数
    • RUN 和 CMD 都是执行命令,差异在于 RUN 中定义的命令会在执行 docker build 命令创建镜像时执行,而 CMD 中定义的命令会在执行 docker run 命令运行镜像时执行

.dockerignore

.gitignore 文件功能类似,用户忽略文件——这里指的是当构建镜像时,需要忽略的内容

1
2
node_modules
npm-debug.log

构建镜像

构建镜像

这里 ryoma1992 是我本人在 Docker Hub 中的账号,在构建镜像时,可以不用

1
docker build -t ryoma1992/node-web-app:1.0.0 .

image.png

docker login

如果在 docker build 时遇到此类错误,可以使用 docker login 先登录

1
2
Step 1/7 : FROM node:8.9
Get https://registry-1.docker.io/v2/library/node/manifests/8.9: unauthorized: incorrect username or password

查看镜像

使用 docker image ls 命令即可查看之前构建的镜像

image.png

运行

运行

1
docker run -d -p 20000:8080 ryoma1992/node-web-app:1.0.0

image.png

其中:

  • -d:表示后台运行
  • -p:表示端口映射关系,这里是本地 20000 映射容器内的8080

查看运行情况

使用 docker ps 来查看容器

image.png

浏览器访问

image.png

docker logs

image.png

上传镜像

docker tag

https://docs.docker.com/engine/reference/commandline/tag/
这里我提前编译了一个版本,镜像命名为 node-web-app:1.0.1

1
2
3
4
5
// 格式
docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]

// 实际运行
docker tag node-web-app:1.0.1 ryoma1992/node-web-app:1.0.1

上传

1
docker push ryoma1992/node-web-app:1.0.1

image.png

Docker Hub 查看

image.png

去部署服务器运行

之前的运行是在本地运行的,但是在上一步我们将镜像推到了 Docker Hub。现在在一台新服务器中运行:

拉取镜像 & 运行

image.png

注意到第一行:本地没有目标镜像,故而会从 Docker 仓库中下载

访问

image.png

image.png

资料