本稿の手順を実施することで
- インスタンスのブート時に Rootless モードの Docker エンジンサービスの開始と同時に、任意の compose.yml 構成を開始する。
が実現できる。
ベースとして AWS EC2 の Debian 12 インスタンスを使用する。
基本的に以下の公式ドキュメントに沿って実施する。
- AWS にルートユーザーを作成してクレカを登録する。
- AWS のルートユーザーで IAM アカウントを作成して PowerUserAccess を付与する。
- IAM アカウントで t2.micro インスタンスをストレージ 30GB の Debian 12 で作成する。
- インスタンス作成前に「ポート 22 をインバウンドで許可」とするセキュリティグループを作成しておく。インスタンス作成時にそのセキュリティグループを指定する。
- インスタンス作成前にキーペアを作成しておく。キーペア作成と同時に秘密鍵が自動的にダウンロードされる。インスタンス作成時にそのキーペアを指定する。
- インスタンス作成後に admin ユーザーで ssh ログインできることを確認する。
- Debian 12 に Docker エンジンをインストールする。 https://docs.docker.com/engine/install/debian/
- 公式ドキュメントの最後で
sudo docker run hello-world
を実行しているが、本稿の手順のこの時点で実行する必要は無い。
- 公式ドキュメントの最後で
Docker を Rootless モードで起動するようにする。 https://docs.docker.com/go/rootless/
まず最初に通常インストール状態で起動している Docker エンジンを停止する。
Docker Engine が普通にインストールされている状態で、AWS EC2 の Debian 12 であれば admin ユーザーで
sudo systemctl disable --now docker.service docker.socket
する。
Debian 12 であれば
sudo apt-get install uidmap
とする。
Ubuntu の場合も同じで良いはず。(未確認)
参照しているドキュメントには「dbus-user-session が入っていなかったらインストールする」とあるが、AWS EC2 の Debian 12 の場合は最初から入っている。
rootless ユーザーを作成する。
これはAWS EC2 の Debian 12 のデフォルトユーザー admin だと「パスワード無しで sudo」が実行できてしまうので、セキュリティリスク低減を目的として「sudo できないユーザー」を使いたいため。
admin ユーザーの状態で以下を実行する。
sudo useradd -m rootless # ホームディレクトリ有りでユーザーを新規に作成する
sudo chsh -s /bin/bash rootless # シェルをbashに変更する(必須ではない)
sudo passwd -l rootless # 新規で作成した rootless ユーザーのパスワードを無効化する(ログインは ssh のみ)
rootless ユーザーが作成できたら、admin ユーザーの状態で
sudo su - rootless
として rootless ユーザーになり、.ssh
ディレクトリを作り、公開鍵を記載した authorized_keys
ファイルを配置する。
対応する秘密鍵で rootless ユーザーに ssh ログインできるところまで確認する。
ssh で rootless ユーザーにログインして
dockerd-rootless-setuptool.sh check
dockerd-rootless-setuptool.sh install
を実行する。
公式ドキュメントに沿って Docker エンジンをインストールしていれば dockerd-rootless-setuptool.sh
はインストールされているはず。
ssh でログインしないと、dockerd-rootless-setuptool.sh
の内部で実行される systemctl --user show-environment
が正しく動作せず(環境変数 XDG_RUNTIME_DIR
が不足するため) dockerd-rootless-setuptool.sh
の実行がうまくいかない。
ssh でログイン(正確には ssh でなくともよいのでとにかく「ログイン」のプロセスを経てアクセス)すると、環境変数 XDG_RUNTIME_DIR
が自動的にセットされる。
最後に rootless ユーザーに ssh でログインした状態で
docker run hello-world
が成功すれば Rootless モードの導入は完了。
この状態では admin ユーザーや root ユーザーでは docker ps
などの docker コマンドが機能しない。これは正常な状態で、環境が壊れたわけではないので要注意。
ssh で rootless ユーザーにログインする。
/home/rootless/work/test などとしてディレクトリを作成し、/home/rootless/work/test/compose.yml を作成する。
version: "3"
services:
nginx:
image: nginx:latest
ports:
- 8080:80
AWS EC2 のセキュリティグループに、「ポート 8080 をインバウンドで許可」というルールを追加しておくのを忘れない。
この状態で
docker compose up -d
docker compose down
して NGINX のウェルカムページが表示されたり表示されなくなったりすることを確認する。
ここで ports: - 8080:80
としているポート番号には2種類の制約がある。
- Rootless モードの制約として 1024 以下のポート番号は使えない。(設定すれば使えるが本稿の範囲外)
ports: - 80:80
としていないのはこれが理由。
- 最近のブラウザの制約として 10080 などの特定のポート番号は「ブラウザが」表示を制限する。
ports: - 10080:80
など該当するポート番号を使用してしまうと「curl ではデータが正常に受信できるがブラウザだと表示できない」という状況になる。- AWS などであれば HTTPS を終端するロードバランサの配下で 10080 番ポートで HTTP を待ち受けるという構成が可能と思われる。(未確認)
全て rootless ユーザーでの操作となる。
/home/rootless/.config/systemd/user/sample-nginx.service を作成する。
[Unit]
Description=Sample NGINX
Requires=docker.service
After=docker.service
[Service]
ExecStart=/usr/bin/docker compose -f /home/rootless/work/test/compose.yml up
ExecStop=/usr/bin/docker compose -f /home/rootless/work/test/compose.yml down
Restart=always
[Install]
WantedBy=default.target
ひとまず最低限度これだけあれば動く。
systemctl の操作には --user オプションを付ける必要がある。
systemctl --user daemon-reload
systemctl --user status sample-nginx.service
systemctl --user start sample-nginx.service
systemctl --user stop sample-nginx.service
systemctl --user enable sample-nginx.service
start すると NGINX のウェルカムページが表示されるようになり、stop すると表示されなくなる。
enable にすると「再起動した EC2 インスタンスに ssh で rootless ユーザーとしてログイン」した時に Docker サービスと同時に sample-nginx.service も start するようになる。
逆に言うと、現時点の設定だけだと「ssh で rootless ユーザーとしてログイン」しないと、Docker サービスも sample-nginx.service も動かず、ブラウザでアクセスしても NGINX のウェルカムページは表示されない。
まとめると、ここまでの手順を実施できていれば、
- AWS EC2 インスタンスをブート(もしくは再起動)する。
- root, admin, rootless いずれのアカウントでもログインせずに、ブラウザでインスタンスのIPアドレス(とポート番号)にアクセスする。
- この時点では、ブラウザは NGINX のウェルカムページを表示できない。
- rootless ユーザーに ssh でログインしてから、ブラウザでインスタンスのIPアドレス(とポート番号)にアクセスする。
- ブラウザに NGINX のウェルカムページが表示される。
という動作になる。
rootless ユーザーで
loginctl enable-linger rootless
loginctl show-user rootless
を実行する。
show-user の実行結果は以下のようになる。Linger の項目が yes になっている。
UID=1001
GID=1001
Name=rootless
Timestamp=Mon 2023-08-28 08:18:24 JST
TimestampMonotonic=13729055
RuntimePath=/run/user/1001
Service=user@1001.service
Slice=user-1001.slice
Display=2
State=active
Sessions=2
IdleHint=no
IdleSinceHint=1693180144047894
IdleSinceHintMonotonic=1853696593
Linger=yes
インスタンスを再起動して、なにもせずに(root, admin, rootless でログインせずに)ブラウザで NGINX のウェルカムページが表示されることを確認する。
compose.yml の構成が起動してくるまで、インスタンス再起動を実行してから数分ほど待つ必要がある点に注意する。
また、
loginctl disable-linger rootless
を実行すると、インスタンス再起動だけでは NGINX のウェルカムページが表示できなくなり、「rootless ユーザーに ssh でログインするとウェルカムページが表示できるようになる」という状態に戻ることを確認する。
最後にもう一度
loginctl enable-linger rootless
しておく。
- Rootless モードの Docker をインストールする。
- 配置したサービスについて
systemctl --user enable 配置したサービス
を実行しておく。(1回だけ) loginctl enable-linger rootless
を実行しておく。(1回だけ)
以上の3つのポイントを押さえることで「ブート時に Rootless モードの Docker で compose.yml 構成を自動で開始する」が達成される。
rootless ユーザーの .profile に1行追加する。
rootless@ip-172-31-44-83:~$ id
uid=1001(rootless) gid=1001(rootless) groups=1001(rootless)
rootless@ip-172-31-44-83:~$ diff -u ~/.profile.2023-0829-2231 ~/.profile
--- /home/rootless/.profile.2023-0829-2231 2023-08-29 13:32:27.460746100 +0000
+++ /home/rootless/.profile 2023-08-29 13:27:01.819819290 +0000
@@ -25,3 +25,6 @@
if [ -d "$HOME/.local/bin" ] ; then
PATH="$HOME/.local/bin:$PATH"
fi
+
+export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock
+
VSCode の REMOTE-SSH で EC2 の rootless ユーザーに接続し、そこからコンテナにアタッチしにいくと Rootless モードで動いているコンテナが候補に表示される。