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

dwj*_*ton 13 docker microservices devops monorepo

我最近开始使用 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
Run Code Online (Sandbox Code Playgroud)

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

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

我将介绍一些场景:

  1. ADD在我的 Dockerfile 中打包.json,然后运行 ​​npm install。

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

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

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

    解决方法:使用cp --dereference“取消符号链接”节点模块工作。请参阅此AskUbuntu 问题

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

    这可以正常工作,但是对于正在检查代码库并对commonor进行修改的人来说utilities,这是行不通的,因为他们没有发布 npm 包的特权。

  4. 我将build命令配置backend为不视为commonutilities视为外部,以及commonsomething-specific视为外部。

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

    这样,当构建发生时,并在 webpack 中使用这种技术,bundle 将包含来自something-specfic, common 和utilities.

    但这管理起来很麻烦。

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

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

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

小智 2

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

原因是:您确实将整个存储库视为单一事实来源,并且希望对整个存储库的任何修改都反映在 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" ]

Run Code Online (Sandbox Code Playgroud)

包.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"
  },
}

Run Code Online (Sandbox Code Playgroud)

  • 这是一个有趣的想法。我对数十项服务和多年开发的这种扩展有些怀疑。还有一个缺点是限制自己只能使用单个操作系统/容器基础映像,我通常将不同的基础映像用于不同的目的。 (7认同)