Docker 构建中未找到 TSC

mik*_*a88 22 node.js typescript docker dockerfile docker-compose

当构建需要从打字稿编译的图像时,我收到此错误。

sh: 1: tsc: 未找到

命令“/bin/sh -c npm run tsc”返回非零代码:127

这是相关代码:

docker-compose.yaml

version: '3.1'

services:
  nodeserver:
    build:
      context: .
      target: prod
    ports:
      - "3000:3000"
    volumes:
      - ./src:/app/src
      - ./public:/app/public
      - ./templates:/app/templates
Run Code Online (Sandbox Code Playgroud)

Dockerfile

FROM node:15.11.0 AS base
EXPOSE 3000
ENV NODE_ENV=production
WORKDIR /app
COPY package*.json ./

RUN npm install --only=production && npm cache clean --force

##########################################################################################

FROM base AS dev

ENV NODE_ENV=development

RUN npm install --only=development

CMD npm run dev

##########################################################################################

FROM dev AS source

COPY dist dist
COPY templates templates
COPY public public

RUN npm run tsc

##########################################################################################

FROM base AS test

COPY --from=source /app/node_modules /app/node_modules
COPY --from=source /app/templates /app/templates
COPY --from=source /app/public /app/public
COPY --from=source /app/dist /app/dist

CMD npm run test

##########################################################################################

FROM test AS prod

CMD npm start
Run Code Online (Sandbox Code Playgroud)

包.json

{
  "name": "nodeserver",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "node ./dist/app.js",
    "deploy": "git add . && git commit -m Heroku && git push heroku main",
    "tsc": "tsc --outDir ./dist",
    "dev": "npm run ts-watch",
    "test": "npm run jest --runInBand",
    "ts-watch": "tsc-watch --project . --outDir ./dist --onSuccess \"nodemon ./dist/app.js\""
  },
  "jest": {
    "testEnvironment": "node"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/MiquelPiza/nodeserver.git"
  },
  "author": "",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/MiquelPiza/nodeserver/issues"
  },
  "homepage": "https://github.com/MiquelPiza/nodeserver#readme",
  "dependencies": {
    "@sendgrid/mail": "^7.4.2",
    "bcryptjs": "^2.4.3",
    "express": "^4.17.1",
    "handlebars": "^4.7.7",
    "jsonwebtoken": "^8.5.1",
    "lodash": "^4.17.20",
    "mongodb": "^3.6.4",
    "mongoose": "^5.11.19",
    "multer": "^1.4.2",
    "socket.io": "^4.0.0",
    "validator": "^13.5.2"
  },
  "devDependencies": {
    "@types/bcryptjs": "^2.4.2",
    "@types/express": "^4.17.11",
    "@types/jsonwebtoken": "^8.5.0",
    "@types/lodash": "^4.14.168",
    "@types/mongoose": "^5.10.3",
    "@types/multer": "^1.4.5",
    "@types/node": "^14.14.33",
    "@types/sendgrid": "^4.3.0",
    "@types/validator": "^13.1.3",
    "env-cmd": "^10.1.0",
    "jest": "^26.6.3",
    "nodemon": "^2.0.7",
    "supertest": "^6.1.3",
    "tsc-watch": "^4.2.9",
    "typescript": "^4.2.3"
  },
  "engines": {
    "node": "15.11.0"
  }
}
Run Code Online (Sandbox Code Playgroud)

tsconfig.json

{
  "compilerOptions": {

    "target": "es5", 
    "module": "commonjs",
    "strict": true,
    "strictNullChecks": false,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
  },
  "include": ["src"]
}
Run Code Online (Sandbox Code Playgroud)

这个 dockerfile 的工作原理:

FROM node:15.11.0 AS build

WORKDIR /app
COPY package.json .
RUN npm install
ADD . .
RUN npm run tsc


FROM node:15.11.0
WORKDIR /app

COPY package.json .
RUN npm install --production

ADD public ./public
ADD templates ./templates
COPY --from=build /app/dist dist

EXPOSE 3000
CMD npm start
Run Code Online (Sandbox Code Playgroud)

我使用 Docker 课程中的这个 dockerfile 作为参考:https://github.com/BretFisher/docker-mastery-for-nodejs/blob/master/typescript/Dockerfile 我不明白我做错了什么,源阶段应该具有开发依赖项,其中包括 typescript,因此它应该能够运行 tsc。

任何帮助表示赞赏。谢谢。

编辑:

除了使用 npm ci 而不是 npm install 之外,我还必须将 tsconfig.json 复制到工作目录(并复制 src 目录而不是由 tsc 创建的 dist),以便 tsc 正常工作。这是 Dockerfile 中修改后的源代码阶段:

FROM dev AS source

COPY src src
COPY templates templates
COPY public public
COPY tsconfig.json tsconfig.json

RUN npm run tsc
Run Code Online (Sandbox Code Playgroud)

小智 32

应该是NODE_ENV环境变量的问题。

ENV NODE_ENV=production
Run Code Online (Sandbox Code Playgroud)

如果这样设置,devDependencies则不会安装 中的依赖项。

  • 将“ENV NODE_ENV=生产”行移动到“RUN npm ci”和“RUN npm run build”之间后解决了我的问题。 (3认同)

kth*_*pso 10

编辑2:

问题已得到解决。如果您的 package-lock.json 文件已损坏,您可以使用实用程序fix-has-install-script修复它。

原答案:

使用npm ci(或添加package-lock.json到您的文件中,或在构建之前在本地环境中.dockerignore删除)。package-lock.json原因在这里得到解答。

编辑1:

这就是我相信正在发生的事情。免责声明,我不是这方面的专家,nodejs事实上npm我还是个新手。而这一切都是基于一些实验的推测。

出了什么问题?

npm未通过符号链接链接开发依赖项的二进制文件,node_modules/.bin因为package-lock.json文件已进入损坏状态,其中(产品)依赖项采用 lockfileVersion 2 格式,而开发依赖项仍采用 lockfileVersion 1 格式。

为什么会发生这种情况?

注意:这里做了很多假设。

  1. 您的本地主机使用 npm 6,docker 容器使用 npm 7。因此,现有的package-lock.jsonis inlockfileVersion: 1其中不包含bin具有二进制文件的依赖项部分。版本 2 确实保存了该bin:部分,npm必须使用该部分来确定要安装/链接的二进制文件。

  2. 当您使用版本 7运行生产依赖项安装(例如NODE_ENV=production npm install)时,将您的版本升级到,其中一部分包括保存安装二进制文件的依赖项的部分。重要的是,它仅更新生产依赖项。现在该文件已损坏,因为它声称采用版本 2 格式,但所有开发依赖项要么仍为版本 1,要么至少没有正确应用该部分。npmnpmpackage-lock.jsonlockfileVersion: 2bin:package-lock.jsonbin:

  3. 当您现在尝试安装开发依赖项时,npm会看到 位于package-lock.jsonlockfileVersion: 2,因此它假定开发依赖项也已升级(但它们尚未升级,或者至少未正确升级)。它找不到这些bin:部分,因为它们不存在,因此它不会将二进制文件链接到目录node_modules/.bin/

您可以使用以下命令执行它的最小复制Dockerfile

FROM node:14 as npm6
WORKDIR /app
# Create a node project using npm 6 and install a dev dependency
# that contains a binary.
RUN npm init --yes && \
    npm install --save-dev typescript

FROM node:15 as npm7
COPY --from=npm6 /app/package*.json /app/
WORKDIR /app
# Install production dependencies, then all dependencies. This should
# link the binaries for typescript in (e.g. tsc) under node_modules/.bin.
RUN npm install -g npm@7.10.0 && \
    npm install --production && \
    npm install

# Causes error, tsc not found.
CMD ["npx", "-c", "tsc --version"]
Run Code Online (Sandbox Code Playgroud)

我找不到现有的错误单,因此我在这里创建了一个。也许它会得到修复。

  • 我不明白为什么删除 package-lock.json 会起作用。npm ci 不需要 package-lock.json 吗? (3认同)