Docker Compose 容器化 Node.js 应用:开发环境高效部署指南
引言
如果您正在积极开发一个应用程序,使用Docker可以极大地简化您的工作流程,并加速应用程序部署到生产环境的过程。在开发过程中采用容器化技术具有以下显著优势:
- 环境一致性: 您可以自由选择项目所需的编程语言和依赖项,而无需担心系统冲突问题。
- 环境隔离性: 有助于更轻松地排查问题,并加速新团队成员的上手过程。
- 环境可移植性: 允许您轻松打包代码并与他人共享。
本教程将详细指导您如何使用Docker为Node.js应用程序搭建开发环境。您将利用Docker Compose创建两个容器:一个用于Node应用程序,另一个用于MongoDB数据库。鉴于该应用程序需要Node和MongoDB协同工作,您的设置将实现以下功能:
- 将宿主机上的应用程序代码与容器内的代码同步,以便在开发过程中实时修改。
- 确保应用程序代码的更改无需重启即可生效。
- 为应用程序数据创建一个受用户和密码保护的数据库。
- 持久化存储这些数据。
完成本教程后,您将拥有一个在Docker容器中运行的、功能完备的鲨鱼信息应用程序。

前提条件
要顺利完成本教程,您需要满足以下条件:
- 一台运行Ubuntu 18.04的开发服务器,并配置了具有sudo权限的非root用户以及活动的防火墙。有关如何设置这些的指导,请参阅《初始服务器设置指南》。
- 服务器上已安装Docker,请按照《如何在Ubuntu 18.04上安装和使用Docker》的步骤1和2进行操作。
- 服务器上已安装Docker Compose,请按照《如何在Ubuntu 18.04上安装Docker Compose》的步骤1进行操作。
步骤1——克隆项目并修改依赖项
搭建此设置的第一步是克隆项目代码并修改其package.json
文件,该文件包含了项目的依赖项。您将在项目的devDependencies
中添加nodemon
,并指定在开发过程中使用它。使用nodemon
运行应用程序可确保在您对代码进行更改时自动重新启动。
首先,从Silicon Cloud社区的GitHub账户克隆nodejs-mongo-mongoose
存储库。该存储库包含了在《如何将MongoDB与Node应用程序集成》中描述的设置代码,该说明了如何使用Mongoose将MongoDB数据库与现有的Node应用程序集成。
将存储库克隆到名为node_project
的目录中。
- git clone https://github.com/do-community/nodejs-mongo-mongoose.git node_project
请进入node_project
目录。
- cd node_project
使用nano或您喜欢的编辑器打开项目的package.json
文件。
- nano package.json
在项目依赖之下、闭合大括号之上,创建一个新的devDependencies
对象,其中包括nodemon
。
以下是~/node_project/package.json
的原文中文释义:
“~” 代表用户的 home 目录
“node_project” 是一个文件夹名字
“package.json” 是一个 JSON 格式的配置文件。
...
"dependencies": {
"ejs": "^2.6.1",
"express": "^4.16.4",
"mongoose": "^5.4.10"
},
"devDependencies": {
"nodemon": "^1.18.10"
}
}
当您编辑完成后,保存并关闭文件。如果您使用的是nano文本编辑器,请按下CTRL+X
,然后按Y
,最后按ENTER
。
项目代码已设置完毕,相关依赖项也已修改,现在您可以开始重构代码以适应容器化工作流程。
第二步——配置您的应用程序以与容器协同工作
将您的应用程序修改为容器化工作流意味着使您的代码更加模块化。容器在不同环境之间提供可移植性,因此您的代码应尽可能与底层操作系统解耦。为了实现这一点,您将重构代码,更多地利用Node的process.env
属性。该属性返回一个包含运行时用户环境信息的对象。您可以在代码中使用该对象,通过环境变量在运行时动态分配配置信息。
从app.js
开始,这是您的主应用程序入口点。打开文件:
- nano app.js
在文件内部,您将看到一个端口常量的定义,以及一个使用该常量来指定应用程序将监听的端口的监听函数。
在中国的母语中把以下内容改述一遍,只需要一种选项:~/home/node_project/app.js
这是文章《使用Docker Compose 将 Node.js 应用程序进行容器化,用于开发》的第2部分(共10部分)。
内容片段:
...
const port = 8080;
...
app.listen(port, function () {
console.log('Example app listening on port 8080!');
});
通过使用 process.env
对象在运行时允许动态分配端口常量,重新定义端口常量。对常量定义和监听函数进行以下更改:
~/home/node_project/app.js
可以用以下的方式在中文中表达:
家目录/节点项目/app.js
...
const port = process.env.PORT || 8080;
...
app.listen(port, function () {
console.log(`Example app listening on ${port}!`);
});
您的新常量定义会动态地使用运行时传入的值或 8080
端口来分配端口。同样地,您已经重写了监听函数,使用了模板字面量,当监听连接时,它将插值端口值。因为您将在其他地方映射您的端口,这些修改将避免您不断修改此文件以适应环境变化。
当您编辑完成后,保存并关闭文件。
接下来,您将修改数据库连接信息,以删除任何配置凭据。打开包含此信息的 db.js
文件。
- nano db.js
目前,该文件具有以下功能:
- 导入 Mongoose,您正在使用的对象文档映射器(ODM),用于为您的应用程序数据创建模式和模型。
- 将数据库凭据设置为常量,包括用户名和密码。
- 使用
mongoose.connect
方法连接到数据库。
有关此文件的更多信息,请参见《如何将MongoDB与您的Node应用程序集成》第3步。
您修改文件的第一步将是重新定义包含敏感信息的常量。当前,这些常量的样式如下:
~/node_project/db.js
可以用一种方式进行本地化,仅需一个选项。
...
const MONGO_USERNAME = 'sammy';
const MONGO_PASSWORD = 'your_password';
const MONGO_HOSTNAME = '127.0.0.1';
const MONGO_PORT = '27017';
const MONGO_DB = 'sharkinfo';
...
可以使用 process.env
对象来捕获这些常量的运行时值,而不是将这些信息硬编码。将该块修改如下:
~/node_project/db.js
的中文翻译版本:~/node_project/db.js
...
const {
MONGO_USERNAME,
MONGO_PASSWORD,
MONGO_HOSTNAME,
MONGO_PORT,
MONGO_DB
} = process.env;
...
编辑完成后,请保存并关闭文件。
在这一点上,您已经修改了 db.js
以与您的应用程序环境变量配合使用,但您仍然需要一种将这些变量传递给您的应用程序的方式。创建一个 .env
文件,并提供值以在运行时传递给您的应用程序。
打开文件。
- nano .env
这个文件将包含您从 db.js
中移除的信息:您的应用程序数据库的用户名和密码,以及端口设置和数据库名称。请记得使用您自己的信息更新这里列出的用户名、密码和数据库名称。
~/node_project/.env
的另一种选项:
MONGO_USERNAME=sammy
MONGO_PASSWORD=your_password
MONGO_PORT=27017
MONGO_DB=sharkinfo
请注意,您已经删除了原始出现在 db.js
中的主机设置。现在,您需要在 Docker Compose 文件的级别上定义您的主机,同时提供其他关于您的服务和容器的信息。
在您完成编辑后,请保存并关闭此文件。
由于您的 .env
文件包含敏感信息,您将希望确保它被包含在您项目的 .dockerignore
和 .gitignore
文件中,以防止其复制到版本控制或容器中。
打开您的 .dockerignore
文件。
- nano .dockerignore
请将以下内容添加到文件的底部:
只需要一种选项,以下是对“~/node_project/.dockerignore
”进行中文本地化解释:
“只需一个路径选择,表示“~/node_project/.dockerignore
”。”
...
.gitignore
.env
在您完成编辑后保存并关闭文件。
这个代码仓库中的 .gitignore
文件已经包含了 .env
文件,但是请随意检查它是否存在。
- nano .gitignore
~/node_project/.gitignore
只需要一个选项,用中文进行同义转述:“~/node_project/.gitignore
文件”。
...
.env
...
在这一点上,您已成功从项目代码中提取出敏感信息,并采取措施来控制这些信息的复制方式和位置。现在,您可以优化数据库连接代码,以适应容器化工作流程。
第三步 – 修改数据库连接设置
您下一步需要做的是通过添加处理应用程序无法连接到数据库的代码,使您的数据库连接方法更加强健可靠。当使用 Compose 来处理容器时,引入这种弹性水平到您的应用程序代码是一种推荐的做法。
打开 db.js
进行编辑。
- nano db.js
注意之前添加的代码,以及用于 Mongo 连接 URI 的 URL 常量和 Mongoose 连接方法。
~/node_project/db.js
的汉语本地化的一个选项就是:
这是文章《使用Docker Compose 将 Node.js 应用程序进行容器化,用于开发》的第3部分(共10部分)。
...
const {
MONGO_USERNAME,
MONGO_PASSWORD,
MONGO_HOSTNAME,
MONGO_PORT,
MONGO_DB
} = process.env;
const url = `mongodb://${MONGO_USERNAME}:${MONGO_PASSWORD}@${MONGO_HOSTNAME}:${MONGO_PORT}/${MONGO_DB}?authSource=admin`;
mongoose.connect(url, {useNewUrlParser: true});
目前,您的 connect
方法接受一个选项,告诉 Mongoose 使用 Mongo 的新 URL 解析器。您可以在这个方法中添加选项来定义重新连接尝试的参数。通过创建一个 options
常量来包含相关信息,除了新的 URL 解析器选项。在您的 Mongo 常量下方,添加以下对 options
常量的定义:
请将以下内容以中文进行本地化改写:~/节点项目/数据库.js
...
const {
MONGO_USERNAME,
MONGO_PASSWORD,
MONGO_HOSTNAME,
MONGO_PORT,
MONGO_DB
} = process.env;
const options = {
useNewUrlParser: true,
reconnectTries: Number.MAX_VALUE,
reconnectInterval: 500,
connectTimeoutMS: 10000,
};
...
reconnectTries
选项告诉 Mongoose 无限期地继续尝试连接,而 reconnectInterval
以毫秒为单位定义连接尝试之间的时间间隔。connectTimeoutMS
将使 Mongo 驱动程序在连接尝试失败之前等待 10 秒钟。
现在您可以在 Mongoose 的 connect
方法中使用新的 options
常量来微调您的 Mongoose 连接设置。您还需要添加一个 Promise 来处理可能的连接错误。
目前,Mongoose 的连接方法如下所示:
~/节点项目/数据库.js
...
mongoose.connect(url, {useNewUrlParser: true});
删除现有的连接方法,并用包含 options
常量和 Promise 的以下代码替换。
请将以下路径更改为本地文件路径:~/node_project/db.js
...
mongoose.connect(url, options).then( function() {
console.log('MongoDB is connected');
})
.catch( function(err) {
console.log(err);
});
在成功连接的情况下,您的函数将记录一条适当的消息;否则,它将捕获并记录错误,以便您进行故障排除。
完成的文件将如下所示:
~/节点项目/数据库.js
const mongoose = require('mongoose');
const {
MONGO_USERNAME,
MONGO_PASSWORD,
MONGO_HOSTNAME,
MONGO_PORT,
MONGO_DB
} = process.env;
const options = {
useNewUrlParser: true,
reconnectTries: Number.MAX_VALUE,
reconnectInterval: 500,
connectTimeoutMS: 10000,
};
const url = `mongodb://${MONGO_USERNAME}:${MONGO_PASSWORD}@${MONGO_HOSTNAME}:${MONGO_PORT}/${MONGO_DB}?authSource=admin`;
mongoose.connect(url, options).then( function() {
console.log('MongoDB 已连接');
})
.catch( function(err) {
console.log(err);
});
在编辑完成后,保存并关闭文件。
您现在已经为应用程序代码添加了弹性,以处理应用程序无法连接到数据库的情况。有了这段代码,您可以继续使用 Compose 定义您的服务。
第四步 – 使用 Docker Compose 定义服务
这是文章《使用Docker Compose 将 Node.js 应用程序进行容器化,用于开发》的第5部分(共10部分)。
在你重构了代码之后,你可以开始编写docker-compose.yml
文件来定义你的服务。在Docker Compose中,服务是运行中的容器实例,而服务定义——即你在docker-compose.yml
文件中配置的信息——包含了每个容器镜像如何运行的详细说明。Compose工具允许你定义多个服务,从而构建复杂的多容器应用程序。
在定义你的服务之前,你将向你的项目添加一个名为“wait-for”的工具。这个工具的目的是确保你的应用程序仅在数据库启动任务完全完成后才尝试连接数据库。这个包装脚本利用netcat
来轮询特定的主机和端口,以确认它们是否接受TCP连接。通过测试数据库是否已准备好接受连接,它能有效控制应用程序连接数据库的时机。
尽管Compose允许你使用depends_on
选项来指定服务之间的依赖关系,但这种顺序仅基于容器是否正在运行,而非其“就绪状态”。对于你的设置而言,depends_on
并不是最佳选择,因为你希望应用程序仅在数据库启动任务(包括向管理员身份验证数据库添加用户和密码)完全完成后才进行连接。有关使用wait-for
及其他工具控制启动顺序的更多信息,请参阅Compose文档中的相关建议。
打开一个名为wait-for.sh
的文件。
nano wait-for.sh
输入以下代码到文件中以创建轮询函数:
~/node_project/app/wait-for.sh
的中文翻译为:~/node_project/app/等待.sh
。
#!/bin/sh
# original script: https://github.com/eficode/wait-for/blob/master/wait-for
TIMEOUT=15
QUIET=0
echoerr() {
if [ "$QUIET" -ne 1 ]; then printf "%s\n" "$*" 1>&2; fi
}
usage() {
exitcode="$1"
cat << USAGE >&2
Usage:
$cmdname host:port [-t timeout] [-- command args]
-q | --quiet Do not output any status messages
-t TIMEOUT | --timeout=timeout Timeout in seconds, zero for no timeout
-- COMMAND ARGS Execute command with args after the test finishes
USAGE
exit "$exitcode"
}
wait_for() {
for i in `seq $TIMEOUT` ; do
nc -z "$HOST" "$PORT" > /dev/null 2>&1
result=$?
if [ $result -eq 0 ] ; then
if [ $# -gt 0 ] ; then
exec "$@"
fi
exit 0
fi
sleep 1
done
echo "Operation timed out" >&2
exit 1
}
while [ $# -gt 0 ]
do
case "$1" in
*:* )
HOST=$(printf "%s\n" "$1"| cut -d : -f 1)
PORT=$(printf "%s\n" "$1"| cut -d : -f 2)
shift 1
;;
-q | --quiet)
QUIET=1
shift 1
;;
-t)
TIMEOUT="$2"
if [ "$TIMEOUT" = "" ]; then break; fi
shift 2
;;
--timeout=*)
TIMEOUT="${1#*=}"
shift 1
;;
--)
shift
break
;;
--help)
usage 0
;;
*)
echoerr "Unknown argument: $1"
usage 1
;;
esac
done
if [ "$HOST" = "" -o "$PORT" = "" ]; then
echoerr "Error: you need to provide a host and port to test."
usage 2
fi
wait_for "$@"
当你完成添加代码后,请保存并关闭文件。
将脚本设为可执行。
chmod +x wait-for.sh
接下来,打开docker-compose.yml
文件。
nano docker-compose.yml
首先,通过将以下代码添加到文件中来定义Node.js应用程序服务:
~/node_project/docker-compose.yml
的中文本地表达如下:
version: '3'
services:
nodejs:
build:
context: .
dockerfile: Dockerfile
image: nodejs
container_name: nodejs
restart: unless-stopped
env_file: .env
environment:
- MONGO_USERNAME=$MONGO_USERNAME
- MONGO_PASSWORD=$MONGO_PASSWORD
- MONGO_HOSTNAME=db
- MONGO_PORT=$MONGO_PORT
- MONGO_DB=$MONGO_DB
ports:
- "80:8080"
volumes:
- .:/home/node/app
- node_modules:/home/node/app/node_modules
networks:
- app-network
command: ./wait-for.sh db:27017 -- /home/node/app/node_modules/.bin/nodemon app.js
Node.js 服务定义包括以下选项:
- build(构建): 此选项定义了当 Compose 构建应用程序镜像时将应用的配置选项,包括上下文(context)和 Dockerfile。如果您想使用来自 Docker Hub 等注册表的现有镜像,则可以使用
image
指令,并提供您的用户名、仓库和镜像标签信息。 - context(上下文): 此选项定义了镜像构建的构建上下文——在本例中,即当前项目目录。
- dockerfile: 此选项指定了当前项目目录中的 Dockerfile 作为 Compose 用于构建应用程序镜像的文件。有关此文件的更多信息,请参阅“如何使用 Docker 构建 Node.js 应用程序”。
- image(镜像), container_name(容器名称): 这些选项用于为镜像和容器命名。
- restart(重启策略): 此选项定义了重启策略。默认值为
no
(不重启),但您已将容器设置为除非停止(unless-stopped
)才重启。 - env_file(环境变量文件): 此选项告诉 Compose 您希望从构建上下文中的名为
.env
的文件中添加环境变量。 - environment(环境变量): 使用此选项可以添加您在
.env
文件中定义的 Mongo 连接设置。请注意,您没有将NODE_ENV
设置为development
,因为如果未设置NODE_ENV
,这是 Express 的默认行为。当部署到生产环境时,您可以将其设置为production
以启用视图缓存和更简洁的错误消息。另请注意,您已将db
数据库容器指定为宿主,如第2步所述。 - ports(端口映射): 此选项将宿主机的 80 端口映射到容器的 8080 端口。
- volumes(卷): 您在此处包含了两种类型的挂载:
- 第一种是绑定挂载(bind mount),它将宿主机上的应用程序代码挂载到容器上的
/home/node/app
目录。这将促进快速开发,因为您对宿主机代码所做的任何更改都会立即同步到容器中。 - 第二种是命名卷(named volume),名为
node_modules
。当 Docker 运行应用程序 Dockerfile 中列出的npm install
指令时,npm 将在容器上创建一个新的node_modules
目录,其中包含运行应用程序所需的包。然而,您刚刚创建的绑定挂载将隐藏这个新创建的node_modules
目录。由于宿主机上的node_modules
是空的,绑定挂载会将一个空目录映射到容器,从而覆盖新的node_modules
目录并阻止您的应用程序启动。命名卷node_modules
通过持久化/home/node/app/node_modules
目录的内容并将其挂载到容器来解决此问题,从而避免了绑定挂载的影响。
- 第一种是绑定挂载(bind mount),它将宿主机上的应用程序代码挂载到容器上的
注意:此部分是文章《使用Docker Compose 将 Node.js 应用程序进行容器化,用于开发》的第6部分(共10部分)。
您的绑定会将容器中的 node_modules
目录内容挂载到主机上,并且该目录的所有者将是 root
,因为这个命名卷是由 Docker 创建的。
如果主机上已经存在一个预先存在的 node_modules
目录,则会覆盖在容器中创建的 node_modules
目录。本教程中构建的设置假设您在主机上没有预先存在的 node_modules
目录,也不会在主机上使用 npm。这符合应用程序开发的十二要素方法,该方法最大限度地减少执行环境之间的依赖关系。
- networks(网络):这指定了您的应用程序服务将加入
app-network
网络,您将在文件底部定义该网络。 - command(命令):此选项允许您设置当 Compose 运行镜像时应执行的命令。请注意,这将覆盖您在应用程序 Dockerfile 中设置的
CMD
指令。在这里,您使用wait-for
脚本运行应用程序,该脚本将轮询db
服务的 27017 端口,以测试数据库服务是否就绪。一旦就绪性测试成功,脚本将执行您设置的命令/home/node/app/node_modules/.bin/nodemon app.js
,以使用nodemon
启动应用程序。这将确保您对代码进行的任何未来更改都会被重新加载,而无需重新启动应用程序。
接下来,在应用程序服务定义之后添加以下代码来创建数据库服务。
~/node_project/docker-compose.yml
文件内容如下:
...
db:
image: mongo:4.1.8-xenial
container_name: db
restart: unless-stopped
env_file: .env
environment:
- MONGO_INITDB_ROOT_USERNAME=$MONGO_USERNAME
- MONGO_INITDB_ROOT_PASSWORD=$MONGO_PASSWORD
volumes:
- dbdata:/data/db
networks:
- app-network
对于 nodejs
服务,一些设置保持不变,但您还对镜像、环境和卷的定义进行了以下更改:
- image(镜像):为了创建此服务,Compose 将从 Docker Hub 拉取
4.1.8-xenial
版本的 Mongo 镜像。您正在固定一个特定版本,以避免 Mongo 镜像更改可能导致的未来冲突。有关版本固定的更多信息,请参阅 Docker 关于 Dockerfile 最佳实践的文档。 - MONGO_INITDB_ROOT_USERNAME, MONGO_INITDB_ROOT_PASSWORD:Mongo 镜像提供了这些环境变量,以便您可以修改数据库实例的初始化。
MONGO_INITDB_ROOT_USERNAME
和MONGO_INITDB_ROOT_PASSWORD
一起在管理认证数据库中创建一个根用户,并确保容器启动时启用认证。您使用.env
文件中的值设置了MONGO_INITDB_ROOT_USERNAME
和MONGO_INITDB_ROOT_PASSWORD
,并通过env_file
选项将其传递给db
服务。这样做意味着您的sammy
应用程序用户将成为数据库实例上的根用户,拥有该角色所有的管理和操作权限。在生产环境中工作时,您会希望创建一个具有适当范围权限的专用应用程序用户。
注意:请记住,如果您使用已存在的数据目录启动容器,这些变量将不会生效。
- dbdata:/data/db:命名卷
dbdata
将持久化存储在 Mongo 默认数据目录/data/db
中的数据。这将确保在停止或移除容器的情况下,您不会丢失数据。
通过使用 networks
选项,db
服务也被添加到了 app-network
网络中。
作为最后一步,将卷和网络定义添加到文件底部。
...
networks:
app-network:
driver: bridge
volumes:
dbdata:
node_modules:
用户定义的桥接网络 app-network
允许在同一 Docker 守护进程主机上的容器之间进行通信。这简化了应用程序内部的流量和通信,因为它在相同的桥接网络上为容器间通信开放了所有端口,同时不向外部暴露任何端口。因此,您的数据库容器和 Node.js 容器可以相互通信,您只需要暴露 80 端口以便前端访问应用程序。
您的顶级卷键定义了 dbdata
和 node_modules
两个卷。当 Docker 创建卷时,卷的内容存储在由 Docker 管理的主机文件系统的一部分,即 /var/lib/docker/volumes/
中。每个卷的内容都存储在 /var/lib/docker/volumes/
下的一个目录中,并被挂载到使用该卷的任何容器中。通过这种方式,即使您删除并重新创建数据库容器,您的用户创建的鲨鱼信息数据也将持久保存在 dbdata
卷中。
最终的 docker-compose.yml
文件将如下所示:
~/node_project/docker-compose.yml:
version: '3'
services:
nodejs:
build:
context: .
dockerfile: Dockerfile
image: nodejs
container_name: nodejs
restart: unless-stopped
env_file: .env
environment:
- MONGO_USERNAME=$MONGO_USERNAME
- MONGO_PASSWORD=$MONGO_PASSWORD
- MONGO_HOSTNAME=db
- MONGO_PORT=$MONGO_PORT
- MONGO_DB=$MONGO_DB
ports:
- "80:8080"
volumes:
- .:/home/node/app
- node_modules:/home/node/app/node_modules
networks:
- app-network
command: ./wait-for.sh db:27017 -- /home/node/app/node_modules/.bin/nodemon app.js
db:
image: mongo:4.1.8-xenial
container_name: db
restart: unless-stopped
env_file: .env
environment:
- MONGO_INITDB_ROOT_USERNAME=$MONGO_USERNAME
- MONGO_INITDB_ROOT_PASSWORD=$MONGO_PASSWORD
volumes:
- dbdata:/data/db
networks:
- app-network
networks:
app-network:
driver: bridge
volumes:
dbdata:
node_modules:
在您完成编辑后保存并关闭文件。
在您已经设置了服务定义之后,您就可以开始应用程序了。
第五步 – 测试应用程序
当您的 docker-compose.yml
文件就位后,您可以使用 docker-compose up
命令创建您的服务。您还可以通过使用 docker-compose down
命令停止和删除容器来测试您的数据是否会持久保存。
首先,通过运行带有 -d
标志的 docker-compose up
命令,构建容器镜像并创建服务,然后将在后台运行 nodejs
和 db
容器。
- docker-compose up -d
输出确认您的服务已经创建。
这是文章《使用Docker Compose 将 Node.js 应用程序进行容器化,用于开发》的第10部分(共10部分)。
… Creating db … done
Creating nodejs … done
您还可以通过显示服务的日志输出来获取关于启动过程的更详细信息。
- docker-compose logs
如果一切启动正确,以下是输出结果。
… nodejs | [nodemon] starting `node app.js`
nodejs | Example app listening on 8080!
nodejs | MongoDB is connected …
db | 2019-02-22T17:26:27.329+0000 I ACCESS [conn2] Successfully authenticated as principal sammy on admin
您也可以使用docker-compose ps
命令来检查您的容器状态。
- docker-compose ps
输出表明您的容器正在运行。
Name Command State Ports
———————————————————————-
db docker-entrypoint.sh mongod Up 27017/tcp
nodejs ./wait-for.sh db:27017 — … Up 0.0.0.0:80->8080/tcp
启动您的服务后,您可以在浏览器中访问http://your_server_ip
。

点击“获取鲨鱼信息”按钮,进入一个包含输入表单的页面,您可以在页面上提交鲨鱼名称和鲨鱼一般特征描述。

在表格中,添加您选择的一种鲨鱼。为了进行演示,请将“巨牙鲨”添加到鲨鱼名称栏,并在鲨鱼特征栏中添加“古老”。

点击提交按钮,会将包含这些鲨鱼信息的页面显示给您。

作为最后一步,测试一下您刚刚输入的数据是否会在删除数据库容器后继续存在。
回到您的终端,输入以下命令来停止和删除您的容器和网络:
- docker-compose down
请注意,您没有包括“–volumes”选项,因此您的“dbdata”卷不会被删除。
以下输出确认您的容器和网络已被移除。
Stopping nodejs … done
Stopping db … done
Removing nodejs … done
Removing db … done
Removing network node_project_app-network
重新创建容器
- docker-compose up -d
现在返回到鲨鱼信息表:

选择一种新的鲨鱼输入。本例将使用“座头鲸鲨”和“大型”:

一旦您点击提交按钮,您会注意到新的鲨鱼已经添加到您的数据库的鲨鱼收藏中,而且您之前输入的数据没有丢失。

您的应用程序现在正在运行在启用了数据持久化和代码同步的Docker容器上。
结论
通过遵循本教程,您已经使用 Docker 容器为您的 Node 应用程序建立了开发环境。通过提取敏感信息并将应用程序状态与应用程序代码解耦,您使得您的项目更加模块化和易于携带。您还配置了一个模板化的 docker-compose.yml
文件,可以根据您的开发需求和要求进行修改。
随着您的发展,您可能对学习如何设计容器化和云原生工作流的应用程序更感兴趣。请参阅有关 Kubernetes 应用架构和 Kubernetes 应用现代化的更多信息。
请查看《如何使用Docker构建Node.js应用程序》和《如何将MongoDB集成到您的Node应用程序中》以了解本教程中使用的代码。如果想了解使用容器在Nginx反向代理上部署Node应用程序的信息,请查看《如何使用Nginx、Let’s Encrypt和Docker Compose保护容器化的Node.js应用程序》。