使用Docker Compose容纳Node.js应用程序进行开发

如果您正在积极开发应用程序,Docker可以简化您的工作流程以及将应用程序部署到生产环境的过程。本教程将向您展示如何使用Docker为Node.js应用程序设置开发环境。您将使用Docker Compose创建两个容器 - 一个用于Node应用程序,另一个用于MongoDB数据库。在本教程结束时,您将在Docker容器上运行一个有效的shark信息应用程序。

介绍

如果您正在积极开发应用程序,使用Docker可以简化您的工作流程以及将应用程序部署到生产环境的过程。 在开发中使用容器具有以下优点:

  • 环境是一致的,这意味着您可以为项目选择所需的语言和依赖项,而无需担心系统冲突。
  • 环境是孤立的,可以更轻松地解决问题和新团队成员。
  • 环境是可移植的,允许您打包并与他人共享代码。

本教程将向您展示如何使用Docker为Node.js应用程序设置开发环境。 您将使用Docker Compose创建两个容器 - 一个用于Node应用程序,另一个用于MongoDB数据库。 由于此应用程序适用于Node和MongoDB,因此我们的设置将执行以下操作:

  • 将主机上的应用程序代码与容器中的代码同步,以便在开发期间进行更改。
  • 确保对应用程序代码的更改无需重新启动即可运行。
  • 为应用程序的数据创建受用户和密码保护的数据库。
  • 坚持这些数据。

在本教程结束时,您将在Docker容器上运行一个有效的shark信息应用程序:

完整的鲨鱼系列

先决条件

要学习本教程,您需要:

第1步 - 克隆项目并修改依赖项

构建此设置的第一步是克隆项目代码并修改其package.json文件,其中包含项目的依赖项。 我们将nodemon添加到项目的devDependencies ,指定我们将在开发期间使用它。 使用nodemon运行应用程序可确保在您对代码进行更改时自动重新启动它。

首先,从DigitalOcean社区GitHub帐户克隆nodejs-mongo-mongoose存储库 此存储库包含如何将MongoDB与您的节点应用程序集成中描述的设置中的代码,该代码解释了如何使用Mongoose将MongoDB数据库与现有节点应用程序集成。

将存储node_project到名为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

在项目依赖项下方和结束大括号之上,创建一个包含nodemon的新devDependencies对象:

〜/ node_project /的package.json
...
"dependencies": {
    "ejs": "^2.6.1",
    "express": "^4.16.4",
    "mongoose": "^5.4.10"
  },
  "devDependencies": {
    "nodemon": "^1.18.10"
  }    
}

完成编辑后保存并关闭文件。

随着项目代码的到位及其依赖项的修改,您可以继续重构容器化工作流的代码。

第2步 - 配置应用程序以使用容器

修改我们的容器化工作流应用程序意味着使我们的代码更加模块化。 容器提供环境之间的可移植性,我们的代码应该通过尽可能地与底层操作系统分离来反映这一点。 为了实现这一点,我们将重构我们的代码以更好地利用Node的process.env属性,该属性在运行时返回一个包含用户环境信息的对象。 我们可以在代码中使用此对象,以便在运行时使用环境变量动态分配配置信息。

让我们从我们的主要应用程序入口点app.js开始。 打开文件:

nano app.js

在里面,您将看到port 常量的定义,以及使用此常量指定应用程序将监听的端口的listen函数

〜/家/ node_project / app.js
...
const port = 8080;
...
app.listen(port, function () {
  console.log('Example app listening on port 8080!');
});

让我们重新定义port常量,以允许在运行时使用process.env对象进行动态分配。 对常量定义和listen功能进行以下更改:

〜/家/ node_project / app.js
...
const port = process.env.PORT || 8080;
...
app.listen(port, function () {
  console.log(`Example app listening on ${port}!`);
});

我们的新常量定义使用在运行时或8080传入的值动态分配port 类似地,我们重写了listen函数以使用模板文字 ,该模板文字将在监听连接时插入端口值。 因为我们将把我们的端口映射到其他地方,所以这些修订将阻止我们在环境发生变化时不断修改此文件。

完成编辑后,保存并关闭文件。

接下来,我们将修改数据库连接信息以删除任何配置凭据。 打开db.js文件,其中包含以下信息:

nano db.js

目前,该文件执行以下操作:

  • 导入Mongoose,我们用来为我们的应用程序数据创建模式和模型的Object Document Mapper (ODM)。
  • 将数据库凭据设置为常量,包括用户名和密码。
  • 使用mongoose.connect方法连接到数据库。

有关该文件的更多信息,请参阅如何将MongoDB与您的节点应用程序集成的 第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
...
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
...
.gitignore
.env

完成编辑后保存并关闭文件。

此存储库中的.gitignore文件已包含.env ,但请随意检查它是否存在:

nano .gitignore
~~ / node_project /的.gitignore
...
.env
...

此时,您已成功从项目代码中提取敏感信息,并采取措施控制此信息的复制方式和位置。 现在,您可以为数据库连接代码添加更强大的功能,以便针对容器化工作流进行优化。

第3步 - 修改数据库连接设置

我们的下一步是通过添加处理我们的应用程序无法连接到我们的数据库的情况的代码来使我们的数据库连接方法更加健壮。 在使用Compose处理容器时, 建议在应用程序代码中引入这种级别的弹性。

打开db.js进行编辑:

nano db.js

您将看到我们之前添加的代码,以及Mongo的连接URI和Mongoose connect方法的url常量:

〜/ node_project / db.js
...
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解析器 让我们为此方法添加一些选项,以定义重新连接尝试的参数。 除了新的URL解析器选项之外,我们还可以通过创建包含相关信息的options常量来实现此目的。 在Mongo常量下面,为options常量添加以下定义:

〜/ node_project / db.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将10秒定义为Mongo驱动程序在连接尝试失败之前将等待的时间段。

我们现在可以在Mongoose connect方法中使用新的options常量来微调我们的Mongoose连接设置。 我们还将添加一个承诺来处理潜在的连接错误。

目前,Mongoose connect方法如下所示:

〜/ node_project / db.js
...
mongoose.connect(url, {useNewUrlParser: true});

删除现有的connect方法并将其替换为以下代码,其中包括options常量和承诺:

〜/ node_project / db.js
...
mongoose.connect(url, options).then( function() {
  console.log('MongoDB is connected');
})
  .catch( function(err) {
  console.log(err);
});

在连接成功的情况下,我们的函数会记录一条适当的消息; 否则它将catch并记录错误,允许我们进行故障排除。

完成的文件如下所示:

〜/ node_project / db.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 is connected');
})
  .catch( function(err) {
  console.log(err);
});

完成编辑后保存并关闭文件。

您现在已经为应用程序代码添加了弹性,以处理应用程序可能无法连接到数据库的情况。 有了这段代码,您可以继续使用Compose定义您的服务。

第4步 - 使用Docker Compose定义服务

重构代码后,您就可以使用服务定义编写docker-compose.yml文件了。 Compose中的服务是一个正在运行的容器,服务定义(将包含在docker-compose.yml文件中)包含有关每个容器映像将如何运行的信息。 Compose工具允许您定义多个服务以构建多容器应用程序。

但是,在定义我们的服务之前,我们将在我们的项目中添加一个名为wait-for的工具wait-for以确保我们的应用程序只在数据库启动任务完成后才尝试连接到我们的数据库。 此包装器脚本使用netcat来轮询特定主机和端口是否正在接受TCP连接。 使用它可以通过测试数据库是否已准备好接受连接来控制应用程序连接到数据库的尝试。

虽然Compose允许您使用depends_on选项指定服务之间的依赖关系,但此顺序基于容器是否正在运行而不是其准备就绪。 使用depends_on对我们的设置不是最佳的,因为我们希望我们的应用程序仅在数据库启动任务(包括向admin认证数据库添加用户和密码)完成时才连接。 有关使用wait-for和其他工具控制启动顺序的更多信息,请参阅Compose文档中的相关建议

打开一个名为wait-for.sh的文件:

nano wait-for.sh

将以下代码粘贴到文件中以创建轮询功能:

〜/ node_project /应用程序/ wait-for.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

首先,通过将以下代码添加到文件来定义nodejs应用程序服务:

〜/ node_project /搬运工-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

nodejs服务定义包括以下选项:

  • build :这定义了Compose构建应用程序映像时将应用的配置选项,包括contextdockerfile 如果要使用Docker Hub等注册表中的现有映像,则可以使用image指令 ,并提供有关用户名,存储库和映像标记的信息。
  • context :这定义了映像构建的构建上下文 - 在本例中是当前项目目录。
  • dockerfile :这将指定当前项目目录中的Dockerfile ,作为Compose用于构建应用程序映像的文件。 有关此文件的更多信息,请参阅如何使用Docker构建Node.js应用程序
  • imagecontainer_name :这些名称适用于图像和容器。
  • restart :这定义了重启策略。 默认值为no ,但我们已将容器设置为重新启动,除非它已停止。
  • env_file :这告诉Compose我们想要从位于我们的构建上下文中的名为.env的文件中添加环境变量。
  • environment :使用此选项可以添加.env文件中定义的Mongo连接设置。 请注意,我们没有将NODE_ENV设置为development ,因为如果未设置NODE_ENV ,这是Express的 默认行为。 迁移到生产环境时,可以将其设置为production启用视图缓存和更简洁的错误消息 另请注意,我们已将db数据库容器指定为主机,如第2步中所述
  • ports :这会将主机上的端口80映射到容器上的端口8080
  • volumes :我们在这里包括两种类型的安装:

    • 第一个是绑定装载 ,它将我们在主机上的应用程序代码安装到容器上的/home/node/app目录。 这将有助于快速开发,因为您对主机代码所做的任何更改都将立即填充到容器中。
    • 第二个是命名node_modules 当Docker运行应用程序Dockerfile列出的npm install指令时, npm将在容器上创建一个新的node_modules目录,其中包含运行该应用程序所需的包。 但是,我们刚刚创建的绑定挂载将隐藏这个新创建的node_modules目录。 由于node_modules上的node_modules为空,因此bind将空目录映射到容器,覆盖新的node_modules目录并阻止我们的应用程序启动。 命名的node_modules卷通过保留/home/node/app/node_modules目录的内容并将其挂载到容器来隐藏绑定来解决此问题。

    使用此方法时,请牢记以下几点

    • 您的bind会将容器上node_modules目录的内容挂载到主机,并且该目录将由root拥有,因为命名卷是由Docker创建的。
    • 如果主机上有预先存在的node_modules目录,它将覆盖在容器上创建的node_modules目录。 我们在本教程中构建的设置假定您没有预先存在的node_modules目录,并且您将不在主机上使用npm 这与应用程序开发十二因素方法保持一致,从而最大限度地减少了执行环境之间的依赖关系。
  • networks :这指定我们的应用程序服务将加入app-network网络,我们将在文件底部定义。

  • command :此选项允许您设置Compose运行映像时应执行的命令。 请注意,这将覆盖我们在应用程序Dockerfile设置的CMD指令。 在这里,我们使用wait-for脚本运行应用程序,该脚本将轮询端口27017上的db服务以测试数据库服务是否准备就绪。 准备就绪测试成功后,脚本将执行我们设置的命令/home/node/app/node_modules/.bin/nodemon app.js ,以使用nodemon启动应用程序。 这将确保我们对代码所做的任何未来更改都会重新加载,而无需重新启动应用程序。

接下来,通过在应用程序服务定义下添加以下代码来创建db服务:

〜/ node_project /搬运工-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服务定义的一些设置保持不变,但我们还对imageenvironmentvolumes定义进行了以下更改:

  • image :要创建此服务,Compose将从Docker Hub中提取4.1.8-xenial Mongo映像 我们正在固定一个特定版本,以避免在Mongo图像发生变化时可能出现的未来冲突。 有关版本固定的更多信息,请参阅有关Dockerfile最佳实践的Docker文档。
  • MONGO_INITDB_ROOT_USERNAMEMONGO_INITDB_ROOT_PASSWORDmongo映像使这些环境变量可用,以便您可以修改数据库实例的初始化。 MONGO_INITDB_ROOT_USERNAMEMONGO_INITDB_ROOT_PASSWORD一起在admin身份验证数据库中创建root用户,并确保在容器启动时启用身份验证。 我们使用.env文件中的值设置了MONGO_INITDB_ROOT_USERNAMEMONGO_INITDB_ROOT_PASSWORD ,我们使用env_file选项传递给db服务。 这样做意味着我们的sammy应用程序用户将成为数据库实例上的root用户 ,可以访问该角色的所有管理和操作权限。 在生产中工作时,您将需要创建具有适当范围特权的专用应用程序用户。 注意:请记住,如果启动具有现有数据目录的容器,这些变量将不会生效。
  • dbdata:/data/db :命名卷dbdata将持久存储在Mongo的缺省数据目录 /data/db 这将确保您在停止或删除容器时不会丢失数据。

我们还使用networks选项将db服务添加到app-network网络。

最后一步,将卷和网络定义添加到文件的底部:

〜/ node_project /搬运工-compose.yml
...
networks:
  app-network:
    driver: bridge

volumes:
  dbdata:
  node_modules:  

用户定义的桥接网络app-network可以在我们的容器之间进行通信,因为它们位于同一个Docker守护程序主机上。 这简化了应用程序内的流量和通信,因为它打开了同一桥接网络上的容器之间的所有端口,同时不向外界暴露任何端口。 因此,我们的dbnodejs容器可以相互通信,我们只需要公开端口80以便对应用程序进行前端访问。

我们的顶级volumes密钥定义了卷dbdatanode_modules 当Docker创建卷时,卷的内容存储在由Docker管理的主机文件系统/var/lib/docker/volumes/的一部分中。 每个卷的内容都存储在/var/lib/docker/volumes/下的目录中,并安装到使用该卷的任何容器中。 这样,即使我们删除并重新创建db容器,我们的用户将创建的shark信息数据也将保留在dbdata卷中。

完成docker-compose.yml文件如下所示:

〜/ node_project /搬运工-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
    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:  

完成编辑后保存并关闭文件。

有了您的服务定义,您就可以启动该应用程序了。

第5步 - 测试应用程序

使用docker-compose.yml文件,您可以使用docker-compose.yml docker-compose up命令创建服务。 您还可以通过使用docker-compose down停止和删除容器来测试您的数据是否会持续存在。

首先,构建容器映像并通过使用-d标志运行nodejs docker-compose up创建服务,然后在后台运行nodejsdb容器:

docker-compose up -d

您将看到输出确认您的服务已创建:

...
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 您将看到如下所示的着陆页:

申请登陆页面

单击“ 获取鲨鱼信息”按钮。 您将看到一个带有输入表单的页面,您可以在其中输入鲨鱼名称和该鲨鱼的一般特征的描述:

鲨鱼信息表

在表单中,添加您选择的鲨鱼。 为了演示的目的,我们将Megalodon Shark添加到Shark Name字段,将AncientShark Character字段:

填充鲨鱼表格

单击“ 提交”按钮。 您将看到一个显示此鲨鱼信息的页面:

鲨鱼输出

作为最后一步,我们可以测试您刚刚输入的数据是否会在您删除数据库容器时持续存在。

返回终端,键入以下命令以停止和删除容器和网络:

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

现在回到鲨鱼信息表:

鲨鱼信息表

输入您选择的新鲨鱼。 我们将选择Whale SharkLarge

输入新鲨鱼

单击“ 提交”后 ,您将看到新的shark已添加到数据库中的shark集合中,而不会丢失您已输入的数据:

完整的鲨鱼系列

您的应用程序现在在Docker容器上运行,并启用了数据持久性和代码同步。

结论

通过本教程,您已使用Docker容器为Node应用程序创建了开发设置。 通过提取敏感信息并将应用程序的状态与应用程序代码分离,您已使项目更加模块化和可移植。 您还配置了样板docker-compose.yml文件,您可以根据开发需求和需求的变化进行修改。

在开发过程中,您可能有兴趣了解有关为容器化和Cloud Native工作流程设计应用程序的更多信息。 有关这些主题的更多信息,请参阅Kubernetes的构建应用程序和Kubernetes的 现代化应用程序

要了解有关本教程中使用的代码的更多信息,请参阅如何使用Docker构建Node.js应用程序以及如何将MongoDB与您的节点应用程序集成 有关使用容器部署带有Nginx反向代理的Node应用程序的信息,请参阅如何使用Nginx,Let's Encrypt和Docker Compose保护Containerized Node.js应用程序