开发人员是不是应该能够在他们的开发环境中从 lerna monorepo 创建 docker 工件?

Posted

技术标签:

【中文标题】开发人员是不是应该能够在他们的开发环境中从 lerna monorepo 创建 docker 工件?【英文标题】:Should a developer be able to create a docker artifact from a lerna monorepo in their development environment?开发人员是否应该能够在他们的开发环境中从 lerna monorepo 创建 docker 工件? 【发布时间】:2019-10-11 04:05:05 【问题描述】:

我最近开始使用 lerna 来管理一个 monorepo,并且在开发中它运行良好。

Lerna 在我的各种包之间创建符号链接,因此像 'tsc --watch' 或 nodemon 这样的工具可以很好地检测其他包中的更改。

但是我在这个环境中创建 docker 镜像时遇到了问题。

假设我们有一个具有这种结构的项目:

root
  packages
     common → artifact is a private npm package, this depends on utilities, something-specific
     utilities → artifact is a public npm package
     something-specific -> artifact is a public npm package
     frontend → artifact is a docker image, depends on common
     backend → artifact is a docker image, depends on common and utilities

在这种情况下,在开发中,一切都很好。我正在运行某种实时重新加载服务器,并且符号链接可以正常工作,以便依赖项正常工作。

现在假设我想从后端创建一个 docker 映像。

我将介绍一些场景:

    我在我的 Dockerfile 中ADDpackage.json,然后运行 ​​npm install。

    不起作用,因为未发布公共和实用程序包。

    我在后端运行我的构建命令,在 docker 文件中添加 /build 和 /node_modules。

    不起作用,因为我构建的后端有 require('common')require('utilities') 命令,它们位于 node_modules(符号链接)中,但 Docker 只会忽略这些符号链接文件夹。

    解决方法: 使用 cp --dereference 来“取消符号链接”节点模块可以正常工作。请参阅此AskUbuntu question。

    第 1 步,但在构建 docker 映像之前,我会发布 npm 包。

    这没问题,但对于正在检查代码库并修改commonutilities 的人来说,它不会起作用,因为他们没有发布 npm 包的权限。

    我将backendbuild 命令配置为不将commonutilities 视为外部,将common 配置为不将something-specific 视为外部。

    我认为首先构建something-specific,然后是common,然后是utilities,然后是backend

    这样,当构建发生时,并在 webpack 中使用这种技术,捆绑包将包含来自 something-specfic、common 和 utilities 的所有代码。

    但这管理起来很麻烦。

这似乎是我试图在这里解决的一个非常简单的问题。当前在我的机器上运行的代码,我想拉出并放入一个 docker 容器中。

请记住,我们在这里想要实现的关键是让某人能够检查代码库、修改任何包,然后构建 docker 映像,所有这些都来自他们的开发环境。

我在这里是否缺少明显的 lerna 技术,或者我可以用来考虑解决此问题的 devops 参考框架?

【问题讨论】:

您找到可行的解决方案了吗,我也面临类似的问题? 我不明白这个问题的方方面面:一个问题是构建所有尊重依赖的 npm 工件。 package.json 工作区功能还可以。 npm 不能很好地处理这个问题,yarn 做得更好,Lerna 增加了一些功能。第二个问题是构建多个 docker 镜像。每个子项目都有自己的 Dockerfile。然后 CI 和 CD 工具将完成剩下的工作,因为它们在构建 npm 工件后运行,它们将拥有构建 docker 映像的一切。 强制性 +1 - 很想知道您是否曾在这里提出过合理的解决方案 @dwjohnston 这里与我的问题有关:***.com/questions/59320343/… cp --dereference 方法仅适用于在 monorepo 中没有使用同一库的不兼容版本的简单情况。 【参考方案1】:

我们遇到了类似的问题,这就是我们所做的:将 Dockerfile 放在 monorepo 的根目录中(lerna.json 所在的位置)。

原因:您确实将整个 repo 视为单一事实来源,并且您希望对整个 repo 的任何修改都反映在 docker 映像中,因此为单个包使用单独的 Dockerfile 就没有意义了。

Dockerfile

FROM node:12.13.0

SHELL ["/bin/bash", "-c"]

RUN mkdir -p /app
WORKDIR /app

# Install app dependencies
COPY package.json /app/package.json
COPY yarn.lock /app/yarn.lock
COPY packages/frontend/package.json /app/packages/frontend/package.json
COPY packages/backend/package.json /app/packages/backend/package.json
COPY lerna.json /app/lerna.json
RUN ["/bin/bash", "-c", "yarn install"]

# Bundle app source
COPY . /app
RUN ["/bin/bash", "-c", "yarn bootstrap"]
RUN ["/bin/bash", "-c", "yarn build"]

EXPOSE 3000

CMD [ "yarn", "start" ]

package.json


  "private": true,
  "workspaces": [
    "packages/*"
  ],
  "scripts": 
    "bootstrap": "lerna clean --yes && lerna bootstrap",
    "build": "lerna run build --stream",
    "start": "cross-env NODE_ENV=production node dist/backend/main",
  ,
  "devDependencies": 
    "lerna": "^3.19.0",
    "cross-env": "^6.0.3"
  ,


【讨论】:

这是一个有趣的想法。我对数十种服务和多年发展的这种扩展有些怀疑。还有一个缺点是将自己限制在单个操作系统/容器基础镜像上,我通常将不同的基础镜像用于不同的目的。 @GudlaugurEgilsson,您始终可以使用 ARG 作为基本映像,这样您就不会受到限制。 另外一个问题是 monorepos 可能是 NPM 包以及应用程序/UI/API 的混合体。当然,您不想 dockerize 的包,但应用程序/UI/API(在其 package.json 文件中都标记为 private: true确实需要 dockerized。【参考方案2】:

聚会迟到了,但我的方法是将 webpack 与 webpack-node-externalsgenerate-package-json-webpack-plugin 结合使用,请参阅 npmjs.com/package/generate-package-json-webpack-plugin。

使用节点外部,我们可以将来自其他工作区(libs)的所有依赖项捆绑到应用程序中(这使得私有 npm 注册表过时)。使用 generate package json 插件,会创建一个新的 package json,其中包含除我们的工作空间依赖项之外的所有依赖项。有了这个包旁边的 json 包,我们可以在 dockerfile 中执行 npm 或 yarn install。

【讨论】:

以上是关于开发人员是不是应该能够在他们的开发环境中从 lerna monorepo 创建 docker 工件?的主要内容,如果未能解决你的问题,请参考以下文章

软件开发-人员流动

每个优秀的 .NET 开发人员都应该能够回答的问题? [关闭]

Linux开发环境搭建与使用——ubuntu更新设置

编程开发必读书籍:每个Web开发人员都应该阅读的10本书[图]

敏捷开发原则

Windows Phone 平台是不是支持应用程序开发人员的受限/测试版?