😮

Homebrew付きAlpine LinuxをDockerで作る

2024/10/19に公開

記事の背景

元々は開発環境をWSL上のUbuntu & Homebrewで構築していましたが、
色々なファイルを誤って削除してしまったりで起動できなくなり、
都度初期化し作り直していたため、構築時間がかさみ、非常に面倒だと感じていました。

その中で2年程前にDockerとAlpine Linuxの存在を知ったことで、
ミニマルな開発環境をイメージ化しておいて、壊れたらコンテナごと削除して作り直す
という構想が出来ました。

しかし、当時はAlpine LinuxにHomebrewを入れるのが至難の業で、そのままでは導入できず、
フォルダをコマンドで作成し、Rubyを一からコンパイルするなど、手順が多く、
自身の技術力の低さも相まって、ミニマルなイメージにするには難しい課題がありました。
参考: 「Alpine Linux 環境への Linuxbrew の導入手法(こちら)」(@z80oolong(Z.OOL.)さん)

HomebrewのIssue(こちら)でもAlpine Linuxへの導入について話がありましたが、
Alpine Linuxの仕様の問題で対応ができずそのままClosedに…。

結局訳あって熱は冷めてしまい、Docker自体も気がつけば触らなくなっていました。

それから時が経ち、技術力も上がったので、改めて挑戦・検証してみたところ、
幾つかのパッケージ導入+αの作業だけで簡単にHomebrewが導入できる事がわかりました。
これにより、UbuntuやDebianを使うよりもミニマルな開発環境を構築しやすくなりました。
この記事を通して少しでも知見が得られましたら幸いです。

導入方法

以下のコードが入ったDockerfileをビルドするだけで、
Homebrew付きAlpine Linuxが導入できます。シンプル!

FROM alpine
RUN apk update --no-cache
RUN apk upgrade --no-cache
RUN apk add bash --no-cache
RUN apk add curl --no-cache
RUN apk add git --no-cache
RUN apk add coreutils --no-cache
RUN apk add grep --no-cache
RUN apk add gcompat --no-cache

RUN echo -n $' \n\
        #!/bin/sh \n\
        while test $# -gt 0; do \n\
            case "$1" in \n\
                --vers | --versi | --versio | --version) \n\
                echo \'ldd (Alpine MUSL 2.13) 2.13\' \n\
                exit 0 \n\
                ;; \n\
            esac \n\
        done \n\
        exec /lib/ld-musl-x86_64.so.1 --list "$@" \n\
    ' > /usr/bin/ldd

RUN /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
ENV PATH "/home/linuxbrew/.linuxbrew/bin:$PATH"

ミニ解説

後に色々なところの仕様が変わり再現ができなくなることを防ぐため、
メモ程度に解説を残します。

  • Windows 11 のDocker Desktopを使用してビルドしました。
    実行したときのAlpine Linuxのバージョンは3.20.3でした。

  • apkの--no-cacheオプションでアプリのインストール等でキャッシュを作らないようにします。
    軽量化が目的。

  • bash curl gitは無いとHomebrewインストール時に「コマンドがない」旨のエラーが出ます。

  • grepcoreutilsにあるsortコマンドは、
    素のAlpineだとHomebrew導入時に必要なオプション引数を認識しないようです。
    具体的には以下です。そのためapkコマンドで導入をしています。

    • grepmax-countオプション
    • sortfield-separatorオプション
  • gcompatglibcの代わりに使える互換レイヤーです。
    導入理由は「Alpine glibc」で検索すると様々な方の記事がありますので省かせてください…。
    Alpine Linuxにデフォルトで入っているmuslをglibcっぽく振る舞わせるものらしいです。
    詳細はGithubのReadmeをご覧いただければ幸いです。 (こちら)

  • echoで長々と書いてあるコードですが、/usr/bin/lddlddコマンドの挙動が
    他のLinux OSとは異なるようで、上書きして他のLinux OSに近しい挙動にしています。
    引用: 「Alpine Linux 環境への Linuxbrew の導入手法(こちら)」(@z80oolong(Z.OOL.)さん)

  • Homebrewのインストールコマンドは公式のGithubリポジトリ(こちら)から引用しました。

  • brewコマンドが利用できるよう環境変数を追加しています。
    DockerなのでPATHENVで指定しています。
    Alpine LinuxをWSL2等で素で使用する場合は環境変数の読み込ませ方に一癖あるようです。
    bashrcみたいな感じで登録できないらしいです。
    (詳細は分からないため、ご自身で検索いただけますと幸いです。)

編集履歴

  • 2024/10/20 Homebrewのインストールコマンドがおかしかったので直しています。

Discussion