Dockerでコンテナを起動するとき、rootユーザでプロセスを起動してしまうと危険です。
参考: Dockerコンテナを本番環境で使うためのセキュリティ設定 - Qiita
公開されているDockerイメージの多くは何もしなければrootで実行するようになっているので、実行ユーザを変更する設定が必要になります。
最も簡単で効果が高いのは、Dockerfile内でユーザを作成して実行ユーザに指定する方法です。
コンテナ起動時に docker run -u <uid>
でUIDを指定する方法や、KubernetesのSecurityContextを使う方法などもあります。
例えば、次のような感じになります。
FROM debian
RUN useradd docker
USER docker
CMD ["bash"]
これで bash
が docker
ユーザで実行されます。
これだけでもまあいいのですが、useradd
にはいろいろオプションがあり、どのオプションを指定すればいいのか考えてみました。
Dockerfileでよく指定されるオプションには次のようなものがあります。
-g
: name or ID of the primary group of the new account-l
: do not add the user to the lastlog and faillog databases-m
: create the user’s home directory-M
: do not create the user’s home directory-r
: create a system account-s
: login shell of the new account-u
: user ID of the new account-U
: create a group with the same name as the user
それぞれについてみていきます。
-g
はグループを指定します。グループのgidもuidと同じにしていたほうがわかりやすいので -g
で指定することになります。
-l
ですが、lastlogとfaillogはほぼ意味がないのでつけといて思います。
-m/-M
は、例えばそのユーザでシェルを起動して運用することが想定される場合はホームディレクトリは作成しておいた方が便利です。
-r
を指定するとシステムアカウントとしてユーザが作成されます。/etc/login.defs
に定義されているシステムアカウントの範囲でuidが設定されます。また、ホームディレクトリが作成されません。-u
でuidを指定し、ホームディレクトリについては -m/-M
で指定するのでこのオプションは不要です。
-s /bin/false
でリモートログインを禁止できます。/bin/false
や /sbin/nologin
が指定してあっても、docker exec -u <uid> sh
や sudo -u <user> sh
によってそのユーザでシェルを実行できます。防げない攻撃がないこともないのでセキュリティ向上のために指定しておいてもいいでしょう。
-u
で明示的にuidを設定できます。これを指定しない場合は自動で番号を割り振られます。コンテナ外でユーザを指定するときはuidが必要になったりするので、明示的に設定しておいたほうがいいです。
-U
でユーザと同じ名前のグループを作成しますが、gidがuidと同じになるとは限らないのでグループは-g
で指定した方がいいです。
つまり、次のようにユーザを作成するといいと思います。
RUN groupadd -g 61000 docker
RUN useradd -g 61000 -l -M -s /bin/false -u 61000 docker
ユーザでシェルを起動して運用が発生する場合1は、次のように-M
ではなく-m
を使ってホームディレクトリを作成した方が便利です。
RUN groupadd -g 61000 docker
RUN useradd -g 61000 -l -m -s /bin/false -u 61000 docker
uidが61000なのは、だいたい自動で生成されるuidが1000〜60000に設定されている2ので、その範囲から外しているからです。ちなみにGKEのホストVMは5000〜60000になっていて、uidを5000とかにするとGKEが作ったユーザとuidがかぶる可能性があります。