Open5

rootless dockerでユーザ権限で安全にdockerを使う(Linuxへのインストールメモ)

oratakeoratake

なんでrootless

LinuxでDockerを使用する場合、基本的にはroot権限で使うことになる

こんなかんじ
$ sudo docker run hello-world

ただその場合Dockerで実行しているもの=rootで実行されるため、コンテナに変なものが入っているとリスクがでかい
なのでDockerをユーザ権限で実行することにより、ヤバいコンテナからサーバを守れる(というガバ理解)
詳しくはこのあたり
https://medium.com/nttlabs/rootless-docker-12decb900fb9

uname

Ubuntu 22.04 LTS

oratakeoratake

install

aptで入れると2015年とかのビルドが入ってくるので、docker大本営のリポジトリをaptに登録するのがよさそう
以下参考
https://self-development.info/ubuntu-22-04-ltsへの最新版dockerのインストール/
aptに登録しているので以降の更新は sudo apt update でまとめていけるようになる

名前空間

こちらを参考
https://zenn.dev/nemolize/articles/3cec197e5f5ec8

↑追加で
どうやらUbuntuでは最初から100000から0xFFFF個のuid,gidをとってるっぽかったので要らない説あった
/etc/subuid, /etc/subgid あたりlessして確認してみるとよいかもしれなかった。

特権ポート(~1024)

webの80とかメールの443とか含むよくあるポートは基本的に使えなくなっている
ので、使えるように設定
https://docs.docker.jp/engine/security/rootless.html#rootless-exposing-privileged-ports
上記はdockerの19.03とかで古い可能性がある
コマンドで $HOME/bin/rootlesskit のパス指定がされているが、このあたり which rootlesskit で正しいパスを入れておく必要がある
sysctl.dの設定は新規にファイルを作成。/etc/sysctl.d/99-docker-rootless.conf みたいに書いてdocker関係の設定としてやりました感出しておく

oratakeoratake

Permission関係

Laravel実行時になんかしらしくじっているので確認

プロジェクトのルートに permission_test/ ディレクトリを777で設置
sailのshellに入ってこの中に適当なtxtファイルをtouchしてみる

sail shell
sail@(コンテナハッシュ):/var/www/html$ ls -l
drwxrwxrwx  2 root root   4096 Oct 25 03:08 permission_test
sail@(コンテナハッシュ):/var/www/html$ touch permission_test/test.txt
sail@(コンテナハッシュ):/var/www/html$ ls -la permission_test/test.txt
-rw-r--r-- 1 sail sail 0 Oct 25 03:08 permission_test/test.txt
sail@(コンテナハッシュ):/var/www/html$ id
uid=1000(sail) gid=1000(sail) groups=1000(sail)

外からの見た目

$ id
uid=1000(oratake) gid=1000(oratake)
$ ls -l
drwxrwxrwx  2    - oratake oratake 2022-10-25 12:07 permission_test
$ ls -la permission_test
.rw-r--r-- 1 0 100999 100999 2022-10-25 12:08 test.txt

(母艦のlsは個人的にexaで設定を書き直しているので一部普通のlsと違うが、ユーザidグループidの並びは一緒)
母艦のuid1000のユーザで作成したものはコンテナ内ではrootとして見えている
コンテナ内でuid1000で作成したものは外からみると10万とかの下駄をはいている。
uidが1000なのが外では100999
単純に99999足されてると

おそらく解決案と思われるもの。以下2つで同様のことを言ってる気がする
https://tech-blog.rakus.co.jp/entry/20200826/docker
https://qiita.com/yohm/items/047b2e68d008ebb0f001

dockerのrootlessモードでの検証

https://qiita.com/yuyakato/items/b4ea7e123cd47b22b2c7
normalモードでの検証はあったが、rootlessモードでの検証はないので同様の検証をやってみる

# UID/GIDを指定せず、idコマンドを実行してUID/GIDを確認します。
# →UID/GIDは0:0です。
$ docker container run --tty --rm ubuntu:22.04 id
uid=0(root) gid=0(root) groups=0(root)

# UID/GIDを指定せず、touchコマンドで空ファイルを生成して、ファイルのUID/GIDを確認します。
# →ファイルのUID/GIDは0:0です。
$ docker container run --tty --rm --volume /$(pwd):/out ubuntu:22.04 /bin/bash -c "umask 0077 && touch /out/without_user && ls -ln /out/without_user"
-rw------- 1 0 0 0 Oct 25 04:44 /out/without_user

# UID/GIDとして1000:1000を指定し、idコマンドを実行してUID/GIDを確認します。
# →UID/GIDは1000:1000です。
$ docker container run --tty --user 1000:1000 ubuntu:22.04 id
uid=1000 gid=1000 groups=1000

# UID/GIDとして1000:1000を指定し、touchコマンドで空ファイルを生成して、ファイルのUID/GIDを確認します。
# →ファイルのUID/GIDは1000:1000です。
$ docker container run --tty --user 1000:1000 --volume /$(pwd):/out ubuntu:22.04 /bin/bash -c "umask 0077 && touch /out/with_user_1000 && ls -ln /out/with_user_1000"
-rw------- 1 1000 1000 0 Oct 25 05:33 /out/with_user_1000

# UID/GIDとして2000:2000を指定し、idコマンドを実行してUID/GIDを確認します。
# →UID/GIDは2000:2000です。
$ docker container run --tty --user 2000:2000 ubuntu:22.04 id
uid=2000 gid=2000 groups=2000

# UID/GIDとして2000:2000を指定し、touchコマンドで空ファイルを生成して、ファイルのUID/GIDを確認します。
# →ファイルのUID/GIDは2000:2000です。
$ docker container run --tty --user 2000:2000 --volume /$(pwd):/out ubuntu:22.04 /bin/bash -c "umask 0077 && touch /out/with_
user_2000 && ls -ln /out/with_user_2000"
-rw------- 1 2000 2000 0 Oct 25 05:37 /out/with_user_2000

# Dockerホスト側のファイルのUID/GIDを確認します。
# →UID/GIDはDockerコンテナ内と同一ではないです。
$ ls -la
.rw------- 1 0 oratake oratake 2022-10-25 13:44 without_user #コンテナ内でrootのものは外からは1000として見えている。
.rw------- 1 0 100999   100999   2022-10-25 14:33 with_user_1000 #コンテナ内1000が100999
.rw------- 1 0 101999   101999   2022-10-25 14:37 with_user_2000 # コンテナ内2000が101999

つまり、コンテナ内uid=0なら1000だが、コンテナ内uid=1だと100000になっていると思われる。

oratakeoratake

権限を力業で乗り切ってみる()

uidが100999になるならホストのユーザ(1000)が同じグループになればよいのでは...?

コンテナの中
# chown -R 1000:1000 ./

全部1000に書き換えても問題ないと(ガバ)判断。
あとはホスト側で100999と1000を同じグループにぶっこんでいく

ウォォォォ
$ sudo groupadd rootless-docker -g 100999
$ sudo gpasswd -a oratake rootless-docker
$ chmod -R a=rX,u+w,g+w ここにプロジェクトのルートパス #グループにwrite権限を付与していく

これで使えるかどうか確認中

追記: 同じことDocker公式に書いてあった
https://docs.docker.jp/desktop/install/linux-install.html#linux-install-file-sharing