Skip to content

Instantly share code, notes, and snippets.

@hytdsh
Last active August 29, 2023 13:37
Show Gist options
  • Save hytdsh/16134873a0603ef5c88f227a94b835e4 to your computer and use it in GitHub Desktop.
Save hytdsh/16134873a0603ef5c88f227a94b835e4 to your computer and use it in GitHub Desktop.
AWS で Docker を Rootless で動かしアプリを展開する

概要

本稿の手順を実施することで

  • インスタンスのブート時に Rootless モードの Docker エンジンサービスの開始と同時に、任意の compose.yml 構成を開始する。

が実現できる。

ベースとして AWS EC2 の Debian 12 インスタンスを使用する。

基本的に以下の公式ドキュメントに沿って実施する。

とりあえず Docker エンジンをインストールする

  1. AWS にルートユーザーを作成してクレカを登録する。
  2. AWS のルートユーザーで IAM アカウントを作成して PowerUserAccess を付与する。
  3. IAM アカウントで t2.micro インスタンスをストレージ 30GB の Debian 12 で作成する。
    • インスタンス作成前に「ポート 22 をインバウンドで許可」とするセキュリティグループを作成しておく。インスタンス作成時にそのセキュリティグループを指定する。
    • インスタンス作成前にキーペアを作成しておく。キーペア作成と同時に秘密鍵が自動的にダウンロードされる。インスタンス作成時にそのキーペアを指定する。
  4. インスタンス作成後に admin ユーザーで ssh ログインできることを確認する。
  5. Debian 12 に Docker エンジンをインストールする。 https://docs.docker.com/engine/install/debian/
    • 公式ドキュメントの最後で sudo docker run hello-world を実行しているが、本稿の手順のこの時点で実行する必要は無い。

Rootless モードをインストールする

Docker を Rootless モードで起動するようにする。 https://docs.docker.com/go/rootless/

通常インストールの Docker エンジンを停止する

まず最初に通常インストール状態で起動している 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 ユーザーを作成する

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 ログインできるところまで確認する。

Rootless モードのインストール

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 コマンドが機能しない。これは正常な状態で、環境が壊れたわけではないので要注意。

compose.yml によるサービスの起動

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 を待ち受けるという構成が可能と思われる。(未確認)

compose.yml の起動を systemd に登録する

全て 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 のウェルカムページは表示されない。

まとめると、ここまでの手順を実施できていれば、

  1. AWS EC2 インスタンスをブート(もしくは再起動)する。
  2. root, admin, rootless いずれのアカウントでもログインせずに、ブラウザでインスタンスのIPアドレス(とポート番号)にアクセスする。
    • この時点では、ブラウザは NGINX のウェルカムページを表示できない。
  3. rootless ユーザーに ssh でログインしてから、ブラウザでインスタンスのIPアドレス(とポート番号)にアクセスする。
    • ブラウザに NGINX のウェルカムページが表示される。

という動作になる。

インスタンスのブート時に compose.yml を起動する

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

しておく。

まとめ

  1. Rootless モードの Docker をインストールする。
  2. 配置したサービスについて systemctl --user enable 配置したサービス を実行しておく。(1回だけ)
  3. loginctl enable-linger rootless を実行しておく。(1回だけ)

以上の3つのポイントを押さえることで「ブート時に Rootless モードの Docker で compose.yml 構成を自動で開始する」が達成される。

おまけ: VSCodeでアタッチする

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 モードで動いているコンテナが候補に表示される。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment