Closed15

Cloud Build で yarn v3 を使いたい

nbstshnbstsh

Cloud Build official builder に yarn があったのでみる。

https://github.com/GoogleCloudPlatform/cloud-builders/tree/master/yarn

nbstshnbstsh

The Node team provides node images that support multiple tagged versions of yarn and additional Node tooling. Please visit https://hub.docker.com/_/node for details.

dockerhub の node image で yarn 使えるからそっちを使えばいいらしい

cloudbuild.yaml
steps:
- name: 'node'
  entrypoint: 'yarn'
  args: ['install']
nbstshnbstsh

yarn は global に install するもんじゃない

そもそも yarn の version ごとの違いに詳しいわけではないので yarn の 公式 Doc みる。

The preferred way to manage Yarn is by-project and through Corepack, a tool shipped by default with Node.js. Modern releases of Yarn aren't meant to be installed globally, or from npm.

yarn は project 単位で管理するものとのこと。global install は一昔前の話みたい。

https://yarnpkg.com/getting-started/install

nbstshnbstsh

corepack

corepack についてのページを読む。

You may notice by reading our installation guide that we don't tell you to run npm install -g yarn to install Yarn - we even recommend against it. The reason is simple: just like your project dependencies must be locked, so should be the package manager itself.

project 単位で yarn の version も固定したほうが良いよね、とのこと。

Corepack is included with all official Node.js releases starting from Node.js 14.19 / 16.9. It's however opt-in for the duration of the experimental stage, so you'll need to run corepack enable before it's active.

corepack は node に梱包されてるから別途 install する必要はなさげ。ただし enable してあげる必要がある。

corepack enable

https://yarnpkg.com/corepack

nbstshnbstsh

corepack enable さえしてあれば、yarn 使えるようになる。
そんで、project ごとに package.json の packageManager の値に応じて yarn の version が利用されるっぽい。

  "packageManager": "yarn@4.5.1"

つまり、node の image で corepack enable してあげれば良さげ。

nbstshnbstsh

Docker image 作って試す

手元で docker image 作って試してみる。

まず、node image (node:22-alpine) でシンプルに yarn の version 出してみる。

docker run --rm node:22-alpine yarn --version
1.22.22

yarn の version は 1.22.22。

nbstshnbstsh

corepack enable して package.json の指定通りに変わるか

以下の package.json を用意

{
  "name": "corepack-sample",
  "packageManager": "yarn@4.5.1"
}

node image を元に以下を追加した Dockerfile 用意

  • corepack enable 実行
  • package.json を配置
Dockerfile
FROM node:22-alpine

RUN corepack enable

WORKDIR /app

COPY package.json .

docker image build する。

docker build -t corepack-sample .

container 実行して yarn の version 確認

docker run --rm corepack-sample yarn --version

実行結果↓

! Corepack is about to download https://repo.yarnpkg.com/4.5.1/packages/yarnpkg-cli/bin/yarn.js
4.5.1

ちゃんと package.json で指定した version "4.5.1" が利用されている

nbstshnbstsh

corepack enable を除外するとどうなるかも確認してく

Dockerfile
FROM node:22-alpine

- RUN corepack enable

WORKDIR /app

COPY package.json .

image 再 build して確認。

docker build -t corepack-sample .
docker run --rm corepack-sample yarn --version

実行結果↓

1.22.22

ちゃんと node image で設定されるデフォの yarn version になっているのでOK

nbstshnbstsh

build 時に yarn を download させておきたい

! Corepack is about to download https://repo.yarnpkg.com/4.5.1/packages/yarnpkg-cli/bin/yarn.js

上記の例だと、container 実行時に corepack が yarn を download している感がある。image build 時にやっておきたい感。

yarn で何かしらの command が叩かれたタイミングで download してるみたいなので Dockerfile 内で yarn --version を追加しておく。

Dockerfile
FROM node:22-alpine

RUN corepack enable

WORKDIR /app

COPY package.json .

+ RUN yarn --version
docker build -t corepack-sample .
docker run --rm corepack-sample yarn --version

実行結果↓

4.5.1

実行後すぐに表示されたので、ちゃんと download 省けたみたい。

nbstshnbstsh

corepack を利用していない場合

自分の project では corepack を利用した覚えがないため、corepack を利用していない場合のケースについても調べる。

corepack を利用しないで yarn init すると以下2点が生成される

  • .yarnrc.yml
  • .yarn/releases/yarn-$VERSION.cjs

.yarnrc.yaml は yarnPath が指定されているだけ。

.yarnrc.yml
yarnPath: .yarn/releases/yarn-4.5.1.cjs

Path of a Yarn binary to use instead of the global one.
This binary will be executed instead of any other (including the global one) for any command run within the directory covered by the rc file. If the file extension ends with .js it will be required, and will be spawned in any other case.

https://yarnpkg.com/configuration/yarnrc#yarnPath

corepack を利用しない場合は、project の利用する version の yarn binary (といっても cjs) を .yarn/releases に保持するみたい。

つまり、project 内に .yarnrc.yaml が存在し、yarnPath が設定されている場合は global に install したり corepack enable したりする必要はなさそう。

nbstshnbstsh

Docker image で試す

.yarnrc.yaml, .yarn directory を container 内にコピーした状態で、yarn の versioin が .yarnrc.yaml で指定したものか確認する。

.yarnrc.yml
yarnPath: .yarn/releases/yarn-4.5.1.cjs
Dockerfile
FROM node:22-alpine

WORKDIR /app

COPY .yarnrc.yml .
COPY .yarn .yarn
docker build -t corepack-sample .
docker run --rm corepack-sample yarn --version

実行結果↓

4.5.1

問題なく .yarnrc.yml で指定された version になっている。
念の為 container 内で app directory とそれ以外で yarn の version 確認。

docker run --rm -it firebase-yarnv3-docker sh        

ちゃんと app directory 外では node image のデフォの v1.22.22 が利用されていることがわかる↓

nbstshnbstsh

ここまでまとめ

  • Cloud Build で yarn を利用したければ dockerhub の node image を使えばOK
  • node image の yarn の version はデフォで v1.22.22
  • node image で yarn v3 以降を利用したい場合、
    • corepack を利用している場合は corepack enable してあげればOK
    • .yarn/releases 内の binary を利用している場合は .yarnrc.rml と .yarn を container に配置すればOK
nbstshnbstsh

Cloud Build で yarn v3 を使う

自分の project のケースだと、.yarn/releases 内の binary を利用して yarn v3 を使っているため node image をそのまま使えば問題なさそう。

これでOK↓

cloudbuild.yaml
steps:
- name: 'node'
  entrypoint: 'yarn'
  args: ['install']
nbstshnbstsh

実行 directory を指定

dir fiield を指定すればOK

Use the dir field in a build step to set a working directory to use when running the step's container. If you set the dir field in the build step, the working directory is set to /workspace/<dir>. If this value is a relative path, it is relative to the build's working directory. If this value is absolute, it may be outside the build's working directory, in which case the contents of the path may not be persisted across build step executions (unless a volume for that path is specified).

cloudbuild.yaml
steps:
- name: 'node'
  entrypoint: 'yarn'
  args: ['install']
  dir: 'examples/hello_world'

https://cloud.google.com/build/docs/build-config-file-schema#dir

このスクラップは27日前にクローズされました