解决 Docker 中 Node.js 中的“缺少启动脚本”错误

Temp mail SuperHeros
解决 Docker 中 Node.js 中的“缺少启动脚本”错误
解决 Docker 中 Node.js 中的“缺少启动脚本”错误

在 Docker 中启动 Node.js 后端:故障排除指南

尝试运行时遇到错误 Node.js 后端 里面一个 Docker容器 可能会令人沮丧,特别是当它是由于简单的“缺少启动脚本”消息时。此错误经常发生在以下情况 国家公共管理 在您的设置中找不到正确的启动命令。如果您受到此打击,那么您并不孤单!

在许多情况下,问题归结为 package.json 和 Docker 设置之间的路径不正确或配置不一致。处理事情的时候很容易忽略一个小细节 多阶段构建、容器化和配置文件。我自己也遇到过这个问题,我可以说修复它通常涉及检查每个文件的位置和脚本。

例如,我曾经部署过一个后端,后来发现我的 dist 文件夹没有正确映射,导致启动命令失败。简单的调整可以解决这些问题,但找到合适的需要耐心🔍。检查所有依赖项和脚本是否正确映射可以节省调试时间。

在本指南中,我们将深入研究一些修复此错误的实际步骤,特别是如果您与数据库一起运行后端,例如 动态数据库 在 Docker 中。让我们一起解决“缺少启动脚本”错误,让您的后端顺利运行!

命令 描述
CMD ["node", "dist/server.js"] 定义启动时在 Docker 容器中运行的主要命令。在这里,它指示 Docker 通过执行 dist 文件夹内的 server.js 来启动应用程序,解决 缺少启动脚本 通过确保 Docker 知道要运行哪个脚本来解决问题。
WORKDIR /app 将容器内的工作目录设置为/app。这对于确保后续命令中的所有文件路径都引用此目录、简化 Docker 中的构建和运行时流程至关重要。
COPY --from=builder /app/dist ./dist 将构建器阶段的 dist 文件夹中的构建文件复制到运行时环境的 dist 目录中。此命令对于确保已编译的 TypeScript 文件在容器中可用至关重要。
RUN npm install --omit=dev 仅安装生产依赖项,忽略开发依赖项。该命令针对生产构建进行了优化,减少了容器的最终大小,并通过排除开发工具来提高安全性。
healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000"] 定义运行状况检查以验证 Docker 中的 DynamoDB 服务是否正在运行。它使用curl尝试连接到指定的本地端点,确保服务在后端启动之前可用。
depends_on: 在 docker-compose.yml 中指定依赖项。在这里,它确保后端服务等待 DynamoDB 初始化,从而防止尝试连接到未就绪的服务时出现错误。
EXPOSE 3001 在 Docker 容器内打开端口 3001,使后端服务可以在此端口上访问。设置网络并允许外部服务或其他容器访问后端需要此命令。
test('dist folder exists', ...) 一个 Jest 单元测试,用于检查 dist 文件夹是否正确生成。此测试有助于验证构建步骤是否成功,捕获 dist 目录中丢失文件的潜在问题。
expect(packageJson.scripts.start) 确认 package.json 中存在启动脚本的 Jest 测试行。通过确保部署前的配置准确性,有助于防止运行时错误丢失启动命令。

Node.js 和数据库连接的 Docker 配置

在上面的示例中,Docker 设置利用多阶段构建,这对于创建高效的生产就绪容器非常有用。第一阶段定义为“构建器”,安装依赖项并编译 打字稿 文件到 JavaScript 中 距离 文件夹。此步骤确保编译后的代码已准备好用于生产,而不包含不必要的开发依赖项。构建后,第二阶段(运行时)仅复制已编译的文件和生产依赖项,从而最大限度地减少容器大小。如果您经常部署到每一点优化都很重要的云环境,那么此设置特别有用! 🚀

工作目录 两个阶段中的命令都将容器的工作目录设置为 /app。这简化了文件路径并围绕该目录组织所有操作。随后, 复制 指令将特定文件从主机移动到容器。在第一阶段,复制 package*.json 文件和 tsconfig.json 以允许依赖项安装和 TypeScript 编译,并且 运行 npm 安装RUN npm 运行构建 命令确保一切设置正确。此设置可确保正确复制和配置所有文件,从而有助于避免丢失启动脚本等问题。

docker-compose.yml 文件连接后端 动态数据库,这对于本地测试和开发至关重要。这 取决于 选项告诉 Docker 在后端服务之前启动 DynamoDB,确保数据库已准备好接受来自后端的任何连接尝试。在现实场景中,如果后端在数据库之前启动,没有这样的依赖关系设置可能会导致连接问题,从而导致令人沮丧的错误。这 健康检查 命令通过 ping 端点来测试 DynamoDB 是否可访问,然后重试直至建立连接。这种级别的错误处理可以确保服务以正确的顺序启动,从而节省时间。

最后,在 package.json 中,我们定义了 开始 脚本为 节点 dist/server.js。此命令可确保 NPM 确切地知道要在容器中运行哪个文件,从而有助于避免“缺少启动脚本”错误。还有一个用于编译 TypeScript 代码的构建命令和一个用于删除 dist 文件夹的 clean 命令,确保每个部署都是全新的。使用此类 npm 脚本可以使设置更加可靠,尤其是在涉及 Docker 时,因为它提供了可预测的路径和操作。 Docker、Docker Compose 和 NPM 脚本的这种全面配置协同工作,创建了简化的开发到生产工作流程。

解决方案 1:调整 Dockerfile 和 Package.json 以正确复制文件

该解决方案利用 Docker 和 Node.js 确保文件正确复制到 距离 文件夹并且 NPM 可以找到 开始 脚本。

# Dockerfile
FROM node:18 AS builder
WORKDIR /app
# Copy necessary config files and install dependencies
COPY package*.json tsconfig.json ./
RUN npm install
# Copy all source files and build the project
COPY . .
RUN npm run build
# Production stage
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/package*.json ./
RUN npm install --omit=dev
COPY --from=builder /app/dist ./dist
EXPOSE 3001
# Adjust command to start the server
CMD ["node", "dist/server.js"]

解决方案2:修改docker-compose.yml进行环境控制

该解决方案修改了 docker-compose.yml 配置以指定正确的命令并确保脚本在 Docker 中正确运行。

# docker-compose.yml
version: "3.9"
services:
  backend:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "3001:3001"
    environment:
      PORT: 3001
    depends_on:
      - dynamodb
    command: ["npm", "run", "start"]
  dynamodb:
    image: amazon/dynamodb-local
    ports:
      - "8001:8000"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000"]
      interval: 10s
      timeout: 5s
      retries: 5

解决方案 3:验证和更新 Package.json 脚本

该解决方案涉及确保 开始 脚本在中正确定义 包.json 文件以防止丢失脚本错误。

{
  "name": "backend",
  "version": "1.0.0",
  "main": "dist/server.js",
  "scripts": {
    "build": "tsc",
    "start": "node dist/server.js",
    "dev": "nodemon --exec ts-node src/server.ts",
    "clean": "rimraf dist"
  }
}

单元测试:确保脚本和 Docker 配置完整性

这些 Jest 测试验证基本文件是否已正确复制以及 NPM 脚本在容器环境中是否正常运行。

// test/deployment.test.js
const fs = require('fs');
describe('Deployment Tests', () => {
  test('dist folder exists', () => {
    expect(fs.existsSync('./dist')).toBe(true);
  });
  test('start script exists in package.json', () => {
    const packageJson = require('../package.json');
    expect(packageJson.scripts.start).toBe("node dist/server.js");
  });
  test('Dockerfile has correct CMD', () => {
    const dockerfile = fs.readFileSync('./Dockerfile', 'utf8');
    expect(dockerfile).toMatch(/CMD \["node", "dist\/server.js"\]/);
  });
});

确保 Docker 中 Node.js 项目的文件复制和结构正确

在 Docker 中使用 Node.js 应用程序时,一个关键的考虑因素是确保所有必要的文件在容器中正确复制和构建。在多阶段构建中,如上面的示例,每个阶段都有特定的目的。初始阶段“构建器”负责将 TypeScript 编译为 JavaScript 并准备 距离 文件夹。第二阶段仅包含生产文件,减少容器大小并优化部署。这种方法不仅减少了不必要的膨胀,而且还通过省去开发工具来增强安全性。

Docker for Node.js 的一个重要方面是组织 包.json启动脚本 准确。通过在 Dockerfile 中明确指定路径并确保启动命令在 包.json,您可以最大限度地减少“缺少启动脚本”之类的错误。确认 Docker 知道每个文件应该放在哪里也很重要,尤其是在涉及多个服务或文件夹的复杂设置中。例如,使用 COPY 命令仅添加 距离 文件夹和最终容器的必要配置确保只有必要的文件在生产中可用。

要检查您的服务的运行状况, docker-compose.yml 文件使用运行状况检查来验证数据库是否准备就绪。通过定义依赖关系,我们确保后端服务在数据库响应之前不会启动,从而防止与时间相关的连接问题。此设置在数据库连接至关重要的实际应用程序中特别有用。如果没有这种结构,服务可能会在其他服务启动之前尝试连接,从而导致运行时错误和用户潜在的停机时间🔄。

有关修复 Node.js 中“缺少启动脚本”的常见问题

  1. 是什么原因导致 NPM 中出现“缺少启动脚本”错误?
  2. package.json 文件没有 start 脚本已定义。 NPM 找不到启动应用程序的正确入口点。
  3. 是否 package.json 文件需要位于 dist 文件夹?
  4. 不,该 package.json 通常驻留在根目录中,仅将必要的文件复制到 dist 文件夹。
  5. 为什么我们在 Docker 中使用多阶段构建?
  6. 多阶段构建使我们能够创建轻量级、生产就绪的容器。通过分离构建和运行时环境,排除不必要的文件,提高安全性和效率。
  7. 如何 healthcheck 在 Docker Compose 中有帮助吗?
  8. healthcheck 命令检查服务是否已启动并正在运行,这在需要首先准备好依赖服务(例如数据库)的情况下至关重要。
  9. 在此设置中我可以使用其他数据库代替 DynamoDB 吗?
  10. 是的,您可以更换 DynamoDB 与其他数据库。调整 Docker Compose 配置以适合您首选的数据库服务。
  11. 为什么我们使用 RUN npm install --omit=dev 命令?
  12. 此命令仅安装生产依赖项,这有助于通过排除开发工具来保持容器的轻量级。
  13. 我怎样才能确认 dist 文件夹是否正确复制?
  14. 您可以在代码中添加测试来检查是否 dist 存在,或者在构建后使用 Docker CLI 检查容器的内容。
  15. 我需要在 Dockerfile 和 Docker Compose 中指定端口吗?
  16. 是的,在两者中指定端口可确保容器端口与主机端口匹配,从而使服务可以从 Docker 外部访问。
  17. 为什么设置 WORKDIR 在Docker中重要吗?
  18. 环境 WORKDIR 为所有命令创建默认目录路径,简化文件路径并系统地组织容器文件。
  19. 如何查看 Docker 日志来调试此错误?
  20. 使用 docker logs [container_name] 访问日志,可以深入了解任何启动错误或丢失的文件。

修复 Docker 中的 Node.js 启动错误

解决“缺少启动脚本”错误需要注意细节,特别是在配置 Docker 的文件结构和 NPM 脚本方面。检查您的 Dockerfile 以确保编译的文件已复制到 距离 文件夹并且正确定义了 package.json 中的启动脚本可以节省您数小时的调试时间。

维护清晰的设置和有组织的脚本将有助于 Docker 容器顺利运行,并且在 Docker Compose 中使用运行状况检查可确保服务按正确的顺序加载。通过这些调整,您的后端应该能够可靠地启动,从而为您提供更顺畅的开发工作流程。 🛠️

来源和参考文献
  1. 有关 Docker 多阶段构建以及 Docker 中 Node.js 应用程序最佳实践的详细信息: Docker 文档
  2. 有关在 Docker Compose 中设置运行状况检查和依赖项以确保服务按正确顺序启动的综合指南: Docker Compose 健康检查
  3. 解决“缺少启动脚本”错误和其他常见 NPM 问题,包括为生产构建正确配置 package.json: NPM 文档
  4. 在 Docker 环境中配置和测试 DynamoDB Local 的简介,包括与 Node.js 后端的使用: AWS DynamoDB 本地指南