Docker `npm install` 与 TypeScript 中的 GitHub 私有 repo 依赖项
Posted
技术标签:
【中文标题】Docker `npm install` 与 TypeScript 中的 GitHub 私有 repo 依赖项【英文标题】:Docker `npm install` with GitHub private repo dependency in TypeScript 【发布时间】:2021-12-04 14:42:01 【问题描述】:我们有一个 Node TypeScript 项目,我们正在尝试 Dockerize。该项目依赖于另一个 GitHub 私有仓库,该仓库通过 package.json 中的“git@github.com:private-repo-name”语法引用。依赖项目也是一个TS项目。在任何本地开发 PC 操作系统(例如 macOS、Ubuntu LTS 等)的克隆位置和 shell 中运行 npm install
(或 npm ci
等)时,主项目安装和构建良好。然而,当我们尝试 Dockerize 主项目时,我们看到npm build
脚本错误显然没有意义。依赖项目有一个“准备”脚本,它在为依赖项目调用的npm install
之后运行,在它的 repo 被签出之后。 “准备”脚本是npm run build
,“构建”脚本是tsc -p . && npm run validate
。
所以事情看起来像这样:
主项目的package.json:
"name": "main-project",
"private": true,
"scripts":
...
,
"dependencies":
...
"typescript": "^4.3.4",
"private-repo": "git@github.com:my-private-repo.git#a-branch",
,
"devDependencies":
"@types/example": "^1.0.0",
...
依赖项目package.json:
"name": "dependency-project",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"scripts":
"build": "tsc -p . && npm run validate",
"prepare": "npm run build",
"validate": "node dist/validate.js"
,
"private": true,
"dependencies":
...
,
"devDependencies":
"@types/example": "1.0.0",
...
总体目标是分层构建 Docker 映像,但我们在刚刚完成第一层(主项目的npm install
)时遇到了障碍。
主项目的 Dockerfile 如下所示:
FROM node:16-alpine
ARG SSH_KEY
RUN apk add git openssh-client
COPY package.json package-lock.json ./
RUN mkdir -p -m 0600 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts
RUN ssh-agent sh -c 'echo $SSH_KEY | base64 -d | ssh-add - ; npm ci'
这种将私钥传递给层构建的方法效果很好(尽管它是我们能够使用的各种方法中唯一的一种,包括 Docker Buildkit)。 repo 被签出并且安装显然成功,然后“准备”脚本(因此npm build
和tsc -p
)运行。
当我们运行docker build --build-arg SSH_KEY=$key .
时一切正常,直到出现以下错误:
#9 27.31 npm ERR! > my-private-repo@0.0.3 prepare
#9 27.31 npm ERR! > npm run build
#9 27.31 npm ERR!
#9 27.31 npm ERR!
#9 27.31 npm ERR! > my-private-repo@0.0.3 build
#9 27.31 npm ERR! > tsc -p . && npm run validate
#9 27.31 npm ERR!
#9 27.31 npm ERR! error TS2688: Cannot find type definition file for 'cacheable-request'.
#9 27.31 npm ERR! The file is in the program because:
#9 27.31 npm ERR! Entry point for implicit type library 'cacheable-request'
#9 27.31 npm ERR! error TS2688: Cannot find type definition file for 'chai'.
#9 27.31 npm ERR! The file is in the program because:
#9 27.31 npm ERR! Entry point for implicit type library 'chai'
#9 27.31 npm ERR! error TS2688: Cannot find type definition file for 'cors'.
#9 27.31 npm ERR! The file is in the program because:
#9 27.31 npm ERR! Entry point for implicit type library 'cors'
#9 27.31 npm ERR! error TS2688: Cannot find type definition file for 'faker'.
#9 27.31 npm ERR! The file is in the program because:
#9 27.31 npm ERR! Entry point for implicit type library 'faker'
#9 27.31 npm ERR! error TS2688: Cannot find type definition file for 'lodash'.
#9 27.31 npm ERR! The file is in the program because:
#9 27.31 npm ERR! Entry point for implicit type library 'lodash'
#9 27.31 npm ERR! error TS2688: Cannot find type definition file for 'mocha'.
#9 27.31 npm ERR! The file is in the program because:
#9 27.31 npm ERR! Entry point for implicit type library 'mocha'
#9 27.31 npm ERR! error TS2688: Cannot find type definition file for 'responselike'.
#9 27.31 npm ERR! The file is in the program because:
#9 27.31 npm ERR! Entry point for implicit type library 'responselike'
令人困惑的是,那些“错误 TS2688”消息所指的包都不是依赖项(私有 repo)项目的依赖项(它们位于 main 的 package-lock.json 中项目。我们不知道如何解释。
我们尝试过的主要故障排除步骤包括:
在本地开发 PC 操作系统上使用相同的 Node 和 npm 版本,并运行主项目的npm install
[工作正常]。
在这篇文章之后,尝试在它所抱怨的每个包中查找index.d.ts
文件(但这些包甚至不在依赖项目中):https://github.com/microsoft/TypeScript/issues/27956
试图理解和检查这个帖子,无济于事:Fixing TS2688: Cannot find type definition file in node_modules
似乎在相关 Docker 层中调用的 shell 的用户上下文中一定有某些东西导致 TS 使用错误的 package.json(即错误的依赖项),因为我们在 Dockerfile 中所做的是非常简单,除了 Docker 层外,它在任何地方都可以使用。
【问题讨论】:
【参考方案1】:[更新/回答我自己的问题]
我无法完全解释这种行为,因为它没有任何意义。相反,我尝试使用 ubuntu:20.04 而不是 node:16-alpine 图像。我必须添加节点和一堆依赖项,但完成之后我能够npm ci
就好了,没有那个打字稿投诉或任何其他投诉。
这是 Dockerfile 以防万一(注意这只是基础/构建层):
FROM ubuntu:20.04
RUN apt-get update \
# had to install tzdata this first to get the noninteractive to work
&& DEBIAN_FRONTEND="noninteractive" apt-get install -y --no-install-recommends tzdata \
&& apt-get install -y curl gnupg build-essential libcurl4-openssl-dev openssh-client git\
&& curl -fsSL https://deb.nodesource.com/setup_16.x | bash - \
#&& apt-get remove -y --purge cmdtest \
&& apt-get update \
&& apt-get install -y nodejs \
&& rm -rf /var/lib/apt/lists/* \
&& rm -rf /var/lib/apt/lists.d/* \
&& apt-get autoremove \
&& apt-get clean \
&& apt-get autoclean
RUN adduser --disabled-password --gecos "" --uid 1000 node
RUN chown -R node:node /home/node
USER node
# had to set mode to 0700 otherwise couldn't open .ssh director to write known_hosts file
RUN mkdir -p -m 0700 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts
RUN mkdir -p ~/app/node_modules && chown -R node:node /home/node/app
WORKDIR ~/app
COPY package.json package-lock.json ./
# had to allow uid=1000 access for this to work
RUN --mount=type=ssh,uid=1000 npm ci
COPY --chown=node:node . .
RUN npm run build
希望对其他人有所帮助,因为我花了大约一周的“空闲”时间来达到这一点!
【讨论】:
以上是关于Docker `npm install` 与 TypeScript 中的 GitHub 私有 repo 依赖项的主要内容,如果未能解决你的问题,请参考以下文章
Docker 容器的最大调用堆栈大小超过了 npm install
npm install 在 docker 的 jenkins 管道中失败
npm install 后 Gitlab Shared Runner docker build
在 Docker 中运行时,`npm install` 导致`cb() never called!`