👏

Docker開発環境(1): ownerがrootになるのを回避する

2021/08/03に公開

最近では Docker でいろいろなソフトウェアをビルドするのもすっかりメジャーになりました。チュートリアルに従って Docker で何かをビルドしてみたことがある、という人も多いかと思います。

このときビルドするまでは良いのですが、ファイルを消そうと思ったら owner が root になっていて sudo しないと消せない、という経験をした方も多いと思います。試しにカレントディレクトリをコンテナにマップして、その中にファイルを作ってみましょう。

$ mkdir tmp && cd tmp
$ docker run --rm -it -v $PWD:/build -w /build ubuntu:20.04
root@8495f53aafff:/build# touch a
root@8495f53aafff:/build# ls -l
total 0
-rw-r--r-- 1 root root 0 Aug  3 03:31 a
root@8495f53aafff:/build# exit
$ ls -l
total 0
-rw-r--r-- 1 root root 0 Aug  3 12:31 a

コンテナで操作するユーザーは root であり、ファイルも root の所有になっています。

さて、ここで root ではなく自分の uid/gid でビルドできないものでしょうか。実際のところこれは docker run に -u オプションで uid/gid を指定すれば簡単にできます。同様にやってみます。

$ docker run --rm -it -u $(id -u):$(id -g) -v $PWD:/build -w /build ubuntu:20.04
groups: cannot find name for group ID 1000
I have no name!@1d9148fc3261:/build$ touch b
I have no name!@1d9148fc3261:/build$ ls -l
total 0
-rw-r--r-- 1 root root 0 Aug  3 03:31 a
-rw-r--r-- 1 1000 1000 0 Aug  3 03:33 b
I have no name!@1d9148fc3261:/build$ exit
exit
$ ls -l
total 0
-rw-r--r-- 1 root    root    0 Aug  3 12:31 a
-rw-r--r-- 1 <user>  <user>  0 Aug  3 12:33 b

コンテナで操作するユーザーはホスト環境の自分と同じ番号 uid/gid の一般ユーザーで、ファイルもそのユーザーの所有になっていますね。これで OK です…と言いたいところですが、たいていのケースではこれでも良いのですが、これでは困ることがあります。

  • コンテナ内に当該 uid/gid のユーザー・グループが存在しない。
  • (ほぼ同じ問題として)当該ユーザーのホームディレクトリが存在しない。

make して作れるシンプルなアプリケーションなら良いのですが、Yocto や AOSP などファームウェアのビルドシステムを使う場合、ビルドシステムが

  • ビルドしたユーザの名前を埋め込もうとする。
  • git の user.name, user.email が登録されていることを想定している。

という場合があり、このときコンテナ内に正しいユーザーエントリーがないとうまくビルドができません。

無理やりやるのであれば、/etc や /home をそのままコンテナに見せてやればやってやれないことはないです。

$ docker run --rm -it -u $(id -u):$(id -g) -v $PWD:/build \
    -v /etc:/etc -v /home:/home -w /build ubuntu:20.04
[<user>@335f500fc0ad build]$ ls -l
total 0
-rw-r--r-- 1 root    root    0 Aug  3 03:31 a
-rw-r--r-- 1 <user>  <user>  0 Aug  3 03:33 b

今度はコンテナの中からユーザー名が見えるようになりました。

ただ、さすがにこれはコンテナにホスト環境を見せ過ぎというか、コンテナで環境を分離したメリットを半分放棄しているような状態で、「正式なビルド手順」としてはかなり選びづらい方法です。

ここで改めて問題を再定義します。以下のような要件を満たす Docker コンテナを作ることを目標にしてみましょう。

  • コンテナ内でホストの自分の uid/gid でビルドができるようにする。
  • コンテナ内には当該 uid/gid を持つ正しいユーザーが存在する。
  • コンテナ内には予め用意されたホームディレクトリが存在する。
  • ホスト環境から不必要に多くのボリュームをマップしない(コンテナの独立性のため)。

このようなコンテナはどのようにすれば作れるでしょうか…。

次回はその具体的な方法について検討していきます。

Discussion