DokcerのベースイメージといえばAlpine Linux。といって過言でないほど使われているAlpine Linuxですが、そのままでは Volta は動きません。
ということで一丁うごかしてやろうやないかい、というのがこの記事の目的です。
nodeの公式Dockerイメージ を見るとわかるのですが、この問題を回避するならソースからビルドすればいいようです。
しかしながら、ソースからビルドしたnodeをVoltaで使うにもかなり手間がかかるでしょうし、 GitHubにあるスレッド でも結局Debianベースにしたようですから、現在のところAlpine LinuxでVoltaを使うのはあまりいい方法ではないようです。
そんなわけで、素直に node:lts-alpine
イメージを使えという話なのですが、ここで終わってはあんまりにも情報がなさすぎるので自分なりに試したことを書いておきます。
平たく言ってしまえば「nodeのバージョン管理ツール」です。
この分野でよく聞くのは nvm-sh/nvm か nodenv/nodenv あたりじゃないでしょうか。実際 Google Trendsで見てみても 知名度はまだまだ低いです。
GitHubのコミット履歴を見てみると、voltaは2017年9月25日にスタートしたプロジェクトのようです。かなり若手・新鋭といえますね。しかしながらGitHubのスターの数でいえば
- nvm: 54.1k
- nodenv: 1.7k
- volta: 4.8k
となかなか期待されていることがわかります。また、 Voltaの公式サイト によれば
- Speed ⚡
- Seamless, per-project version switching
- Cross-platform support, including Windows and all Unix shells
- Support for multiple package managers
- Stable tool installation—no reinstalling on every Node upgrade!
- Extensibility hooks for site-specific customization
ということで、速度・クロスプラットフォームが特徴となっています。
bashが使える環境なら2行でセットアップ完了です。
curl https://get.volta.sh | bash
source ~/.bashrc
ではAlpine Linuxではどうかというと、まずbashが使えません。glibcもありません。そんなわけでちょっと手間ですが環境を整えていきましょう。今回のベースイメージは alpine:3.15
です。
docker run --rm --name=volta_test -it alpine:3.15 /bin/sh
とりあえず以下を実行してもらえばインストールは終わりです。
apk update \
&& apk add --no-cache --virtual .volta_build wget ca-certificates \
&& wget -q -O /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub \
&& wget -O "${GLIBC_APK}" "${GLIBC_BASE_URL}/${GLIBC_APK_VERSION}/${GLIBC_APK}" \
&& wget -O "${GLIBC_BIN_APK}" "${GLIBC_BASE_URL}/${GLIBC_APK_VERSION}/${GLIBC_BIN_APK}" \
&& apk add --no-cache "${GLIBC_APK}" "${GLIBC_BIN_APK}" \
&& rm "${GLIBC_APK}" "${GLIBC_BIN_APK}" \
&& apk del .volta_build
Alpine Linux向けにビルドされているglibcが公開されているので、ありがたく使わせていただきます。また、Alpine Linuxにはwgetがない(busyboxに組み込まれているwgetはSSL通信ができない?)のでこれもインストールします。
glibcが入ってしまえば例の2行にひと手間加えて終わりです。
apk add --no-cache --virtual .volta_installer bash curl openssl \
&& curl https://get.volta.sh | /bin/bash \
&& apk del .volta_installer
. ${HOME}/.profile
なりでパスを通せばVoltaが使えるようになります。
nodeが依存しているライブラリです。
apk add libstdc++
/usr/lib
配下に libstdc++.so.6.0.28
がインストールされます。
volta install node@lts && node --version
## ...
node: /usr/lib/libstdc++.so.6: no version information available (required by node)
node: /usr/lib/libstdc++.so.6: no version information available (required by node)
node: /usr/lib/libstdc++.so.6: no version information available (required by node)
node: /usr/lib/libstdc++.so.6: no version information available (required by node)
node: /usr/lib/libstdc++.so.6: no version information available (required by node)
node: /usr/lib/libstdc++.so.6: no version information available (required by node)
node: /usr/lib/libstdc++.so.6: no version information available (required by node)
node: /usr/lib/libstdc++.so.6: no version information available (required by node)
v16.13.1
おや?
nodeの公式Dockerイメージ を見るとわかるのですが、この問題を回避するならソースからビルドすればいいようです。
しかしながら、ソースからビルドしたnodeをVoltaで使うにもかなり手間がかかるでしょうし、 GitHubにあるスレッド でも結局Debianベースにしたようですから、現在のところAlpine LinuxでVoltaを使うのはあまりいい方法ではないようです。
お手軽にVoltaをつかうなら、以下のようなComposeファイルになります。
# compose.yaml
services:
app:
build:
dockerfile: Dockerfile
args:
UNAME: ${USER}
UID: ${UID:-1000}
GID: ${UID:-1000}
volumes:
- type: bind
source: ./src
target: /home/${USER}/.local/app
bind:
create_host_path: false
working_dir: /home/${USER}/.local/app
tty: true
stdin_open: true
#Dockerfile
FROM ubuntu:latest
ARG UNAME
ARG UID
ARG GID
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
curl \
ca-certificates \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
RUN groupadd --gid ${GID} ${UNAME} \
&& useradd -s /bin/bash --uid ${UID} --gid ${GID} -m ${UNAME}
USER ${UNAME}
ENV HOME=/home/${UNAME}
ENV VOLTA_HOME=${HOME}/.volta
ENV PATH=${VOLTA_HOME}/bin:$PATH
RUN curl -sSL https://get.volta.sh | bash
docker compose build --force-rm --build-arg UNAME=$(id -un) --build-arg UID=$(id -u) --build-arg GID=$(id -g)
docker compose run --rm --user $(id -u):$(id -g) -- app bash