こんにちは、吉岡(@yoshiokatsuneo)です。
Dockerは、シンプルで使い易い軽量仮想環境という特徴を生かして急速に発展しており弊社でも利用しています。
しかし、独自の概念を持つことや、機能が次々追加されていることから、誤解を生じることもあります。
特にセキュリティについては感情的になりやすいので正確な情報を把握することが大切です。ここでは、Dockerコンテナのセキュリティについてよくある誤解と注意点を紹介します。
◆Dockerコンテナのセキュリティに関する誤解
コンテナを単に実行するだけで、ホストや他のコンテナがのっとられる
コンテナは隔離環境で実行されますので、単純に(オプションを明示せずに)一般的なコンテナを実行するだけで、ホストや他のコンテナがのっとられることは現状はありません(知られてはいません)。
ホストのディレクトリ・ファイルを共有すれば、ホストのファイルにアクセスできますが、 明示的に指定しない限り共有されません(-v オプションなど)。 ホストのファイルを共有すればホストにアクセスできますが、これは仮想マシン(VMware, VirtualBox)でも同じです。
外部からの接続についても、明示的にポート番号の共有を指定しない限り、外部から コンテナに接続することはできません(-p, -Pオプション)。
ただし、コンテナは仮想マシンと比べてもホストと密に連携していることから、仮想マシンと比べるとDockerやLinuxでコンテナに関する脆弱性や問題が見つかる可能性は比較的高いとは考えられます。脆弱性を利用する悪意のあるDockerイメージが作られる可能性を否定はできません。適時アップデートを行うとともに最新情報には注意しましょう。万一に備える意味では念のためセキュリティソフトの導入することも有効とは考えられます。
コンテナのrootユーザとホストのrootユーザを変える方法はない
以前は、コンテナとホストのユーザID空間は同じで変える方法はなく、コンテナとホストのrootユーザは同一ユーザでした。
Ver1.10ではユーザ名前空間(ネームスペース)が導入され、コンテナのrootユーザとホストのrootユーザを 別ユーザにすることが可能です。
コンテナからホストにアクセスできるコンテナは必要ない
コンテナの管理ツールを動かすコンテナでは、コンテナ操作のためDockerホストにアクセスする必要があります。例えば、Shipyardのようなコンテナ管理ツールや、nginx-proxyのようなコンテナの動作をフックするようなツールでは コンテナにアクセスする必要があります。
fork爆弾でホストが停止する
以前はDockerには、fork爆弾を直接的に防ぐ機能はありませんでした。
Docker 1.11以降では、"--pids-limit"オプションが導入され、fork爆弾を防止できます。
◆コンテナのセキュリティ上の注意点
Dockerを無闇に恐れる必要はありませんが、セキュリティ上注意する点もあります。
コンテナをサーバとして公開する場合
コンテナをインターネット上のサーバとして動かす場合、通常のサーバと同様レベルのセキュリティに関する注意が必要です。 必要なアクセス制御を行い、アプリケーションやサーバの脆弱性には注意しましょう。 コンテナ起動時は、ポート番号やホストのファイル・ディレクトリの公開についても最低限必要な範囲に限定しましょう。
信用できないDockerイメージや、動作が不明なDockerイメージをサーバとして実行することは避けましょう。
なお、Dockerでは、明示的に指定しない限り、外部から直接コンテナに接続はできません。また、仮想マシン上でDockerホストを動作させていれば、仮想マシンがインターネットに公開されていない限り、コンテナが公開されることもありません。 さらに、パソコン(Windows, Mac)上でDockerを動かしている場合、そのパソコンやネットワークのファイアウォールもありますので、明示的に許可しない限り外部から接続できることもありません。
Dockerコマンドのオプション(ファイル共有、ポート公開)
Dockerコマンドのオプションには注意しましょう。
特にファイル共有に関するオプション(-v)を使うと、コンテナからホストにアクセスできるようになるので注意します。docker.sockのようなソケットファイルの共有についても注意し、ファイル共有は最低限必要な範囲のみ行います。
コンテナのポート番号を公開する場合で、そのDockerホストがインターネットに公開されている場合、コンテナにはインターネットのどこからでもアクセスできる状態になり、適切にアクセス制御を行わないとコンテナへの侵入を許すことになります。コンテナのポート番号をインターネットに公開する場合は、適切にアクセス制御を行いましょう。
Dockerコンテナの信頼度が低い場合、不必要にファイルを公開したりポートを公開しないようにしましょう。明示的にネットワーク接続を無効(--net=none)にすることも検討しましょう。
不審なスクリプトの実行
Dockerに限らず、信用できないスクリプトを実行することは非常に危険ですので避けましょう。Dockerに侵入される可能性はもちろんですが、そのサーバのファイルをすべて削除される可能性や、ウィルス・ワーム・トロイの木馬など悪意のあるスクリプトの可能性すらあります。
そのスクリプトの提供サイトや情報が信頼できるか、スクリプトはHTTPSで提供されているか、また不明な場合は必要に応じてスクリプトの内容を確認しましょう。
不審なコンテナの実行
悪意のあるコンテナや問題のあるコンテナでは、インターネットに不必要にアクセスしたりCPU・メモリ等のリソースを不必要に消費する可能性もあります。
Docker Hubなど知名度のあるレジストリ、特にオフィシャルイメージに大きな問題がある可能性は比較的少ないとは考えられますが、不明なサイトで公開されている不明点が多いコンテナはリスクが高いと考えられます。
信用・リスクに応じてどのコンテナを使うか検討し、またコンテナ起動時にネットワークアクセスを無効にする、リソース制限を行うなどを含めて検討しましょう。
◆まとめ
Dockerはシンプルで使い易いツールですが、道具ですので使い勝手によって便利にも危険にもなります。 特にコンテナをサーバとしてインターネットに公開する場合は、通常のサーバと同等の注意が必要です。
Dockerは、自由に作って壊して試せることが大きな特徴です。信用できるDockerイメージを使い、コンテナをサーバとして公開しないようにすれば危険性は少ないです。 やみくもに怖がったりするのではなく、概念・動作・使い方を理解して使ってみましょう。
最後に手前味噌になりますがDockerに関する書籍『Docker実戦活用ガイド』も書きましたので、よろしければ手に取ってみてください。
paizaではITエンジニアとしてのスキルレベル測定(9言語に対応)や、プログラミング問題による学習コンテンツ(paiza Learning)を提供(こちらは21言語に対応)しています。テストの結果によりS,A,B,C,D,Eの6段階でランクが分かります。自分のプログラミングスキルを客観的に知りたいという方は是非チャレンジしてみてください。