共用サーバーでDockerを使うときはUIDにご用心
共用サーバーでは開発・研究環境の干渉を避けるためにDockerを使って仮想環境を立てることが多いと思います。
この記事は、共用のサーバーでDockerを使うときはUIDに気を付けようという内容です。
なぜ気を付ける必要があるのか
ホスト上でtop
コマンドやps
コマンドでプロセスを見たとき、Dockerコンテナ内でプログラムを実行したユーザーとは異なるユーザーのプロセスとして表示される可能性があるためです。
例えば、以下のような現象が発生します。
- ユーザーAが共用サーバー上でDockerコンテナを立て、コンテナの中でしばらくの間GPUを占有して使用するプログラムを実行した
- ユーザーBが共用サーバー上でGPUを占有しているプロセスを起動したユーザーを確かめようとして
ps
コマンドを実行したところ、実効ユーザー(プログラムの実行者)がユーザーBとなっている
ユーザーBからすれば、実行した覚えのないプログラムが動いていることになりますから、訳がわからなくなってしまいます。
問題が起きる原因
原因は、top
コマンドやps
コマンドでホスト上でコンテナ内のプロセスを見たときに、UIDを基にユーザー名が表示されるためです。
例に挙げたシチュエーションでは以下のようなことが起こっていました。
- ユーザーA(UID:1001)がコンテナ内のユーザーA´(UID:1000)でGPUを使用するプログラムを実行する
- ユーザーB(UID:1000)がホスト上で
ps
コマンドを実行してGPUを占有しているプログラムの実効ユーザーを調べる - ホスト上では実効ユーザーのUIDがユーザーBのもの(UID:1000)であるため、実効ユーザーがユーザーBであると表示する
つまり、プログラムを実行したコンテナ内のユーザーのUIDとホスト上のユーザーのUIDが一致していたとき、ホスト上では後者のものとして表示されるのです。
この現象はDocker内でrootでないユーザーを作成した際に起きやすいです。
Dockerを使うとき、DockerFileなどでイメージを作る際やコンテナを立てた後にuseradd
コマンドでユーザーを作ることを考えます。このとき、何も指定していない場合は利用可能な次のUIDが割り当てられます。
使用されるUIDは/etc/login.defs
の中でUID_MIN
とUID_MAX
として定義されており、何もユーザーが存在しないときはUID_MIN
が割り当てられます。
このとき、UID_MIN
の値はホスト上でも使われていることが多く、上記の問題が発生します。
解決方法
簡単な解決方法
Dockerコンテナ内でユーザーを作るときは、ホスト上の自分のUIDと一致させるか、ホストで使用されていないUIDを使う
これが一番簡単な方法です。コンテナ内で使用しているユーザーのUIDをホスト上の自分のUIDと一致させると、ホスト上でtop
コマンドやps
コマンドを実行したときに実効ユーザーが正しく表示されます。
useradd
コマンドでは、オプションとして-u {UID}
を追加することでUIDを指定してユーザーを作成できます。
少し難易度の高い解決方法
Dockerデーモンの設定ファイルや起動時のコマンドでuserns-remap
を設定することで、UIDに名前空間を持たせることができるようです。
Isolate containers with a user namespace
Isolate containers within a user namespace
docs.docker.com

ただし、コンテナ内からホスト上のファイルを触るときなどの権限周りの設定が難しそうなので、Dockerの使い方によっては導入が厳しいかもしれません。
また、CUDAが正しく動かなくなるという問題もあるようです。GPUサーバーとして使っている場合、致命的です。
おわりに
ここで挙げた例は実体験がもとになっています(卒論のとき大変でした)。
Dockerは便利ですが、使い方をしっかりと理解しないとです。