Skip to content

Instantly share code, notes, and snippets.

@denvernine
Last active February 6, 2025 01:40
Show Gist options
  • Save denvernine/0b6e273ed72a2c6519a9669a5d0e7749 to your computer and use it in GitHub Desktop.
Save denvernine/0b6e273ed72a2c6519a9669a5d0e7749 to your computer and use it in GitHub Desktop.
Alpine LinuxでVoltaを使ってみたかったけどできなかった話

Dockerコンテナ内でVoltaを使ってみたかった

DokcerのベースイメージといえばAlpine Linux。といって過言でないほど使われているAlpine Linuxですが、そのままでは Volta は動きません。

ということで一丁うごかしてやろうやないかい、というのがこの記事の目的です。

結論から言うと

nodeの公式Dockerイメージ を見るとわかるのですが、この問題を回避するならソースからビルドすればいいようです。

しかしながら、ソースからビルドしたnodeをVoltaで使うにもかなり手間がかかるでしょうし、 GitHubにあるスレッド でも結局Debianベースにしたようですから、現在のところAlpine LinuxでVoltaを使うのはあまりいい方法ではないようです。

そんなわけで、素直に node:lts-alpine イメージを使えという話なのですが、ここで終わってはあんまりにも情報がなさすぎるので自分なりに試したことを書いておきます。

Voltaってなに?

平たく言ってしまえば「nodeのバージョン管理ツール」です。

この分野でよく聞くのは nvm-sh/nvmnodenv/nodenv あたりじゃないでしょうか。実際 Google Trendsで見てみても 知名度はまだまだ低いです。

GitHubのコミット履歴を見てみると、voltaは2017年9月25日にスタートしたプロジェクトのようです。かなり若手・新鋭といえますね。しかしながらGitHubのスターの数でいえば

  • nvm: 54.1k
  • nodenv: 1.7k
  • volta: 4.8k

となかなか期待されていることがわかります。また、 Voltaの公式サイト によれば

Features

  • 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

glibcをインストール

とりあえず以下を実行してもらえばインストールは終わりです。

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通信ができない?)のでこれもインストールします。

Voltaをインストール

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が使えるようになります。

libstdc++をインストール

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

references

version: "3.8"
services:
app:
image: volta:test
build:
context: ./app
args:
GLIBC_APK_VERSION: 2.34-r0
volumes:
- type: bind
source: ../app
target: /usr/src/app
networks:
- test
logging:
driver: json-file
options:
max-size: 3m
max-file: 1
stdin_open: true
tty: true
networks:
test:
FROM alpine:3.15
ARG GLIBC_APK_VERSION
CMD [ "/bin/sh" ]
ENV GLIBC_BASE_URL="https://github.com/sgerrand/alpine-pkg-glibc/releases/download"
ENV GLIBC_APK_VERSION="2.34-r0"
ENV GLIBC_APK="glibc-${GLIBC_APK_VERSION}.apk"
ENV GLIBC_BIN_APK="glibc-bin-${GLIBC_APK_VERSION}.apk"
RUN 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
ENV VOLTA_HOME="${HOME}/.volta"
ENV PATH="${VOLTA_HOME}/bin:${PATH}"
RUN apk add --no-cache --virtual .volta_installer bash curl openssl \
&& curl https://get.volta.sh | /bin/bash \
&& apk del .volta_installer
RUN apk add libstdc++ \
&& volta install node@lts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment