授業で使うLinuxの環境は、これまでVirtualBoxをベースに構築していましたが、昨今の環境の変化に対応できてない感じもあるので、Docker上でそれができないかと検証していたら案外簡単に動く話だったので移行中です。 ということで今回はやってみたら案外楽だった作業のまとめ。

もともと授業用に仮想マシンを構築していましたが、Oracle VM VirtualBoxがM1/M2 macに対応準備中(現時点でPreview)ということや、なにより手持ちがIntelのみなので構築ができないということで(お金ほちい)ちょっと問題になっております。 そこで、

  • Intel/M1両対応のDocker(Desktop)
  • Ubuntu 22.04ベース
  • Systemdあり
  • sshあり

というイメージを作れればと思っていたのでした。

結局こうなりました。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 骨子のみです
FROM ubuntu:22.04
ARG USER=linux
ARG PASSWORD
ENV TZ Asia/Tokyo
ENV LC_ALL ja_JP.UTF-8
ENV LANG ${LC_ALL}
ARG DEBCONF_FRONTEND=noninteractive
ARG DEBIAN_FRONTEND=${DEBCONF_FRONTEND}
# タイムゾーン周辺
RUN apt-get update; \
    apt-get install -y tzdata
# ロケール設定
RUN apt-get update; \
    apt-get install -y locales; \
    locale-gen ja_JP.UTF-8
# 足下回り
RUN apt-get update; \
    apt-get install -y init openssh-server sudo
# ssh使えるようにポートを通知
EXPOSE 22
# ユーザー作成(linux)
RUN useradd -s /bin/bash ${USER}; usermod -m -a -G sudo ${USER}; \
    echo "${USER}:${PASSWORD}" | chpasswd; \
    cat /etc/passwd
# apt使用時のキャッシュデータクリア(Dockerビルド向け)を外す
RUN rm -f /etc/apt/apt.conf.d/docker-clean
ENTRYPOINT ["/sbin/init"]

やってることは

  • タイムゾーンとロケールを日本仕様にして置く
  • OpenSSHが使えるように調整
  • ユーザーを作成
    • パスワードをDockerfileに入れておくのはよろしくなさげなので--build-argで渡せ方式
  • Systemd(init)をいれてENTRYPOINTで呼び出す

Systemdが入るので、このイメージからのコンテナ生成では --privileged オプションが必要になります。 とはいえ実行対象がWindows/macOS上のDocker Desktopである以上VM内のSystemdを間借りする感じになるので影響はなさそうです。

おまけのテクニックとして、ホームディレクトリをボリュームに分けてコンテナリセット時でもホームを保持できるようにできないかということもありますが、 こういうとき向けの方法として、 pam_mkhomedir を使うというテクニックが有用となりますね。

1
2
3
4
5
# ユーザー作成(linux) → -m を外す
RUN useradd -s /bin/bash ${USER}; usermod -m -a -G sudo ${USER}; \
    echo "${USER}:${PASSWORD}" | chpasswd; \
    cat /etc/passwd
RUN echo 'session     required      pam_mkhomedir.so skel=/etc/skel umask=0022' >> /etc/pam.d/common-session

このpamモジュールを使うと、ユーザーがログインしたときにホームディレクトリがないときに自動的に作成してくれます。 これで起動時にボリュームで/homeを覆ったときでも大丈夫となります。

で、こうやって作ったイメージを起動してあげましょう。 繰り返し使うことを念頭に置いて、ここではcreate→start方式にしておくと良いでしょう。

1
2
$ docker volume create linux-home
$ docker container create --name=ubuntu -p 2022:22 -v linux-home:/home --privileged IMAGENAME

として準備して、

1
2
3
$ docker start ubuntu
# 5秒ぐらい落ち着いて待つ
$ ssh -p 2022 linux@127.0.0.1

これで普通にログインできます。 なお、docker execを使っても強引には入れますが、HOME変数がきちんと設定できないため接続後のディレクトリがちょっとアレになってしまいます。

終了は、コンテナをstopするだけです。

1
2
$ docker stop ubuntu
# 10秒ほどすると終了します

なお、コンテナ内(ssh中)にpoweroffしてもうまく行きます。 こうなるとほとんど普通のLinux鯖です。


ARM版(M1/M2)イメージを作るためには、buildkitを使います。

1
2
$ docker buildx create --use mybuilder
$ docker buildx build -t USER/IMAGE --push --platform linux/amd64,linux/arm64 .

という感じで作ってpushして配置しておけばOKです。