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 buildtsc -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)项目的依赖项(它们位于 ma​​in 的 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!`

docker image 上的 npm global install 没有访问权限错误

npm install git+ssh 在 docker (node16) 中失败