(2023-12-03 初稿 - 2023-12-19 修正・追記)
はじめに
Alpine Linuxのことは、Dockerのことを調べていたら、人気のあるデストリビューションであること初めて知った。
最初に驚いたのは、そのサイズの小ささ。
$ docker pull alpine $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE alpine latest b541f2080109 2 days ago 7.34MB tensorflow/tensorflow latest fc4fde60d99e 2 months ago 1.76GB busybox latest a416a98b71e2 4 months ago 4.26MB hello-world latest 9c7a54a9a43c 7 months ago 13.3kB
なんと、7.34MBでhello-worldよりも小さく、busyboxよりもちょっと大きいだけ。
Alpine Linuxのことは、ほとんど知らないけど、このサイズならいろいろといじって、dockerのことを勉強しようと思った。
Dockerを使っていて、不便だと感じていた点
Dockerを使っていて不便だと感じていた点は、主に以下の2つ。
- 新しいContainerを作成するたびに、ユーザの追加やインストール、設定を実行する必要がある
- 特に docker run コマンドでオプションを間違えると後で変更が大変
最初の不便は Dockerfile を作成することで、ほとんどの部分は解消する。
2番目の不便なことも、commitとすることでrunのオプションを変更できるけど、Dockerfileがうまくできていれば、再度runし直しても大して手間がかからないことがわかった。
このページでは、Docker初心者の筆者が、Alpine Linuxを育みながらDockerの設定についてのメモを記す。
Alpine Linuxをインストールしたらやること
Alpine Linuxをインストールして、一時的に利用する場合で無ければ、筆者はたぶん以下のことをする。
- alpine Linux のアップデートアップ、グレード(apk update && apk upgrade)
- ユーザ(例:hoge)の追加 (adduser)
- プロンプトの変更 user@hostname:directory 形式 #2023-12-06 追記
- /home/hoge/bin の作成 #2023-12-06 追記
- /home/hoge/bin へのPATH 追加 #2023-12-06 追記
- sudoのインストール( apk add sudo)
- opensshのインストール(apk add openssh)
- /etc/hostsの設定 #2023-12-19 追記
- 各種ソフトウェアの設定ファイルのコピー等
上記のうち、1〜7までは、Dockerfileに記述すれば、最初のログインから使えるようになる。
8については、Docker compose を利用すればできるようだけど、このページではホストと橋渡しディレクトリで渡すことにする。
また、9については、Dockerfileの中にCOPYでContainer内にコピーできるが、8と同様に橋渡しディレクトリで引き渡すことにする。
8、9ともに、ホストへsshができれば、実際にはそれほど困らないと思う。
以上の方針の下に、Dockerfileを作成する。
作成したDockerfile
本記事では、doc-al(docker-alpineの略のつもり)ディレクトリを新たに作成し、Dockerfileを置くことにする。
作成したDockerfileは以下のとおり。
FROM alpine:latest
RUN apk update && apk upgrade
RUN apk update && apk add sudo openssh
ARG USERNAME=hoge
ARG GROUPNAME=hoge
ARG UID=1000
ARG GID=1000
RUN addgroup -S -g "${GID}" "${USERNAME}" && adduser -u "${UID}" -G "${USERNAME}" -D "${USERNAME}" && echo "$USERNAME ALL=(ALL) NOPASSWD:ALL" >gt;>gt; /etc/sudoers
USER $USERNAME
WORKDIR /home/$USERNAME/
# add 2023-12-06
COPY --chown=$USERNAME:$GROUPNAME .profile /home/$USERNAME/
ADD --chown=$USERNAME:$GROUPNAME ./bin /opt/bin
RUN ln -s /opt/bin /home/$USERNAME/bin
ちょっと解説。
- FROM alpine:latest # 最新版のAlpine Linux を利用
- RUN アップデート、アップグレードで最新にしてから、opensshとsudoをインストール
- ARG hogeさんのUIDやGIDの設定
- RUN グループhogeの作成、ユーザhogeの追加、sudoersにhogeを追加。これで、初回起動時からsudoが使える。
- COPY コメント化してあるけど、doc-alディレクトリに.vimrc等を保存しておけば、Conteiner内の/home/hogeディレクトリにコピーすることができる。
- USERは、hoge ワークディレクトリは /home/hogeにする。
- /ect/profile を ホストの doc-al ディレクトリにコピーし、PATHとプロンプトを変更しておく。変更した .profile をコンテナのホームディレクトリにコピー
- ホストのdoc-al/binにコンテナ内で必要な実行ファイルを入れておき、コンテナのホームディレクトリにシンボリックリンクを貼る。
参考までに上記のDockerfileは、以下のようなディレクトリにおいてある。
binディレクトリには、テスト用にhello-alpineというbashスクリプトをおいてあるけど、コンテナ内で必要なスクリプトを保存しておくと便利。
doc-al
├── .profile
├── Dockerfile
└── bin
└── hello-alpine
2 directories, 3 files
また、/rtc/profileからコピーして作成した .profile は、PATHの追加とプロンプトの変更してあり、中身は以下のとおり。
# mod 2023-12-06 add /home/hoge/bin:
export PATH="/home/hoge/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
export PAGER=less
umask 022
# use nicer PS1 for bash and busybox ash
if [ -n "$BASH_VERSION" -o "$BB_ASH_VERSION" ]; then
#PS1='h:w$ '
PS1='u@h:w$ ' # mod 2023-12-06
# use nicer PS1 for zsh
elif [ -n "$ZSH_VERSION" ]; then
PS1='%m:%~%# '
# set up fallback default PS1
else
: "${HOSTNAME:=$(hostname)}"
PS1='${HOSTNAME%%.*}:$PWD'
[ "$(id -u)" -eq 0 ] && PS1="${PS1}# " || PS1="${PS1}$ "
fi
if [ -n "$BASH_VERSION" ] && [ "$BASH" != "/bin/sh" ]; then
# if we're bash (and not /bin/sh bash), also source the bashrc
# by default, bash sources the bashrc for non-login,
# and only /etc/profile on login (-l). so, make it do both on login.
# this ensures that login-shell bash (e.g. -bash or bash -l) still sources the
# system bashrc, which e.g. loads bash-completion
. /etc/bash/bashrc
fi
for script in /etc/profile.d/*.sh ; do
if [ -r "$script" ] ; then
. "$script"
fi
done
unset script
Dockerfileからimageの作成
上記でDockerfileを作成したので、imageを作成する。
ここでは、imageの名前を myalpine にする。
$ cd doc-al $ docker build -t myalpine .
エラーが無ければ、無事にimageが作成できる。
ちなみに、docker imagesで確認すると、まだわずか17.5MBでimageが作成できた。
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE myalpine latest f7c1a7752c5d 20 minutes ago 17.5MB
Alpine Linux すごいね。
作成したImageを使って、runコマンドでContainerを作成
実は、Dockerを使っていて、筆者が一番気を使うコマンドがrun。オプションをつけ忘れてContainerを使い込んで、 後で後悔するのがこのrunコマンド。
後ほど、救済策は紹介するけど、やはり最初から間違えないのに越したことはない。
ここではContainer名を myal 、コンテナのホスト名を test-al として、runコマンドでContainerを作成する。
docker run --name myal -v $PWD:/work -h test-al -itd myalpine
ここで、重要なのは -v(volume)オプションで、現在のディレクトリをContainerの /work ディレクトリにリンクする。これで、ホストとContainerのデータコピー等がスムーズにできるようになる。ちなみに、筆者は、doc-alを/workディレクトリに設定している。
ちょっと不便だけど、インストール後に実行することの5と6番目のことは、-vオプションで概ね解決できる。
なお、以下のように --add-host オプションをつけるとsshでのhostとの連携が良くなる。ここでは、hostをhost-pc アドレスは、192.168.1.xxxに設定。
docker run --name myal -v $PWD:/work --add-host=host-pc:192.168.1.xxx -h test-al -itd myalpine
上記のようにContainerを作成すれば、初回ログインからssh host-pcでssh接続できる。
なお、オプションの-itdは以下の意味。
- -it インターラクティブな操作
- -d Containerを作成したら、デタッチ
(2023-12-19追記)
上記では、--add-host オプションでホストのIPアドレスを追加したけど、カレントディレクトリにhostsファイルを作成しておき、-vオプションを使えば /etc/hosts に渡せることに気がついた。
docker run --name myal -v $PWD:/work -v ./hosts:/etc/hosts:ro -h test-al -itd myalpine
ちなみに、ホストのファイルなので、念のためにROオプションを付けてRead Onlyにしてある。
(追記終了)
runでContainerを作成して、本来なら Ctrl+p Ctrl+q でデタッチすべきところを、exitで終了するとContainerが終了した状態になってしまう。
これを避けるため、筆者は次節で説明するexecコマンドで、ログインするようにしている。
なお、runコマンドでexitしても、以下のとおり start コマンドで再び開始することができる。
docker start myal
execコマンドでログイン、作業の実行
前節で述べたとおり、原則 exec コマンドでログイン、通常の作業をするようにしている。
docker exec -it myal ash docker exec -it --user hoge myal ash --login
ちなみに、Alpine Linuxのデフォルトのshellはashとのこと。下の行のように、--loginオプションをつけるとホームディレクトリの.profileを実行してくれるよ。
ログイン後、現在のディレクトリを確認。
$ pwd /home/hoge
sudoが使えるか確認。
$ sudo apk update && apk upgrade
sshの確認。
$ ssh host-pc The authenticity of host '192.168.1.xxx (192.168.1.xxx)' can't be established. ED25519 key fingerprint is SHA256:2JQIaz3cqnqqMTKorWnEKpUvzxb7Ac9xApgyK9Wx2yI. This key is not known by any other names. Are you sure you want to continue connecting (yes/no/[fingerprint])?
Enterを押して、パスワードを入力すれば、無事にhost-pcにつながる。
$ ls /work Dockerfile
ホストの doc-al に保存したDockfileが表示される。
/workディレクトリは、ホストとのファイルの橋渡しに利用できる大切なディレクトリ。
以上までで、素のAlpine Linuxを利用する場合に比べて、だいぶ楽に使い始めることができると思う。
Bashスクリプトに
物覚えの悪い筆者は、Dockerのコマンドやオプションをすぐに忘れてしまう。(^_^;)
そこで、Dockerのイメージbuildからexecコマンドでログインするまでを、以下のBashスクリプトを書いて実行している。
#!/usr/bin/env bash
# docker exec file
# ver0.01 start 2023-12-03
# ver0.02 hostname user login 2023-12-06
# need Dockerfile
WORKDIR="/home/hoge/doc-al"
DOCNAME="myal"
DOCIMAGENAME="myalpine"
HNAME=$HOSTNAME"-al"
cd $WORKDIR
if [[ ! $(docker images | grep $DOCIMAGENAME) ]]; then
docker build -t $DOCIMAGENAME .
fi
result=$(docker ps -a | grep $DOCNAME)
#echo $result
if [[ $(echo $result | grep "Exited") ]]; then
docker start $DOCNAME >gt;/dev/null
elif [[ ! $result ]]; then
docker run --name $DOCNAME -v $PWD:/work -h $HNAME -itd $DOCIMAGENAME
#docker run --name $DOCNAME -v $PWD:/work --add-host=fam:192.168.1.XXX -h $HNAME -itd $DOCIMAGENAME
fi
docker exec -it --user $USER $DOCNAME ash --login
スクリプトの実行は、chmod +x doc-alで実行権を与えて、以下のとおり実行する。
$ doc-al
特に難しいことはしていないが、簡単に解説する。
- 初回実行時は、myalpine imageができていないので、buildしてimageを作る。
- また、runコマンドを実行して、myalと命名し、/workを橋渡しディレクトリにする。
- ホストの再起動などで、もしmyalがstop(Exit)しているようであれば、startコマンドで起動する。
- myalが起動していれば、execでログインする。
(2023-12-06追記)
上記のBashスクリプトを実行すると、プロンプトも以下のとおり変更され、PATHの追加やユーザのホームディレクトリにログインできるようになる。
hoge@fuga:~$ doc-al hoge@test-al:~$ pwd /home/hoge hoge@test-al:~$ echo $PATH /home/hoge/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
これまでの設定を行った後、Alpine Linuxのサイズを調べてみると以下のとおり。
$ docker ps -a -s CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES SIZE 9e004b908ef7 myalpine "/bin/sh" 2 hours ago Up 2 hours myal 1.88MB (virtual 19.4MB)
なんと、まだ20MBにも達していない。なんと優秀なディストリビューションだこと。
これまでのContainerやImageの削除
上記スクリプトを実行するにあたって、一度、ContainerやImageを削除して実行しないと、スクリプトの評価ができない。
ContainerやImageの削除は、以下のとおり。
$ docker stop myal $ docker rm myal $ docker rmi myalpine
実行後は、docker ps -a や docker imagesで確認を。
runのオプションを変更したい場合
長くContainerを使う場合は、runのオプションに気を使う。
万が一、オプションを変更したい場合は、以下のとおりimageをcommitした後、commitしたimageを用いてrunすることにより、オプションを変更することができる。
ただし、Dockerfile等を変更してimageを作り直すのではないので、あくまでも一時的な対策とのこと。
docker stop myal docker commit myal myalpine:v1 (Versionは自分で、つけない場合はlatest) docker run オプション --name myal-v2 -v $PWD:/work -itd myalpine
以上、参考までに。
おわりに
取り急ぎ、Dockerfieを作成して、Containerを新規に作成しても、ある程度使いやすいようにBashスクリプトを作成した。
今後は、Docker Composeを利用するとさらに便利になるとのことなので、Composeを勉強して、何かわかったら追記するつもり。