はじめに
自分のパソコンでは環境が出来上がっている状態で
みんなで環境構築をやろう! 教えよう! となったとき。
みなさんならどうするでしょうか。
細かい差異も見逃さないために、自分のパソコンに入っているパッケージをアンインストールして、環境構築の実演をしてみせるでしょうか。
(自分のパソコンの環境をいじるのは面倒くさいので)細かいことは気にせず、手順書を作って見守る(適宜困ったことがあったら助ける)でしょうか。
今回は、「自分の環境を汚したくないけど、確実に環境構築をやってもらうために実演をしたい」ってときにDockerコンテナ
使えないかなーと色々調べてみた結果は紹介させてもらいます。
※ あまり実践的ではないです。
知れること・知れないこと
※ 結果的にやっていることはubuntu18.04のイメージにLinuxbrew
をDockerfileでインストールする方法になります。
知れること
- ubuntuのイメージにLinuxbrewをDockerfileを使ってインストールする方法
- 素人目線のDockerfileの書き方のポイント
知れないこと
- windowsで環境構築を実演する際のDockerイメージの作り方
実現方法の考え方
おおよそmacではHomebrew
使って、パッケージインストールして、環境構築等するだろうという偏見仮定の元、
「LinuxbrewをLinuxのDockerイメージに入れたら、見かけ上はmacでHomebrew使うのと変わらなくない? ほらコマンドもbrewで変わらないし……」
という安直な考えで、Linuxbrew
の利用を考えます。
Linuxbrew
Linuxbrew
とはHomebrew
のLinux版(名前そのまま)です。
2019年2月から本家 Homebrew 2.0.0 にてLinuxbrewが正式にサポートされるとのことなので(homebrew-2.0.0)、使わない手はないです。
参考
LinuxbrewでUbuntu18.04のパッケージ管理
Linuxbrewのススメ
目標
作成したイメージのDockerコンテナに入って
$ brew doctor
とコマンドを叩いて、一発でYour system is ready to brew.
と出てくることを目指します。
ホームディレクトリにLinuxbrewをインストールするDockerfile
こちらは道半ばバージョンです。
Linuxbrewは/home/linuxbrew/.linuxbrew
下にインストールすることが推奨されています。
上記デフォルトのディレクトリにインストールすることで、ビルド済みバイナリがあるパッケージはバイナリをインストールできるようになります。
そのためインストール場所がデフォルトでないとbrew doctor
でWarningが出ます。
ただ、Dockerfileで/home/linuxbrew/.linuxbrew
配下にLinuxbrewをインストールするには、私が試した限り、少々特殊なことをする必要がありました。
こちらはこちらで「素直にDockerfileを書いたバージョン」として、記載しておきたいと思います。
こちらの方法だと/home/[ユーザ名]/.linuxbrew/
にインストールされることになります。Warningが出るだけでLinuxbrewは普通に利用可能です。
FROM ubuntu:18.04
LABEL maintainer beeeeyan
#環境変数を設定
ENV DEBIAN_FRONTEND=noninteractive
ENV USER beeeeyan
ENV HOME /home/${USER}
ENV SHELL /bin/bash
ENV PW password
# 種々インストール
RUN apt-get update && \
apt-get install -y --no-install-recommends \
vim \
sudo \
locales \
build-essential \
ca-certificates \
curl \
file \
git && \
# 一般ユーザーアカウント追加
useradd -m ${USER} && \
# 一般ユーザーにsudo権限を付与
gpasswd -a ${USER} sudo && \
# 一般ユーザーのパスワードを設定
echo "${USER}:${PW}" | chpasswd && \
# ログインシェルを指定
sed -i.bak -r s#${HOME}:\(.+\)#${HOME}:${SHELL}# /etc/passwd && \
# localの設定
locale-gen en_US.UTF-8
# コマンドを実行するUSERを変更
USER ${USER}
# 作業ディレクトリを指定
WORKDIR ${HOME}
# Linuxbrewをインストール
RUN sh -c "$(curl -fsSL https://raw.githubusercontent.com/Linuxbrew/install/master/install.sh)" && \
# pathの設定
echo 'export PATH=${HOME}/.linuxbrew/bin:$PATH' >> .bash_profile
説明
素人目線のDockerfileの書き方にも触れています。
今回の「Linuxbrewのインストール」に深く関わる箇所には気持ち最初に☆付けました。
LABEL maintainer beeeeyan
MAINTAINER(作成者情報)はDocker 1.13から非推奨(deprecated)となっているそうです。LABELで書きましょう。
参考 : 1.13以降はMAINTAINERの代わりにLABELを使うようにしよう
ENV DEBIAN_FRONTEND=noninteractive
brew doctor
で出てくるエラーを潰す仮定でlocales
をインストールすることにしたのですが(後述)、locales
をインストールしようとするとapt-get install
自体が止まったので設定しました。詳しくは以下参照ください。
参考 : Docker Ubuntu18.04でtzdataをinstallするときにtimezoneの選択をしないでinstallする
RUN apt-get update && \
apt-get install -y --no-install-recommends \
ここいらへんは呪文ですね。--no-install-recommends
の意味を知らなかったのですが「指定したもの以外余計なものは入れない」ということみたいです。
参考 : #Linux #Ubuntu #docker #Dockerfile のこれは何? apt-get install --no-install-recommends
vim \
sudo \
locales \
build-essential \
ca-certificates \
curl \
file \
git && \
~省略~
# localの設定
locale-gen en_US.UTF-8
-
vim
とsudo
あると便利かな、くらいで入れています。sudo
に関しては「完成版」では必須です。 -
locales
…(省略)…locale-gen en_US.UTF-8
brew doctor
とコマンド叩いて、以下のようなエラーが出たのでインストール&設定しました。
warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8): No such file or directory …(省略)
- ☆
build-essential
とca-certificates
とcurl
とfile
とgit
調べてもらったらわかりますが、build-essential
とcurl
とfile
とgit
については、Linuxbrewをインストールするときに公式で先にインストールするよう指定されているパッケージです。
ポイントは ca-certificatesを指定するところにあります。(これがないとcurl
などを使っても通信ができません)このパッケージは普段は自動でインストールされるものです。勘のいい方はお分かりかと思いますがapt-get install
に--no-install-recommends
を指定した影響で明示的に書いておく必要が出てきたパッケージです。
参考 : 公式
# 一般ユーザーアカウント追加
useradd -m ${USER} && \
# 一般ユーザーにsudo権限を付与
gpasswd -a ${USER} sudo && \
# 一般ユーザーのパスワードを設定
echo "${USER}:${PW}" | chpasswd && \
# ログインシェルを指定
sed -i.bak -r s#${HOME}:\(.+\)#${HOME}:${SHELL}# /etc/passwd && \
☆ 一般ユーザを追加している部分
ユーザを追加する理由はrootユーザでLinuxbrewをインストールしようとするエラーになるからです。参考先の情報からsed
コマンドの書き方は多少調整しました。
参考 : Dockerで開発環境を仮想化する
# コマンドを実行するUSERを変更
USER ${USER}
# 作業ディレクトリを指定
WORKDIR ${HOME}
コマンドを実行するユーザとディレクトリを作成したユーザに変更しています。
後は公式のインストールコマンド叩いて.bash_profile
にLinuxbrewのパス(今回だと/home/[ユーザ名]/.linuxbrew/bin
)を指定するだけです。
なぜ「素直な書き方」では/home/linuxbrew/.linuxbrew
にインストールできないのか?
素直な書き方だとビルド中に以下のような応答が求められます。
==> Select the Homebrew installation directory
- Enter your password to install to /home/linuxbrew/.linuxbrew (recommended)
- Press Control-D to install to /home/[ユーザ名]/.linuxbrew
- Press Control-C to cancel installation
ここでEnter your password
できなくてつみます。
ただ不思議とControl-D
の挙動はしてくれて、/home/[ユーザ名]/.linuxbrew
にインストールされるという寸法です。
[完成版]/home/linuxbrew/.linuxbrew
にLinuxbrewをインストールするDockerfile
ほんの少しトリッキーなことをしたのですが、以下でうまくいきました。
FROM ubuntu:18.04
LABEL maintainer beeeeyan
#環境変数を設定
ENV DEBIAN_FRONTEND=noninteractive
ENV USER beeeeyan
ENV HOME /home/${USER}
ENV SHELL /bin/bash
ENV PW password
# 種々インストール
RUN apt-get update && \
apt-get install -y --no-install-recommends \
vim \
sudo \
locales \
build-essential \
ca-certificates \
curl \
file \
git && \
# 一般ユーザーアカウント追加
useradd -m ${USER} && \
# 一般ユーザーにsudo権限を付与
gpasswd -a ${USER} sudo && \
# 一般ユーザーのパスワードを設定
echo "${USER}:${PW}" | chpasswd && \
# ログインシェルを指定
sed -i.bak -r s#${HOME}:\(.+\)#${HOME}:${SHELL}# /etc/passwd && \
# localの設定
locale-gen en_US.UTF-8 && \
# linuxbrewの「Alternative Installation」を実行
git clone https://github.com/Homebrew/brew /home/linuxbrew/.linuxbrew/Homebrew && \
mkdir /home/linuxbrew/.linuxbrew/bin && \
ln -s /home/linuxbrew/.linuxbrew/Homebrew/bin/brew /home/linuxbrew/.linuxbrew/bin && \
eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv)
# コマンドを実行するUSERを変更
USER ${USER}
# 作業ディレクトリを指定
WORKDIR ${HOME}
# Linuxbrew関連のフォルダ作成
RUN echo ${PW} | sudo -S mkdir -p /home/linuxbrew/.linuxbrew/etc \
/home/linuxbrew/.linuxbrew/include \
/home/linuxbrew/.linuxbrew/lib \
/home/linuxbrew/.linuxbrew/opt \
/home/linuxbrew/.linuxbrew/sbin \
/home/linuxbrew/.linuxbrew/share \
/home/linuxbrew/.linuxbrew/var/homebrew/linked \
/home/linuxbrew/.linuxbrew/var/homebrew/locks \
/home/linuxbrew/.linuxbrew/Cellar && \
# 権限変更
echo ${PW} | sudo -S chown -R ${USER} /home/linuxbrew/.linuxbrew/etc \
/home/linuxbrew/.linuxbrew/include \
/home/linuxbrew/.linuxbrew/lib \
/home/linuxbrew/.linuxbrew/opt \
/home/linuxbrew/.linuxbrew/sbin \
/home/linuxbrew/.linuxbrew/share \
/home/linuxbrew/.linuxbrew/var/homebrew/linked \
/home/linuxbrew/.linuxbrew/Cellar \
/home/linuxbrew/.linuxbrew/Homebrew \
/home/linuxbrew/.linuxbrew/bin \
/home/linuxbrew/.linuxbrew/var/homebrew/locks && \
# パスの設定
echo 'export PATH="/home/linuxbrew/.linuxbrew/bin:$PATH"' >> .bash_profile && \
# パスの反映
. ~/.bash_profile && \
# brew doctorの実行
brew doctor
ポイントは公式の「Alternative Installation」の部分です。
# linuxbrewの「Alternative Installation」を実行
git clone https://github.com/Homebrew/brew /home/linuxbrew/.linuxbrew/Homebrew && \
mkdir /home/linuxbrew/.linuxbrew/bin && \
ln -s /home/linuxbrew/.linuxbrew/Homebrew/bin/brew /home/linuxbrew/.linuxbrew/bin && \
eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv)
「Alternative Installation」で説明されている内容は、任意の場所にLinuxbrew
をインストールする際によく利用されるコマンドです。これをデフォルトの場所にインストールする方式で利用します。
つまり「Alternative Installation」に書かれているインストール場所~/.linuxbrew/Homebrew
を/home/linuxbrew/.linuxbrew/Homebrew
に変更します。(変更した状態のものが上記コマンドです)
# Linuxbrew関連のフォルダ作成
RUN echo ${PW} | sudo -S mkdir -p /home/linuxbrew/.linuxbrew/etc \
/home/linuxbrew/.linuxbrew/include \
/home/linuxbrew/.linuxbrew/lib \
/home/linuxbrew/.linuxbrew/opt \
/home/linuxbrew/.linuxbrew/sbin \
/home/linuxbrew/.linuxbrew/share \
/home/linuxbrew/.linuxbrew/var/homebrew/linked \
/home/linuxbrew/.linuxbrew/var/homebrew/locks \
/home/linuxbrew/.linuxbrew/Cellar && \
# 権限変更
echo ${PW} | sudo -S chown -R ${USER} /home/linuxbrew/.linuxbrew/etc \
/home/linuxbrew/.linuxbrew/include \
/home/linuxbrew/.linuxbrew/lib \
/home/linuxbrew/.linuxbrew/opt \
/home/linuxbrew/.linuxbrew/sbin \
/home/linuxbrew/.linuxbrew/share \
/home/linuxbrew/.linuxbrew/var/homebrew/linked \
/home/linuxbrew/.linuxbrew/Cellar \
/home/linuxbrew/.linuxbrew/Homebrew \
/home/linuxbrew/.linuxbrew/bin \
/home/linuxbrew/.linuxbrew/var/homebrew/locks && \
後半はbrew doctor
と打って怒られる部分を先回りして処理しています。
sudo
で求められるパスワードはecho
と-S
オプションで乗り越え、
前半は必要なフォルダの作成・後半はフォルダの権限の変更(rootユーザではLinuxbrew
が利用できないので)、、といった具合です。
権限の変更はエラーでは${whoami}
でしたが、Dockerfileの統一感を考えて${USER}
でここでは書きました。
# brew doctorの実行
brew doctor
パスを追加して、最後に一回brew doctor
を実行しておきます。
一回目のbrew doctor
では、一部brew
のツールらしきものがインストールされます。(一発でYour system is ready to brew
と出てこない!)
コンテナを立ち上げるまで〜〜
ビルドします。(試行錯誤する段階では、私はAutomated Build Dockerでやってました)
Dockerfileがカレントディレクトリに存在する状態で以下コマンドを実行
$ docker build -t [イメージ名の指定] .
コンテナの起動
$ docker run --name [コンテナ名の指定] -it -d [イメージ名] /bin/bash
起動中のコンテナに入る
※ちょっとした話ですが--login
をつけておかないと.bash_profile
に指定した設定が反映されないのでご注意ください。(パスが反映されずbrew doctor
が実行できない…)
起動中のコンテナに入る
$ docker exec -it [コンテナ名] /bin/bash --login
今回の目標達成です!
参考
-
DockerでCentOS7のコンテナを用意してLinuxbrewをインストールする
expectコマンドに言及されていて、私も格闘しましたが難しかったです。 -
Dockerfileを書くときに気をつけていること10選
Dockerfileの書き方の参考。 -
LinuxbrewでUbuntu18.04のパッケージ管理
Linuxbrewについて