2017/01/03 15:15:03

Dockerコンテナ内のユーザとホストのユーザとの関係について

dokcer
目次(クリックするとジャンプします)
  • 1:Dockerのコンテナとユーザ
  • 2:Dockerのデフォルトの状態での挙動を確認
  • 2.1:コマンド(プロセス)はどうなる?
  • 2.2:ファイルの所有権はどうなる?
  • 3:ホストに存在するユーザと同じuid、gidのユーザーをコンテナ内に作ったらどうなる?
  • 3.1:コマンド(プロセス)はどうなる?
  • 3.2:ファイルの所有権はどうなる?
  • 4:ホストに存在しないuid、gidのユーザーはどうなる?
  • 4.1:コマンド(プロセス)はどうなる?
  • 4.2:ファイルの所有権はどうなる?
  • 5:まとめてみると

Dockerのコンテナとユーザ

すっかりDocker大好きっ子な@MINOです。

最近はプログラミングそのものの勉強よりもDockerの実験ばっかりしているような気がしています。

最近DockerコンテナでGUIアプリを起動させるという実験を行っていました。

それは開発環境を整えるための実験だったのですが、その際にコンテナ内で作ったユーザとホスト上のユーザがどのような関係になるのかがよくわかっていませんでした。

そのため今回はDockerコンテナの中で作ったユーザはホスト上ではどういった扱いになるのかを調べてみたいと思います。

Dockerのデフォルトの状態での挙動を確認

Dockerコンテナは素の状態であればユーザがrootのみの状態で起動します。

すごく簡単なdockerfileを書いてビルドしてみます。

FROM ubuntu:14.04
CMD ["/bin/bash"]
$ docker build -t your/image .

以下のようにコンテナを立ち上げます。

$ docker run -it --rm -v /host/directry/:/container/directry your/image
root@322487ddce7d:/#

ファイル作成のテストのためにボリュームを作っています。

vオプションでバインドしたホストのディレクトリは、ホストのユーザ「mino」が所有権を持ちパーミッションは755です。

minoはuid、gidともに1000です。

コマンド(プロセス)はどうなる?

さて、それではコンテナの内部で何らかのコマンドを実行してみます。

//コンテナ側
root@322487ddce7d:/# sleep 1000

ホスト側で別なターミナルかマルチプレクサのウインドウを開けて、今実行したsleepコマンドのプロセスを確認してみます。

//ホスト側
$ ps aux

~~~~~~
~~~~~~
root      7618  0.0  0.0   4348   668 pts/1    S+   20:03   0:00 sleep 1000
~~~~~~
~~~~~~

sleepコマンドはrootとして動作していることがわかります。

ファイルの所有権はどうなる?

またコンテナの中でなにかファイルを作ってみます。

先程バインドしたボリュームに移動して適当なファイルを作ってみました。

//コンテナ側
root@322487ddce7d:/container/directry  echo root > root.txt

さてこちらもホスト側のlsコマンドでファイルの所有者を確かめてみます。

//ホスト側
$ ls -al

drwxr-xr-x 2 user user 4096 12月 22 20:24 .
drwxr-xr-x 6 user user 4096 12月 22 20:01 ..
-rw-r--r-- 1 root root   10 12月 22 20:24 root.txt

コンテナの中で作ったファイルはroot所有のファイルになっていますね。

当たり前ですが、このファイルはホスト側のroot権限がなければ(それかパーミッションを変えないと)編集することはできません。

このようにコンテナ内のrootで動かしたコマンドやプロセス、作ったファイルはホスト上のrootの権限となります。

もともとDockerコンテナがroot権限によって立ち上げられているので当たり前といえば当たり前なのかもしれません。

ホストに存在するユーザと同じuid、gidのユーザーをコンテナ内に作ったらどうなる?

それではコンテナ内でホストに存在する同uid同gidのユーザを作成してみたらどうでしょうか?

結論から言うとuidとgidが同じであればホスト上でも同じユーザーとしてみなされるようです。

例えば、ホスト側の作業ユーザが「mino」だとします。このminoのuidとgidはともに1000だとします。

(多くの場合最初に作った一般ユーザは1000になるかなと思います)

そこでコンテナ内でuidとgidがともに1000のユーザ「uso」を作ってみます。

FROM ubuntu:14.04                                                                                                                
RUN export uid=1000 gid=1000 && \
echo "uso:x:${uid}:${gid}:uso,,,::/bin/bash" >> /etc/passwd && \
echo "uso:x:${uid}:" >> /etc/group && \
USER uso
CMD ["/bin/bash"]

今度もファイル作成のテストのためにボリュームを作ります。

デフォルトの状態でテストした時と同じようにvオプションでバインドしたホストのディレクトリは、ホストのユーザ「mino」が所有権を持ちパーミッションは755です。

$ docker run -it --rm -v /host/directry/:/container/directry your/image
uso@322487ddce7d:/#

dockerfile内でユーザusoに切り替えているので、コンテナのユーザはusoの状態で起動します。

コマンド(プロセス)はどうなる?

そして先程と同じようにsleepを動かしてみます。

//コンテナ側
uso@322487ddce7d:/# sleep 1000

ホスト側で別なターミナルかマルチプレクサのウインドウを開けてプロセスを確認してみます。

//ホスト側
$ ps aux
~~~~~
~~~~~
mino     10280  0.0  0.0   4348   704 pts/3    S+   20:50   0:00 sleep 1000
~~~~~
~~~~~

sleep 1000はminoの権限で動いていますね。念のためuidも確認してみます。

//ホスト側
$ ps alx
~~~~~
~~~~~
0  1000 10280 10260  20   0   4348   704 hrtime S+   pts/3      0:00 sleep 1000
~~~~~
~~~~~

uidが1000になっていることがわかります。

ファイルの所有権はどうなる?

またコンテナの中でなにかファイルを作ってみます。

先程バインドしたボリュームに移動して適当なファイルを作ってみました。

//コンテナ側
uso@322487ddce7d:/container/directry  echo uso > uso.txt

さてこちらもホスト側のlsコマンドでファイルの所有者を確かめてみます。

//ホスト側
$ ls -al /host/directry/

drwxr-xr-x 2 user user 4096 12月 22 20:24 .
drwxr-xr-x 6 user user 4096 12月 22 20:01 ..
-rw-r--r-- 1 mino mino   10 12月 22 20:24 uso.txt

コンテナ内のユーザusoで作ったファイルはホスト側から確認するとホストのminoの所有になっていますね。

ホストに存在しないuid、gidのユーザーはどうなる?

別なuid、gidのユーザをコンテナ内に作ってみます。

ホスト側には存在しないuid、gidのユーザです。otherという名前にしてみました。

FROM ubuntu:14.04                                                                                                                
RUN export uid=1010 gid=1010 && \
echo "other:x:${uid}:${gid}:other,,,::/bin/bash" >> /etc/passwd && \
echo "other:x:${uid}:" >> /etc/group && \
USER other
CMD ["/bin/bash"]

今度もボリュームを作ります。vオプションでバインドしたホストのディレクトリは、ホストのユーザ「mino」が所有権を持ちパーミッションは755です。

$ docker run -it --rm -v /host/directry/:/container/directry your/image
other@f75b96dbd94e:/#

コマンド(プロセス)はどうなる?

同じようにsleepを動かしてみます。

other@f75b96dbd94e:/# sleep 1000

ホスト側で別なターミナルかマルチプレクサのウインドウを開けてプロセスを確認してみます。

$ ps aux
~~~~~
~~~~~
1010      5605  0.0  0.0   4348   696 pts/1    S+   11:30   0:00 sleep 100
~~~~~
~~~~~

ホスト側に1010というuid、gidのユーザはいないので、ユーザ名と対応しておらず、ユーザ名が表示されていません。

ファイルの所有権はどうなる?

コンテナ内でファイルを作ろうとしますが以下の様にPermission deniedがでてファイルが作れません。

other@f75b96dbd94e:/ubuntu$ echo other > other.txt
bash: other.txt: Permission denied

これはファイルを作る先のディレクトリはホストのユーザであるminoが所有しており、パーミッションが755ですので、書き込み権限が無いためです。

このようにホストに存在しないuid、gidのユーザは、ホスト上からみると「存在しない」ユーザになるので、ホスト側のディレクトリのパーミッションが777とかになっていないと、バインドしたホスト側のディレクトリに書き込みはできません。

まとめてみると

以上のテスト結果から考えると、

  • コンテナ内のrootはホストのrootと同一になる
  • コンテナ内のユーザがホストの一般ユーザとuid、gidが同一の場合、そのユーザはホスト側のユーザと同一になる
  • コンテナ内のユーザがホストにはuid、gidの場合、そのユーザはホストのどのユーザとも結びつかない

といったことになるかと思います。

Dockerを何らかの用途に汎用的につかうとなると、意外とコンテナの中のユーザとホストのユーザの関係が気になることがあります。

特に開発環境をDockerで構築するときはコンテナ内のrootが結構面倒なことになったりします。

コンテナ内で作ったファイルがroot権限になってしまうのは、ホスト側で扱うのが面倒になってしまいますからね。

今回は基本的なテストでしたが、次回はホストのユーザとコンテナ内のrootをどのようにマッピングするかを考えてみたいと思います。