在 Javascript/Typescript monorepo 中使用未发布的包处理 Docker 图像

Posted

技术标签:

【中文标题】在 Javascript/Typescript monorepo 中使用未发布的包处理 Docker 图像【英文标题】:Dealing with Docker images in a Javascript/Typescript monorepo with unpublished packages 【发布时间】:2021-06-26 23:31:47 【问题描述】:

我一直试图找到这个问题的明确答案,但不幸的是我没能找到。有两个类似的 SO 问题涉及这个主题,

Should a developer be able to create a docker artifact from a lerna monorepo in their development environment?

How to build docker images in a lerna monorepo without publishing

但他们没有明确回答,我认为需要添加更多上下文才能获得更清晰的答案。

我正在使用 Next.js 和几个 Express 服务器建立一个爱好项目。我正在构建一组微服务,它们之间会有一个可以共享的公共资源。由于这是一个业余项目,因此将所有这些都存在于一个 git 存储库中是有意义的。同样,作为一个爱好项目,不必将任何包发布到像 NPM 这样的注册表也是有意义的。

让我们想象一个类似于 lerna(一个 JS monorepo 工具)文档展示的结构:

my-lerna-repo/
  package.json
  packages/
    package-1/
      package.json
    package-2/
      package.json

使用 Lerna 之类的工具,您可以拥有一个依赖的 commons 包,并让其他包引用它。 Lerna 将提升这个commons 包并在包的node_modules 中简单地符号链接到它。

这在开发时是有道理的,但是当您将服务容器化时,这在生产中如何工作?例如,如果我们为每个服务创建一个 Dockerfile 并将其扔到 Kubernetes 集群中,则容器将失败,因为 commons 依赖项不存在——它只是一个符号链接。

我查看了 Lerna 的“复制”参数,但没有一个参数存在。我知道还有其他 JS monorepo 工具(例如 Rush),但我知道 Lerna 是最受欢迎的。

如何解决将monorepo依赖包容器化而不发布它们的问题?

【问题讨论】:

【参考方案1】:

对于在开发过程中遇到类似问题的人,我想提供我最终得到的解决方案。

首先,我使用 yarn 工作区在我的单存储库的根目录中设置了一个 package.json:


  "name": "ticketing",
  "private": true,
  "workspaces": [
    "common",
    "service-one",
    "service-two"
  ]

然后,对于每个服务的 docker 文件,我将复制公共项目:

FROM node:alpine as builder
WORKDIR /app

COPY package.json .
COPY common ./common
COPY service-one./service-one


FROM builder as prod
WORKDIR /app
ENV NODE_ENV=production

RUN npm install --prod
CMD npm run prod -w @project/service-one


FROM builder as dev
WORKDIR /app
ENV CI=true

RUN npm install
CMD npm run dev -w @project/service-one

有了这个设置,我不再需要 npm 发布我的公共资源了。

【讨论】:

以上是关于在 Javascript/Typescript monorepo 中使用未发布的包处理 Docker 图像的主要内容,如果未能解决你的问题,请参考以下文章

Javascript/TypeScript 中的 Azure 函数:如何做?

TypeScript初体验

TypeScript系列教程--初探TypeScript

JavaScript / TypeScript 上是不是有“节点”类型? ts(2345)

如何在单独的非 Vue 组件、JavaScript/TypeScript 文件中访问 Vuex 状态?

如何在 javascript/typescript 事件回调中访问它,同时保留 removeEventListener 的能力? [复制]