nodeのバージョンを指定する旅

以前にDockerfileを書いたとき、yarnをインストールすれば一緒にnodeもインストールされることを活用したが、別の環境では違うnodeのバージョンがインストールされてしまった。

nodeとnpmとyarn周りは永遠に悩まされ、その度に調べてはその場しのぎな気がする。

今回の調査結果をまとめておく

やりたいこと と 背景

作っているアプリケーションはnode14系で動作している。

別の環境で開発しようとしたら、同じDockerfileでビルドしたのだが、node16系がインストールされ、そのバージョン違いによるエラーに悩まされた

どの環境でimageをbuildしても、nodejs14系が使われるようにしたい。

方針

まず、yarnのインストール時に一緒にnodeがインストールされることに依存していると、毎回バージョンが変わりかねないので、可能ならnodeを個別にインストールしたい。

最終的にはDockerfileに落とし込むが、まずは動作を確認したいので、コンテナを立ち上げて逐次実行をためしていく

docker run  --rm  -it ruby:2.7.4 bash

node のインストール

nodeのバージョンを指定してのダウンロード/インストールで今回活用できたのは nodesourceというレポジトリ。おそらくは公式。

distributions/README.md at master · nodesource/distributions · GitHub

コマンドが 14.x という書かれ方をしているので、xをほしいバージョンに書き換えるのかと思いきや、そうではないらしい。

minor versionも含めて指定したければもう少し工夫がいりそう。

ともあれ、

curl -fsSL https://deb.nodesource.com/setup_14.x | bash -
apt-get install -y nodejs

を実行すると (なお、ここではコンテナ内のroot userなので、sudo は外してある。sudoはインストールされていない)

# node -v
v14.19.3

と、14系が入った。

ちなみに、親切なことに

## To install the Yarn package manager, run:
     curl -sL https://dl.yarnpkg.com/debian/pubkey.gpg | gpg --dearmor | sudo tee /usr/share/keyrings/yarnkey.gpg >/dev/null
     echo "deb [signed-by=/usr/share/keyrings/yarnkey.gpg] https://dl.yarnpkg.com/debian stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
     sudo apt-get update && sudo apt-get install yarn

と、yarnをいれたければこうしてね、を教えてくれてる。

コマンド内容詳細

一度、実行したコマンドを振り返る

curl -fsSL https://deb.nodesource.com/setup_14.x は、アクセスすればわかるがスクリプトになっている.

curl のオプションはよく見るが、 man curl の結果から転記すると、

  • -s : Silent or quiet mode. Don't show progress meter or error messages.
  • -f : (HTTP) Fail silently (no output at all) on server errors. This is mostly done to better enable scripts etc to better deal with failed attempts.
  • -S : When used with -s, --silent, it makes curl show an error message if it fails.
  • -L : (HTTP) If the server reports that the requested page has moved to a different location (indicated with a Location: header and a 3XX response code), this option will make curl redo the request on the new place

これを | bash - とパイプしている。

--- と同義で、 以降の引き数は全て、ファイル名や引き数として扱われる。

この場合は、 curl -fsSL でダウンロードしたファイルの中身がパイプで渡ってくるので、それをそのまま実行するということになる(はず)。

スクリプトの中身は、少々自信はないが、主にやってることは以下で、distributionファイルをダウンロードして、実行しているように見える。

exec_cmd_nobail() {
    echo "+ $1"
    bash -c "$1"
}

# 略 

if [ -x /usr/bin/curl ]; then
    exec_cmd_nobail "curl -sLf -o /dev/null 'https://deb.nodesource.com/${NODEREPO}/dists/${DISTRO}/Release'"
    RC=$?
else
    exec_cmd_nobail "wget -qO /dev/null -o /dev/null 'https://deb.nodesource.com/${NODEREPO}/dists/${DISTRO}/Release'"
    RC=$?
fi

curl のオプション * -o : Write output to instead of stdout.

yarn のインストール

こちらはもともとDockerfileに以下のように書いていた

RUN echo 'deb http://ftp.jp.debian.org/debian sid main ' >> /etc/apt/sources.list && \
  curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
  echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list

# 略
apt-get install yarn

nodejs インストール時におすすめされていた方法のほうが、安全に見える。

あと、docker build 時に

Warning: apt-key is deprecated. Manage keyring files in trusted.gpg.d instead (see apt-key(8)). と言われていたのを思い出した。

nodesources が教えてくれた方法にしてみる

curl -sL https://dl.yarnpkg.com/debian/pubkey.gpg | gpg --dearmor | tee /usr/share/keyrings/yarnkey.gpg >/dev/null
     echo "deb [signed-by=/usr/share/keyrings/yarnkey.gpg] https://dl.yarnpkg.com/debian stable main" | tee /etc/apt/sources.list.d/yarn.list

ちょっとつまずいたのは、

RUN echo 'deb http://ftp.jp.debian.org/debian sid main ' >> /etc/apt/sources.list && \

としたうえで apt-get update すると、node16系 がインストールされてしまうので、先にnode14系までインストールしてしまってから、yarnインストールのためのスクリプトを実行した。

無事にnodejs14系を使ったうえでアプリケーションが動くことを確認した。