Docker: Node.js
如何使用 Docker 部署 Node.js 应用
👋 欢迎使用 Stackhero 文档!
Stackhero 提供即用型 Docker 云 CaaS(容器即服务) 解决方案,具有众多优势,包括:
- 只需一个
docker-compose up,即可轻松将您的容器部署到生产环境。- 使用 HTTPS 保护的可定制域名(例如,https://api.your-company.com,https://www.your-company.com,https://backoffice.your-company.com)。
- 由私有和专用 VM提供的最佳性能和强大安全性。
- 只需点击即可轻松更新。
节省时间并简化您的生活:只需 5 分钟即可尝试 Stackhero 的 Docker CaaS 云托管 解决方案,并将您的容器部署到生产环境!
本指南为开发 Node.js 应用并快速轻松地部署到生产环境提供了坚实的基础。
不需要事先了解 Docker。所有设置都已准备好以确保顺畅的体验;您只需在计算机上安装 Docker。
此文档适用于希望使用现代可扩展技术部署 Node.js 应用的初学者和有经验的用户,无需不必要的复杂性。
此解决方案的主要特点包括:
- 💪 简单设置,轻松上手
- 🐳 使用 Docker 进行开发和生产环境
- 🔄 使用 nodemon 在代码更改时自动重新加载 Node.js
- 🚀 一键部署到生产环境
- 🔒 TLS 证书管理,确保 HTTPS 加密安全
- 🚧 支持预发布和预生产平台
- 🧱 模块化和可扩展的架构
入门指南
如果您的计算机尚未安装 Docker,可以从 Docker 官方网站下载。要验证 Docker 是否正常运行,请打开终端并运行 docker version。您应该看到版本信息且没有错误。
安装 Docker 后,克隆以下样板库:
git clone https://github.com/stackhero-io/nodejsWithDockerGettingStarted/
cd nodejsWithDockerGettingStarted
然后,通过运行 make development-start 启动开发平台,或使用 make help 查看所有可用命令。
开发平台
要启动开发平台,请运行:
make development-start
此命令构建 Docker 镜像,运行它,并执行在 my-app/package.json 中定义的 dev 脚本(相当于运行 npm run dev)。
在此示例中,创建了一个使用 Express 的简单 REST API。您可以通过访问 http://localhost:5000 查看 API。页面应显示“Hello World”。
接下来,在您喜欢的 IDE 中打开文件 my-app/src/app.js 并修改以下行:
res.send('Hello World');
将其更改为:
res.send('Updated!');
保存文件。Node.js 代码将自动重新加载,刷新 http://localhost:5000 将反映更新后的 API 响应。
恭喜您 - 您现在拥有一个完全可操作的开发平台!
安装包
如果需要安装其他包,可以运行 make development-shell 以访问容器 shell。进入后,使用 NPM 运行 npm install <package> 或使用 Yarn 运行 yarn add <package> 来安装所需的包。
使用现有的 Node.js 项目
如果您有一个现有的 Node.js 项目想要与 Docker 集成,请按照以下步骤操作:
-
在您的项目中创建一个名为
my-app的新目录。 -
将所有项目文件移动到
my-app目录中,排除.gitignore和.git文件。 -
将样板中的
docker、secrets和Makefile复制到项目的根目录。 -
编辑项目中的
.gitignore文件并添加以下行:node_modules/ secrets/*.production secrets/*.staging
开放端口
此样板假设您的应用监听端口 5000。如果您更喜欢其他端口,可以编辑 docker/docker-compose.development.yml 文件,然后使用 make development-start 重新启动环境。
选择特定的 Node.js 版本
如果您希望指定不同的 Node.js 版本,请按照以下步骤操作:
- 打开定义应用 Docker 镜像的文件
docker/my-app.dockerfile。 - 找到第一行
FROM node:<version>-alpine。 - 将
<version>替换为您选择的 Node.js 版本。建议使用长期支持 (LTS) 版本。您可以在 Node.js 网站上查看最新的 LTS 版本。例如,要使用最新的 LTS 版本(当前为 22),将该行更新为FROM node:22-alpine。如果您更喜欢特定的版本号,可以使用类似FROM node:22.13.0-alpine的格式。 - 保存对 Dockerfile 的更改。
环境变量
在文件 secrets/my-app.development 中为开发平台设置环境变量。
对于生产环境,请使用 secrets/my-app.production 文件。
不要将
secrets/my-app.production文件提交到您的 Git 仓库!此文件包含敏感信息,默认在样板的.gitignore中被忽略,以防止意外共享。
存储本地文件
如果您的 Node.js 应用需要存储文件(例如用户上传),请考虑使用对象存储服务,例如 MinIO。对象存储服务可以帮助您的应用无缝扩展,同时减少潜在问题。
如果您更喜欢本地存储文件,请确保始终使用 Docker 卷。直接在容器中存储文件可能导致数据丢失。此样板提供了一个挂载在 /persistent 的卷,用于安全存储文件。
除非您创建了自定义卷并确定配置,否则不要在
/persistent目录之外存储持久数据。在/persistent之外存储文件将导致数据丢失!
添加预发布环境
您可以轻松修改此样板以添加预发布环境。为此:
- 创建
docker/docker-compose.production.yml的副本,并将其命名为docker/docker-compose.staging.yml。此文件定义了预发布环境的容器和配置。 - 创建包含预发布所需敏感信息的 secrets 文件
secrets/my-app.staging,例如数据库密码或 API 密钥。 - 在
Makefile中,找到标记为“Staging platform”的部分并取消注释。
最后,运行 make help 查看现在可用的新预发布命令。
生产平台
如果您还没有 Stackhero for Docker 服务,可以从您的 Stackhero 仪表板轻松创建一个。它将在大约 2 分钟内激活。
如果您是 Stackhero 的新用户,可以免费试用一个月的 Docker 容器云托管。
准备首次生产部署
在将应用部署到生产环境之前,您需要准备一些配置文件:
- 将
secrets/global.production.example复制到secrets/global.production。 - 编辑
secrets/global.production并将<XXXXXX>.stackhero-network.com替换为来自 Stackhero 仪表板的 Docker 服务主机名。 - 将
secrets/my-app.production.example复制到secrets/my-app.production。 - 编辑
secrets/my-app.production并插入您的凭据。 - 更新
docker/docker-compose.production.yml,将<XXXXXX>.stackhero-network.com替换为您的 Docker 服务主机名。
部署到生产环境
部署到生产环境很简单:运行:
make production-deploy
此命令创建一个 Docker 容器,传输您的项目数据,并将其发送到生产环境中的 Docker 服务。打开浏览器并导航到您的 Docker 服务主机名(例如,https://<XXXXXX>.stackhero-network.com)。您应该看到您的 REST API 回复“Hello World”。
您还可以使用
make production,它会部署您的容器并显示实时日志。
显示日志
要监控生产环境或排除故障,可以使用以下命令查看日志:
- 要流式传输实时日志,请运行:
make production-logs-live - 要检索所有存储的日志,请运行:
make production-logs - 要检索特定日期的日志(将
YYYY-MM-DD替换为所需日期),请运行:make production-logs | grep "YYYY-MM-DD"
自定义域名
如果您希望使用不同于 https://<XXXXXX>.stackhero-network.com 的域名,Stackhero for Docker 集成了 Traefik 以简化域管理。Traefik 为您处理 HTTP 路由和 TLS 加密(HTTPS)。
以下是自定义域名的几个示例:
-
要通过端口 5000 上的容器
my-app提供api.my-company.com并使用 TLS 加密,请更新docker/docker-compose.production.yml文件中的labels部分:labels: - "traefik.enable=true" # 启用 Traefik 将流量路由到此容器 - "traefik.http.routers.my-app.rule=Host(`api.my-company.com`)" # 定义主机 - "traefik.http.routers.my-app.tls.certresolver=letsencrypt" # 使用 letsencrypt 获取 TLS 证书 - "traefik.http.services.my-app.loadbalancer.server.port=5000" # 指定端口 5000 -
要通过端口 5000 上的容器
my-app提供my-company.com并将所有请求从www.my-company.com重定向到my-company.com,请在同一文件中更新labels部分:labels: - "traefik.enable=true" - "traefik.http.routers.my-app.rule=Host(`my-company.com`) || Host(`www.my-company.com`)" # 包含两个域 - "traefik.http.routers.my-app.tls.certresolver=letsencrypt" - "traefik.http.services.my-app.loadbalancer.server.port=5000" # 指定端口 5000 # 将 www.my-company.com 重定向到 my-company.com: - "traefik.http.routers.my-app.middlewares=redirect-www" - "traefik.http.middlewares.redirect-www.redirectregex.regex=^https://www.my-company.com/(.*)" - "traefik.http.middlewares.redirect-www.redirectregex.replacement=https://my-company.com/$${1}" - "traefik.http.middlewares.redirect-www.redirectregex.permanent=true"
不要忘记为
my-company.com和www.my-company.com配置 DNS,以便每个都指向您的 Docker 服务的 CNAMEhttps://<XXXXXX>.stackhero-network.com。