Reputation: 1321
I'm trying to find a proper setup to create docker images for individual services in a yarn workspaces monorepo such as this one :
packages/
├─ svc1/
│ ├─ package.json
├─ svc2/
│ ├─ package.json
├─ .../
package.json
yarn.lock
There is an issue when trying to use a Dockerfile inside each service package: the lockfile is located at repo root and the packages may reference some other packages in the repo using workspace:
protocol.
That would make the install
step fail.
Therefore I wanted to create a "build" image that preserves the monorepo layout
package.json
s and yarn.lock
The I would be able to fetch a given package dependencies from this build image and copy appropriate build artifacts to run my services/apps.
Dockerfile is not an option here because because of the directory layout:
COPY **/package.json
respecting directoriesI investigated creating a script at repo root that would
I could not manage to create a proper script to do that, I can't docker cp
files in a container I just created using docker create
but my docker skills may be low.
Would you know how to create/commit this image using a shell script ?
Thank you
Upvotes: 1
Views: 1371
Reputation: 1321
After many trial and errors I managed to do this :
#!/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"
This seem quirky but that worked. Is there a more elegant solution ?
Upvotes: 1