带有 yarn 工作区和 docker 没有 docker 文件的节点 monorepo
node monorepo with yarn workspaces and docker without dockerfiles
我正在尝试找到一个合适的设置来为 yarn workspaces monorepo 中的各个服务创建 docker 图像,例如这个:
packages/
├─ svc1/
│ ├─ package.json
├─ svc2/
│ ├─ package.json
├─ .../
package.json
yarn.lock
尝试在每个服务包中使用 Dockerfile 时出现问题:锁定文件位于存储库根目录,并且这些包可能使用 workspace:
协议引用存储库中的其他一些包。
这将使 install
步骤失败。
因此我想创建一个保留 monorepo 布局的“构建”图像
- 1-复制
package.json
和yarn.lock
- 1.1- 可选择挂载 .yarn/cache 目录(使用 docker 在构建时很难做到)
- 2- 运行 安装步骤
- 3- 提交 repo 容器
我将能够从此构建映像中获取给定的包依赖项并将适当的构建工件复制到 运行 我的 services/apps.
Dockerfile 在这里不是一个选项,因为目录布局:
- 不可能
COPY **/package.json
尊重目录
- 构建上下文很大(我知道。docker忽略可能有帮助)
- 项目可以added/removed我不想每次都编辑docker文件,按照repo布局
我调查了在 repo 根目录下创建一个脚本
- 创建自定义 docker 容器(例如来自 node:alpine)
- 复制每个 package.json 目录布局和锁定文件(& mount .yarn/cache?)
- 运行 安装cmd
- 提交容器
我无法创建一个合适的脚本来执行此操作,我无法 docker cp
我刚刚使用 docker create
创建的容器中的文件,但我的 docker 技能可能是低。
您知道如何使用 shell 脚本 create/commit 这张图片吗?
谢谢
经过多次尝试和错误,我设法做到了:
#!/usr/bin/env sh
set -eo pipefail
echo "pulling node:alpine..."
# find . -name node_modules -prune -false -o -name package.json
workdir="/opt/myrepo"
mountpath="$(pwd)/.yarn/cache"
container=$(docker create --tty --workdir "${workdir}" --mount type=bind,source=${mountpath},target=${workdir}/.yarn/cache,readonly node:alpine sh)
echo "container id=\"${container}\""
echo "docker start \"${container}\""
docker start "${container}"
find . -name node_modules -prune -false -o -name package.json | while IFS= read file; do
path=$(dirname "${file}")
echo "docker exec \"${container}\" mkdir -p \"${path}\""
docker exec "${container}" mkdir -p "${path}"
echo "docker cp \"${file}\" \"${container}:${file}\""
docker cp "${file}" "${container}:${workdir}/${file}"
done
docker cp .yarnrc.yml "${container}":${workdir}/
docker cp yarn.lock "${container}":${workdir}/
docker cp .yarn/plugins "${container}":${workdir}/.yarn/
docker cp .yarn/releases "${container}":${workdir}/.yarn/
docker exec --workdir "${workdir}" "${container}" yarn workspaces focus --all --production
docker commit "${container}" "myrepo:latest"
docker stop "${container}"
echo "done"
这看起来很古怪,但确实有效。有没有更优雅的解决方案?
我正在尝试找到一个合适的设置来为 yarn workspaces monorepo 中的各个服务创建 docker 图像,例如这个:
packages/
├─ svc1/
│ ├─ package.json
├─ svc2/
│ ├─ package.json
├─ .../
package.json
yarn.lock
尝试在每个服务包中使用 Dockerfile 时出现问题:锁定文件位于存储库根目录,并且这些包可能使用 workspace:
协议引用存储库中的其他一些包。
这将使 install
步骤失败。
因此我想创建一个保留 monorepo 布局的“构建”图像
- 1-复制
package.json
和yarn.lock
- 1.1- 可选择挂载 .yarn/cache 目录(使用 docker 在构建时很难做到)
- 2- 运行 安装步骤
- 3- 提交 repo 容器
我将能够从此构建映像中获取给定的包依赖项并将适当的构建工件复制到 运行 我的 services/apps.
Dockerfile 在这里不是一个选项,因为目录布局:
- 不可能
COPY **/package.json
尊重目录 - 构建上下文很大(我知道。docker忽略可能有帮助)
- 项目可以added/removed我不想每次都编辑docker文件,按照repo布局
我调查了在 repo 根目录下创建一个脚本
- 创建自定义 docker 容器(例如来自 node:alpine)
- 复制每个 package.json 目录布局和锁定文件(& mount .yarn/cache?)
- 运行 安装cmd
- 提交容器
我无法创建一个合适的脚本来执行此操作,我无法 docker cp
我刚刚使用 docker create
创建的容器中的文件,但我的 docker 技能可能是低。
您知道如何使用 shell 脚本 create/commit 这张图片吗?
谢谢
经过多次尝试和错误,我设法做到了:
#!/usr/bin/env sh
set -eo pipefail
echo "pulling node:alpine..."
# find . -name node_modules -prune -false -o -name package.json
workdir="/opt/myrepo"
mountpath="$(pwd)/.yarn/cache"
container=$(docker create --tty --workdir "${workdir}" --mount type=bind,source=${mountpath},target=${workdir}/.yarn/cache,readonly node:alpine sh)
echo "container id=\"${container}\""
echo "docker start \"${container}\""
docker start "${container}"
find . -name node_modules -prune -false -o -name package.json | while IFS= read file; do
path=$(dirname "${file}")
echo "docker exec \"${container}\" mkdir -p \"${path}\""
docker exec "${container}" mkdir -p "${path}"
echo "docker cp \"${file}\" \"${container}:${file}\""
docker cp "${file}" "${container}:${workdir}/${file}"
done
docker cp .yarnrc.yml "${container}":${workdir}/
docker cp yarn.lock "${container}":${workdir}/
docker cp .yarn/plugins "${container}":${workdir}/.yarn/
docker cp .yarn/releases "${container}":${workdir}/.yarn/
docker exec --workdir "${workdir}" "${container}" yarn workspaces focus --all --production
docker commit "${container}" "myrepo:latest"
docker stop "${container}"
echo "done"
这看起来很古怪,但确实有效。有没有更优雅的解决方案?