web-dev-qa-db-ja.com

Dockerは仮想マシンとどう違うのですか?

DockerとフルVMの違いを理解するために、 Dockerのドキュメント を読み直してください。それほど重くならずに、どのようにして完全なファイルシステム、分離されたネットワーク環境などを提供することができますか?

一貫性のある運用環境に単純に展開するよりも、Dockerイメージにソフトウェアを展開すること(正しい用語であれば)が簡単なのはなぜですか?

3325
zslayton

Dockerはもともと LinuX Containers (LXC)を使用していましたが、後に runC (以前は libcontainer として知られていました)に切り替え、ホストと同じオペレーティングシステムで動作します。これにより、多くのホストオペレーティングシステムリソースを共有できます。また、階層化ファイルシステム( AuFS )を使用してネットワークを管理します。

AuFSは階層化されたファイルシステムなので、読み取り専用部分と書き込み部分をマージして組み合わせることができます。オペレーティングシステムの共通部分を読み取り専用にして(そしてすべてのコンテナー間で共有して)、書き込み用に各コンテナーに独自のマウントを与えることもできます。

1 GBのコンテナイメージがあるとしましょう。フルVMを使用する場合は、1 GB×必要な数のVMが必要です。 DockerとAuFSを使用すると、すべてのコンテナー間で1 GBの大部分を共有できます。また、1000個のコンテナーがある場合でも、コンテナーのOS用に1 GBを少し超えるスペースしかない可能性があります。 。

完全仮想化システムには、独自のリソースセットが割り当てられ、最小限の共有しか行われません。あなたはより多くの分離を得ます、しかしそれはずっと重いです(より多くのリソースを必要とします)。 Dockerを使用すると、分離が少なくなりますが、コンテナーは軽量になります(必要なリソースが少なくなります)。それで、あなたは簡単にホスト上で何千ものコンテナを走らせることができました、そしてそれはさえ点滅しません。 Xenでそれをやってみてください、そしてあなたが本当に大きいHostを持っていない限り、私はそれが可能だとは思わない。

完全仮想化システムは通常起動に数分かかりますが、Docker/LXC/runCコンテナには数秒、多くの場合1秒もかかりません。

仮想化システムの種類ごとに長所と短所があります。保証されたリソースで完全に分離したい場合は、完全なVMを使用します。プロセスを互いに分離して、適度なサイズのホスト上で大量のプロセスを実行したい場合は、Docker/LXC/runCが適しています。

詳細については、 この一連のブログ投稿 /を参照してください。/ LXCがどのように機能するかを説明するのに役立ちます。

一貫性のある運用環境に単純に展開するよりも、ソフトウェアをdockerイメージに展開するのが正しい理由である場合はなぜですか。

一貫した運用環境を展開することは、行われるよりも簡単です。 ChefPuppet のようなツールを使っていても、OSの更新やその他のものはホストと環境の間で変化します。

Dockerを使用すると、OSを共有イメージにスナップショットすることができ、他のDockerホストに簡単にデプロイできます。ローカルでは、dev、qa、prodなど:すべて同じイメージです。もちろん他のツールでも可能ですが、それほど簡単ではありません。

これはテストに最適です。データベースに接続する必要があるテストが何千もあり、それぞれのテストにデータベースの元のコピーが必要であり、データに変更を加えるとしましょう。これに対する古典的なアプローチは、カスタムコードまたは Flyway - のようなツールを使用して、テストのたびにデータベースをリセットすることです。これは非常に時間がかかり、テストを連続して実行する必要があります。ただし、Dockerを使用すると、データベースのイメージを作成し、テストごとに1つのインスタンスを実行し、それらがすべてデータベースの同じスナップショットに対して実行されることがわかっているため、すべてのテストを並行して実行できます。テストはDockerコンテナと並行して実行されているので、同じボックスで同時に実行することができ、非常に早く終了するはずです。フルVMでそれをやってみてください。

コメントから...

面白い!私はまだ「OSのスナップショット」という概念に混乱していると思います。 OSのイメージを作成せずに、どうやってそれをするのでしょうか。

さて、私が説明できるかどうか見てみましょう。あなたはベースイメージから始めて、そしてあなたの変更を加え、そしてdockerを使ってそれらの変更をコミットする、そしてそれはイメージを作成する。この画像はベースとの違いのみを含みます。あなたがあなたのイメージを実行したいとき、あなたもベースが必要です、そしてそれはレイヤードファイルシステムを使ってベースの上にあなたのイメージを重ねます:上で述べたように、DockerはAUFSを使います。 AUFSは異なるレイヤーを一緒にマージし、あなたが望むものを手に入れます。実行するだけです。あなたはより多くの画像(レイヤー)を追加し続けることができ、それは差分のみを保存し続けるでしょう。 Dockerは通常 レジストリ からの既製のイメージの上に構築されているので、自分でOS全体を「スナップショット」する必要はほとんどありません。

3145
Ken Cochrane

良い答えです。コンテナーとVMのイメージ表現を得るためには、以下のものを見てください。

enter image description here

出典

463
manu97

仮想化とコンテナが低レベルでどのように機能するかを理解することが役立つ場合があります。それは多くのことをクリアします。

注:以下では、説明を少し簡略化しています。詳細については、リファレンスを参照してください。

低レベルでの仮想化の仕組み

この場合、VM managerはCPUリング0(または新しいCPUの「ルートモード」)を引き継ぎ、ゲストOSによって行われたすべての特権呼び出しをインターセプトして、ゲストOSが独自のハードウェアを持っているように見せかけます。楽しい事実:1998年以前は、この種の傍受を行う方法がなかったため、x86アーキテクチャでこれを実現することは不可能と考えられていました。 VMWareの人々 最初の人 これを達成するためにゲストOSの特権呼び出しのためにメモリ内の実行可能バイトを書き換える考えがありました。

最終的な効果は、仮想化により、同じハードウェア上で2つの完全に異なるOSを実行できることです。各ゲストOSは、ブートストラップ、カーネルのロードなどのすべてのプロセスを実行します。たとえば、ゲストOSはホストOSまたは他のゲストに完全にアクセスできず、混乱を招くなど、非常に厳しいセキュリティを設定できます。

低レベルでのコンテナの動作は?

2006 あたり、Googleの従業員の一部を含む人々は、namespacesと呼ばれる新しいカーネルレベル機能を実装しました(ただし、アイデア long 以前 FreeBSDに存在 )。 OSの機能の1つは、ネットワークやディスクなどのグローバルリソースをプロセスに共有できるようにすることです。これらのグローバルリソースが名前空間でラップされ、同じ名前空間で実行されているプロセスにのみ表示されるとしたらどうでしょうか。ディスクのチャンクを取得して名前空間Xに入れると、名前空間Yで実行中のプロセスはそれを表示またはアクセスできなくなります。同様に、名前空間Xのプロセスは、名前空間Yに割り当てられたメモリ内の何かにアクセスできません。もちろん、Xのプロセスは名前空間Yのプロセスを参照したり、対話したりできません。これにより、グローバルリソースの一種の仮想化と分離が提供されます。これがdockerの仕組みです。各コンテナは独自のネームスペースで実行されますが、他のすべてのコンテナとまったく同じsameカーネルを使用します。カーネルがプロセスに割り当てられた名前空間を認識し、API呼び出し中にプロセスが独自の名前空間のリソースにのみアクセスできるようにするため、分離が発生します。

コンテナとVMの制限は今では明らかです。VMのようなコンテナでは完全に異なるOSを実行できません。ただし、同じカーネルを共有しているため、Linuxの異なるディストリビューションをcan実行できます。分離レベルはVMほど強力ではありません。実際、初期の実装では「ゲスト」コンテナがホストを引き継ぐ方法がありました。また、新しいコンテナをロードすると、OSの新しいコピー全体がVMのように起動しないことがわかります。すべてのコンテナ 同じカーネルを共有 。これが、コンテナが軽量である理由です。また、VMとは異なり、OSの新しいコピーを実行していないため、コンテナに大量のメモリを事前に割り当てる必要はありません。これにより、1つのOSで何千ものコンテナを実行しながらサンドボックス化できます。これは、独自のVMでOSの個別のコピーを実行している場合は実行できない場合があります。

427
Shital Shah

Ken Cochraneの答えが好きです。

しかし、ここでは詳しく説明しませんが、視点を追加したいと思います。私の意見では、Dockerはプロセス全体でも異なります。 VMとは対照的に、Dockerは(唯一の)ハードウェアの最適なリソース共有についてではなく、さらにパッケージングアプリケーションのための「システム」を提供します(マイクロサービスのセットとしては望ましいが必須ではありません)。

私にとっては、rpm、 Debian パッケージ、 Maven 、npm + Gitのような開発者向けツール、および Puppet 、VMware、Xenなどのopsツールの間のギャップに収まります。それ...

一貫性のある運用環境に単純に展開するよりも、ソフトウェアをdockerイメージに展開するのが正しい理由である場合はなぜですか。

あなたの質問は、一貫した本番環境を想定しています。 しかしそれをどのように一貫性を保つために? ある程度の量(> 10)のサーバーとアプリケーション、パイプラインの段階を検討します。

これを同期させるために、Puppet、 Chef 、または独自のプロビジョニングスクリプト、未発表のルール、および/または多数のドキュメントなどを使用し始めます。理論上、サーバーは無期限に実行でき、完全に一貫性を保ちます。最新の。実際には、サーバーの構成を完全に管理することはできません。そのため、構成のドリフト、および実行中のサーバーに対する予期しない変更にはかなりの余地があります。

したがって、これを回避するための既知のパターン、いわゆるimmutable serverがあります。しかし不変のサーバーパターンは愛されていませんでした。主にDocker以前に使用されていたVMの制限によるものです。アプリケーション内の一部のフィールドを変更するためだけに、数ギガバイトの大きな画像を処理し、それらの大きな画像を移動させるのは非常に面倒でした。わかりやすい...

Dockerエコシステムを使用すれば、「小さな変更」をギガバイト単位で移動する必要はなくなり(aufsとRegistryに感謝します)、実行時にアプリケーションをDockerコンテナーにパッケージ化してパフォーマンスを失うことを心配する必要はありません。あなたはその画像のバージョンについて心配する必要はありません。

そして最後に、あなたはあなたのLinuxラップトップ上でさえも複雑なプロダクション環境を再現することさえできるでしょう(あなたのケースでうまくいかなかったら私に電話しないでください;)

そしてもちろん、VMでDockerコンテナを起動することもできます(これは良い考えです)。サーバープロビジョニングをVMレベルで減らします。上記すべてをDockerで管理できます。

P.一方、DockerはLXCの代わりに独自の実装 "libcontainer"を使用しています。しかしLXCはまだ使用可能です。

312
aholbreich

Dockerは仮想化方法論ではありません。実際にはコンテナベースの仮想化またはオペレーティングシステムレベルの仮想化を実装する他のツールに依存しています。そのために、Dockerは当初LXCドライバを使用していましたが、libcontainerに移動しました。このlibcontainerは現在runcと名前が変更されています。 Dockerは主に、アプリケーションコンテナ内のアプリケーションの展開を自動化することに焦点を当てています。アプリケーションコンテナは単一のサービスをパッケージ化して実行するように設計されていますが、システムコンテナは仮想マシンのように複数のプロセスを実行するように設計されています。そのため、Dockerはコンテナー化システム上のコンテナー管理またはアプリケーション展開ツールと見なされています。

それが他の仮想化とどのように違うのかを知るために、仮想化とその種類について見ていきましょう。それでは、違いが何であるかを理解しやすくなります。

仮想化

その考えられた形では、それは論理的にメインフレームを分割して複数のアプリケーションが同時に実行できるようにする方法と考えられていました。しかし、企業やオープンソースコミュニティが何らかの方法で特権命令を処理する方法を提供し、単一のx86ベースのシステム上で複数のオペレーティングシステムを同時に実行できるようにすると、シナリオは劇的に変わりました。

ハイパーバイザー

ハイパーバイザーは、ゲスト仮想マシンが動作する仮想環境の作成を処理します。ゲストシステムを監視し、必要に応じてリソースがゲストに割り当てられるようにします。ハイパーバイザーは物理マシンと仮想マシンの間に位置し、仮想化サービスを仮想マシンに提供します。これを実現するために、仮想マシン上のゲストOSの操作を傍受し、ホストマシンのOS上での操作をエミュレートします。

主にクラウドを中心とする仮想化技術の急速な発展により、Xen、VMware Player、KVMなどのハイパーバイザーを利用して単一の物理サーバー上に複数の仮想サーバーを作成できるようになり、仮想化の使用がさらに促進されました。 Intel VTやAMD-Vなどのコモディティプロセッサへのハードウェアサポートの組み込み。

仮想化の種類

仮想化方法は、ハードウェアをゲストオペレーティングシステムに模倣し、ゲストオペレーティング環境をエミュレートする方法に基づいて分類できます。主に、3種類の仮想化があります。

  • エミュレーション
  • 準仮想化
  • コンテナベースの仮想化

エミュレーション

フル仮想化とも呼ばれるエミュレーションは、仮想マシンのOSカーネルを完全にソフトウェアで実行します。このタイプで使用されるハイパーバイザーは、タイプ2ハイパーバイザーと呼ばれています。ゲストOSのカーネルコードをソフトウェアの命令に変換する役割を果たすHostオペレーティングシステムの上にインストールされます。変換は完全にソフトウェアで行われ、ハードウェアの関与を​​必要としません。エミュレーションは、エミュレートされている環境をサポートする、変更されていないオペレーティングシステムを実行することを可能にします。このタイプの仮想化のマイナス面は、他のタイプの仮想化と比較してパフォーマンスの低下につながる追加のシステムリソースオーバーヘッドです。

Emulation

このカテゴリの例には、VMware Player、VirtualBox、QEMU、Bochs、Parallelsなどがあります。

準仮想化

準仮想化は、タイプ1ハイパーバイザーとも呼ばれ、ハードウェア、つまり「ベアメタル」上で直接実行され、その上で実行されている仮想マシンに仮想化サービスを直接提供します。オペレーティングシステム、仮想化ハードウェア、および実際のハードウェアが協調して最適なパフォーマンスを達成するのに役立ちます。これらのハイパーバイザーは通常、設置面積がかなり小さく、それ自体では大規模なリソースを必要としません。

このカテゴリの例には、Xen、KVMなどがあります。

Paravirtualization

コンテナベースの仮想化

オペレーティングシステムレベルの仮想化とも呼ばれるコンテナベースの仮想化は、単一のオペレーティングシステムカーネル内で複数の独立した実行を可能にします。それは可能な限り最高のパフォーマンスと密度を持ち、動的なリソース管理を特徴としています。このタイプの仮想化によって提供される分離仮想実行環境はコンテナーと呼ばれ、トレースされたプロセスのグループと見なすことができます。

Container-based virtualization

コンテナーの概念は、Linuxカーネルバージョン2.6.24に追加された名前空間機能によって可能になりました。コンテナはそのIDをすべてのプロセスに追加し、新しいアクセス制御チェックをすべてのシステムコールに追加します。これはclone()システムコールによってアクセスされ、以前にグローバルだった名前空間の別々のインスタンスを作成することができます。

名前空間はさまざまな方法で使用できますが、最も一般的な方法は、コンテナの外側にあるオブジェクトに対する可視性やアクセスがない独立したコンテナを作成することです。コンテナ内で実行されているプロセスは通常のLinuxシステムで実行されているように見えますが、他の種類のオブジェクトと同じように、他の名前空間にあるプロセスと基盤となるカーネルを共有しています。たとえば、ネームスペースを使用する場合、コンテナ内のrootユーザはコンテナ外のrootとして扱われず、セキュリティが強化されます。

コンテナーベースの仮想化を可能にする次の主要コンポーネントであるLinux制御グループ(cgroups)サブシステムは、プロセスをグループ化し、それらの総リソース消費量を管理するために使用されます。一般的に、コンテナーのメモリーとCPUの消費量を制限するために使用されます。コンテナー化されたLinuxシステムには1つのカーネルしかなく、カーネルはコンテナーに対して完全な可視性を持っているため、リソースの割り当てとスケジューリングは1レベルしかありません。

LXC、LXD、systemd-nspawn、lmctfy、Warden、Linux-VServer、OpenVZ、Dockerなどを含むいくつかの管理ツールがLinuxコンテナ用に利用可能です。

コンテナと仮想マシン

仮想マシンとは異なり、コンテナはオペレーティングシステムのカーネルを起動する必要がないため、1秒以内にコンテナを作成できます。この機能により、コンテナベースの仮想化は他の仮想化アプローチよりも独自かつ望ましいものになります。

コンテナベースの仮想化はホストマシンにほとんどまたはまったくオーバーヘッドを追加しないので、コンテナベースの仮想化はネイティブに近いパフォーマンスを持ちます。

コンテナベースの仮想化では、他の仮想化とは異なり、追加のソフトウェアは必要ありません。

ホストマシン上のすべてのコンテナは、ホストマシンのスケジューラを共有して余分なリソースを節約します。

コンテナー状態(DockerまたはLXCイメージ)は、仮想マシンイメージに比べてサイズが小さいため、コンテナーイメージを配布するのは簡単です。

コンテナー内のリソース管理は、cgroupを介して行われます。 Cgroupsはコンテナがそれらに割り当てられた以上のリソースを消費することを許可しません。ただし、現時点では、ホストマシンのすべてのリソースは仮想マシンに表示されていますが、使用することはできません。これはコンテナとホストマシン上でtopまたはhtopを同時に実行することで実現できます。すべての環境での出力は同じように見えます。

更新:

DockerはLinux以外のシステムでどのようにコンテナーを実行しますか?

Linuxカーネルで利用可能な機能のためにコンテナが可能であるならば、明白な問題はどのように非Linuxシステムがコンテナを実行するかということです。 Docker for MacとWindowsはどちらもLinux VMを使用してコンテナーを実行します。 Virtual Box VMでコンテナーを実行するために使用されていたDocker Toolbox。しかし、最新のDockerは、WindowsではHyper-V、MacではHypervisor.frameworkを使用しています。

それでは、Docker for Macでコンテナーを実行する方法について詳しく説明しましょう。

Docker for Macはハイパーバイザー機能をエミュレートするために https://github.com/moby/hyperkit を使用し、Hyperkitはそのコアでhypervisor.frameworkを使用します。 Hypervisor.frameworkは、Macのネイティブハイパーバイザーソリューションです。 HyperkitはまたネームスペースネットワークおよびファイルシステムにそれぞれVPNKitおよびDataKitを使用します。

DockerがMacで実行するLinux VMは読み取り専用です。しかし、あなたはそれを実行することによってそれにぶつかることができます:

screen ~/Library/Containers/com.docker.docker/Data/vms/0/tty

これで、このVMのカーネルバージョンを確認することさえできます。

# uname -a Linux linuxkit-025000000001 4.9.93-linuxkit-aufs #1 SMP Wed Jun 6 16:86_64 Linux

すべてのコンテナはこのVM内で動作します。

Hypervisor.frameworkにはいくつかの制限があります。そのため、DockerはMacのdocker0ネットワークインタフェースを公開しません。だから、あなたはホストからコンテナにアクセスすることはできません。現在のところ、docker0はVM内でのみ利用可能です。

Hyper-vはWindowsのネイティブハイパーバイザーです。また、Windows 10の機能を利用してLinuxシステムをネイティブに実行しようとしています。

187
Ashish Bista

この記事を通して、VMとLXCの間にいくつかの違いを書きます。まずそれらを定義しましょう。

_ vm _

仮想マシンは物理的なコンピューティング環境をエミュレートしますが、CPU、メモリ、ハードディスク、ネットワーク、およびその他のハードウェアリソースに対する要求は、これらの要求を基盤となる物理ハードウェアに変換する仮想化レイヤによって管理されます。

このコンテキストでは、VMはゲストとして呼び出され、その実行環境はホストと呼ばれます。

_ lxc _ s:

Linuxコンテナ(LXC)は、1つの制御ホスト(LXCホスト)上で複数の独立したLinuxコンテナを実行することを可能にするオペレーティングシステムレベルの機能です。 Linuxコンテナは、ハイパーバイザを必要としないため、VMの軽量な代替品として機能します。 Virtualbox、KVM、Xenなど.

あなたがAlan(Zach Galifianakis - the Hangover series)に薬を飲まれて昨年ラスベガスに行ったことがない限り、あなたはLinuxコンテナー技術への多大な関心の高さに気付くでしょう。ここ数カ月の間に世界中で話題を呼んだプロジェクトは - クラウドコンピューティング環境はより低いオーバーヘッドと潜在的により良いパフォーマンスのために仮想マシン(VM)を放棄してコンテナに置き換えるべきだといういくつかの反響の意見をもたらします。

しかし、大きな問題は、それが実行可能かどうか、それは賢明かどうかということです。

a。 LXCは、Linuxのインスタンスを対象としています。それはLinuxの異なるフレーバーかもしれません(例えばCentOSホスト上のUbuntuコンテナーですが、それでもLinuxです)。同様に、私たちがかなり広い範囲を持っていてVMを見ると、WindowsベースのコンテナーはWindowsのインスタンスにスコープされます。ハイパーバイザーあなたはオペレーティングシステムのLinuxやWindowsに限定されていません。

b。 LXCはオーバーヘッドが少なく、VMと比較してパフォーマンスが優れています。ツールLXCテクノロジの肩の上に構築されたDockerは、開発者にアプリケーションを実行するためのプラットフォームを提供すると同時に、運用サーバーやデータセンターに同じコンテナを展開できるようにするツールを運用担当者に与えました。アプリケーションを実行している開発者、アプリケーションの起動とテスト、およびそのアプリケーションをデプロイしている運用担当者の間の経験をシームレスにしようとします。DevOpsの目的はこれらのサイロを打破することです。

そのため、クラウドインフラストラクチャプロバイダーは、それぞれ特定のワークロードとシナリオを処理するのに適しているため、VMとLXCの適切な使用を推奨することが最善のアプローチです。

VMを放棄することは今のところ実用的ではありません。そのため、VMとLXCにはそれぞれ独自の存在と重要性があります。

134
Pankaj Arora

ここでの回答の大部分は仮想マシンに関するものです。ここ2年間でDockerを使用してきた私にとって最も役に立ったこの質問に対するワンライナーの回答をお送りします。それはこれです:

Dockerはプロセスを実行するための単なる空想的な方法であり、仮想マシンではありません。

それでは、その意味についてもう少し詳しく説明しましょう。仮想マシンは彼ら自身の獣です。仮想マシンとは何かを説明するよりも、 Docker が何を意味するのかを説明することをお勧めします。特に、ここでは「仮想マシン」と言ったときに誰かが何を意味するのかを正確に説明している多くの良い答えがあります。そう...

Dockerコンテナーは、残りのプロセスからホストシステムのカーネル内で cgroups を使用してコンパートメント化された単なるプロセス(およびその子プロセス)です。ホスト上でps auxを実行することで、実際にあなたのDockerコンテナプロセスを見ることができます。たとえば、「コンテナ内で」Apache2を開始することは、ホスト上の特別なプロセスとしてApache2を開始することです。それはちょうどマシン上の他のプロセスからコンパートメント化されています。コンテナはコンテナ化されたプロセスの有効期間外には存在しないことに注意することが重要です。あなたのプロセスが死ぬとき、あなたのコンテナは死にます。これは、Dockerがコンテナ内のpid 1をアプリケーションで置き換えるためです(pid 1は通常initシステムです)。 pid 1に関する最後のポイントは非常に重要です。

これらの各コンテナプロセスが使用するファイルシステムに関しては、Dockerは UnionFS - Backedイメージを使用します。これは、docker pull ubuntuを実行するときにダウンロードしているものです。各「画像」は、単なる一連のレイヤーと関連するメタデータです。ここでは、階層化の概念が非常に重要です。各層は、その下の層からの単なる変更点です。たとえば、Dockerコンテナの構築中にDockerファイル内のファイルを削除すると、実際には最後のレイヤーの上に「このファイルは削除されました」というレイヤーが作成されるだけです。ちなみに、これがあなたがあなたのファイルシステムから大きなファイルを削除することができる理由です、しかしイメージはまだ同じ量のディスクスペースを占めます。現在のファイルの下のレイヤーに、ファイルはまだあります。レイヤー自体は単なるファイルのtarballです。これをdocker save --output /tmp/ubuntu.tar ubuntuそして次にcd /tmp && tar xvf ubuntu.tarでテストすることができます。それからあなたは周りを見てみることができます。長いハッシュのように見えるこれらすべてのディレクトリは、実際には個々のレイヤーです。各ファイルには、その特定の層に関する情報を含むファイル(layer.tar)とメタデータ(json)が含まれています。これらの層は、元の状態の「上に」層として保存されているファイルシステムへの変更を記述しているだけです。 「現在の」データを読むとき、ファイルシステムはあたかもそれが変更の最上位層だけを見ているかのようにデータを読む。ファイルシステムは最上位のレイヤのみを見ているため、ファイルが「前の」レイヤに存在していても削除されているように見えます。たとえ各コンテナの最上位レイヤのファイルシステムに大きな変更があったとしても、これは全く異なるコンテナがそれらのファイルシステムレイヤを共有することを可能にします。コンテナがそれらのベースイメージレイヤを共有するとき、これはあなたにディスクスペースのトンを節約することができます。ただし、ホストシステムからディレクトリやファイルをボリューム経由でコンテナにマウントすると、それらのボリュームはUnionFSを「バイパス」するため、変更はレイヤーに保存されません。

Dockerのネットワーキングは、イーサネットブリッジ(ホスト上ではdocker0と呼ばれます)、およびホスト上のすべてのコンテナー用の仮想インターフェースを使用して実現されます。コンテナ間で通信するための仮想サブネットをdocker0に作成します。ここには、あなたのコンテナ用のカスタムサブネットを作成することや、あなたのコンテナが直接アクセスするためにあなたのホストのネットワーキングスタックを "共有する"機能を含む、ネットワーク化のための多くのオプションがあります。

Dockerは非常に速く動いています。その ドキュメンテーション は私が今まで見た中で最高のドキュメンテーションの一部です。それは一般的によく書かれ、簡潔でそして正確です。私はあなたがより多くの情報のために利用可能なドキュメンテーションをチェックして、あなたがオンラインで読む他の何よりもそのドキュメントを信頼することを勧めます。具体的な質問がある場合は、Freenode IRCに#dockerで参加してそこで質問することを強くお勧めします(Freenodeの webchat を使用することもできます)。

116
L0j1k

Dockerはアプリケーションをそのすべての依存関係とともにカプセル化します。

バーチャライザは、ベアメタルマシン上で通常実行できる任意のアプリケーションを実行できるOSをカプセル化します。

75

両者は非常に異なります。 Dockerは軽量でLXC/libcontainer(カーネルの名前空間とcgroupに依存します)を使用しており、ハイパーバイザー、KVMなどのマシン/ハードウェアエミュレーションはありません。重いXen。

DockerとLXCは、サンドボックス化、コンテナ化、およびリソース分離のためのものです。 IPC、NS(mount)、ネットワーク、PID、UTSなどの名前空間を提供するホストOS(現在はLinuxカーネルのみ)のクローンAPIを使用します。

メモリ、I/O、CPUなどはどうですか。これはcgroupsを使って制御され、そこで特定のリソース(CPU、メモリなど)の仕様/制限を持つグループを作成し、そこにあなたのプロセスを入れることができます。 LXCの上に、Dockerはストレージバックエンド( http://www.projectatomic.io/docs/filesystems/ )を提供します。例えば、異なるマウント名前空間の間でレイヤーを追加したり共有したりできる共用体マウントファイルシステムです。

これは、基本イメージが通常読み取り専用で、コンテナーがレイヤー内の何かを変更した場合にのみ、読み書きパーティションに書き込みを行うという強力な機能です(別名コピーオンライト)。また、レジストリの作成や画像のバージョン管理など、他の多くのラッパーも提供しています。

通常のLXCでは、いくつかのrootfsを使用するか、またはrootfsを共有するときに共有する必要があります。変更は他のコンテナに反映されます。これらの追加機能の多くが原因で、DockerはLXCよりも人気があります。 LXCは、ネットワークやUIなどの外部エンティティに公開されているプロセスの周囲にセキュリティを実装するための組み込み環境で人気があります。 Dockerは、一貫した運用環境が期待されるクラウドマルチテナンシー環境で人気があります。

通常のVM(VirtualBoxやVMwareなど)はハイパーバイザーを使用します。関連技術には、最初のOS(ホストOS、またはゲストOS 0)の最初の層になる専用ファームウェア、またはホストOS上で実行され、CPU、USB /アクセサリ、メモリ、ネットワークなどのハードウェアエミュレーションをゲストOSに提供します。 VMは依然として(2015年現在)高セキュリティのマルチテナント環境で人気があります。

Docker/LXCは、ほとんどの安価なハードウェア上で実行できます(新しいカーネルがあれば1 GB未満のメモリでも問題ありません)。通常のV​​Mでは、2 GB以上のメモリを必要とします。 。ただし、ホストOS上のDockerサポートは、WindowsなどのOS(2014年11月現在)では利用できません。Windows、Linux、およびMac上ではVMの種類を実行できます。

これはdocker/rightscaleからの写真です: Here is a pic from rightscale

56
resultsway

1.軽量

これは多くの港湾労働者の学習者にとっておそらく最初の印象です。

まず、dockerイメージは通常VMイメージよりも小さいため、ビルド、コピー、共有が簡単になります。

第二に、Dockerコンテナは数ミリ秒で起動しますが、VMは数秒で起動します。

2.階層化ファイルシステム

これはDockerのもう一つの重要な機能です。画像にはレイヤがあり、別の画像でレイヤを共有できるため、さらにスペースを節約して構築を高速化できます。

すべてのコンテナがそのベースイメージとしてUbuntuを使用している場合、すべてのイメージが独自のファイルシステムを持っているわけではなく、同じアンダーラインのubuntuファイルを共有しており、独自のアプリケーションデータが異なるだけです。

3.共有OSカーネル

コンテナをプロセスと考えてください。

ホスト上で実行されているすべてのコンテナは、実際には異なるファイルシステムを持つ一連のプロセスです。それらは同じOSカーネルを共有し、システムライブラリと依存関係をカプセル化するだけです。

これはほとんどの場合に適しています(余分なOSカーネルが維持することはありません)が、コンテナー間で厳密な分離が必要な場合は問題になる可能性があります。

なぜそれが重要なのですか?

これらはすべて、革命ではなく改善のように見えます。さて、 定量的蓄積は定性的変換をもたらします

アプリケーションの配置について考えます。新しいソフトウェア(サービス)をデプロイする場合、またはアップグレードする場合は、新しいVMを作成するのではなく、構成ファイルとプロセスを変更することをお勧めします。サービスを更新してVMを作成し、それをテスト(DevとQA間で共有)し、本番環境にデプロイするには数時間、さらには数日かかるためです。何か問題が発生した場合は、もう一度やり直す必要があり、さらに時間がかかります。だから、新しいソフトウェアをインストールするために構成管理ツール(puppet、saltstack、chefなど)を使って、新しいファイルをダウンロードするのが好ましい。

Dockerになると、古いものを置き換えるために新しく作成されたdockerコンテナを使用することは不可能です。メンテナンスははるかに簡単です!新しいイメージを作成し、それをQAと共有し、テストし、展開するだけで数分(すべてが自動化されている場合)、最悪の場合数時間かかります。これは 不変インフラストラクチャと呼ばれます :ソフトウェアを保守(アップグレード)しないで、代わりに新しいソフトウェアを作成してください。

サービスの提供方法が変わります。アプリケーションが欲しいのですが、VMをメンテナンスする必要があります(これは面倒で、私たちのアプリケーションとはほとんど関係ありません)。 Dockerを使うとアプリケーションに集中でき、すべてがスムーズになります。

29
cizixs

基本的にコンテナであるDockerはOS virtualizationをサポートします。つまり、アプリケーションはOSの完全なインスタンスを持っていると感じますが、VMはハードウェア仮想化をサポートします。あなたはそれがあなたがどんなOSでも起動できる物理的なマシンであるように感じます。

Dockerでは、実行中のコンテナーはホストOSカーネルを共有しますが、VMではそれらは独自のOSファイルを持ちます。アプリケーションを開発する環境(OS)は、「テスト」や「本番」など、さまざまなサービス環境にアプリケーションをデプロイするときと同じになります。

たとえば、ポート4000で動作するWebサーバを開発している場合、それを「テスト」環境にデプロイすると、そのポートはすでに他のプログラムによって使用されているので動作しなくなります。コンテナにはレイヤがあります。 OSに加えたすべての変更は1つ以上のレイヤーに保存され、それらのレイヤーはイメージの一部になるため、イメージが移動する場所には依存関係も存在します。

以下の例では、ホストマシンに3つのVMがあります。 VM内のアプリケーションを完全に分離できるようにするために、それぞれが独自のOSファイル、ライブラリ、およびアプリケーションコードのコピーを、完全なメモリ内のOSインスタンスと共に持っています。 Without Containers 下の図はコンテナを使用した同じシナリオを示しています。ここでは、コンテナは単にカーネルやライブラリを含むホストオペレーティングシステムを共有するため、OSの起動、ライブラリのロード、またはこれらのファイルのためのプライベートメモリのコストを支払う必要はありません。それらが占める唯一の増分スペースは、アプリケーションがコンテナー内で稼働するために必要なメモリーおよびディスク・スペースです。アプリケーションの環境は専用のOSのように感じますが、アプリケーションは専用のホストに配置するのと同じようにデプロイします。コンテナ化されたアプリケーションは数秒で起動し、VMの場合よりも多くのアプリケーションのインスタンスがマシンに収まります。 enter image description here

ソース: https://Azure.Microsoft.com/ja-jp/blog/containers-docker-windows-and-trends/

22
Ali Kahoot

違いについてもっと詳しく説明する多くの答えがありますが、ここに私の非常に簡単な説明があります。

1つの重要な違いは、 VMはOS を実行するために別のカーネルを使用することです。これが、それが重くて起動に時間がかかり、より多くのシステムリソースを消費する理由です。

Dockerでは、コンテナはカーネルをホストと共有します 。それゆえ、それは軽量であり、素早く開始および停止することができる。

仮想化では、リソースはセットアップの開始時に割り当てられるため、仮想マシンがアイドル状態のときにリソースが完全には利用されません。 Dockerでは、コンテナには固定量のハードウェアリソースが割り当てられず、要件に応じて自由にリソースを使用できるため、スケーラビリティが非常に高くなります。

Dockerは UNIONファイルシステムを使用します .. Dockerはコピーオンライトテクノロジを使用して、コンテナによって消費されるメモリスペースを削減します。 もっと読む

18
Jayabalan Bala

アプリケーションを実行するためのスタックを提供する3つの異なる設定があります(これは、コンテナとは何か、そして他のソリューションよりも強力になっている理由を認識するのに役立ちます)。

1) Traditional Servers(bare metal)
2) Virtual machines (VMs)
3) Containers

1) 従来のサーバー stackは、オペレーティングシステムとアプリケーションを実行する物理サーバーで構成されています。

利点:

  • 原料の利用

  • アイソレーション

デメリット:

  • 非常に遅い展開時間
  • 高価な
  • 無駄なリソース
  • 規模が難しい
  • 移行が難しい
  • 複雑な構成

2) VM stack は、オペレーティングシステムを実行する物理サーバーと、仮想マシン、共有リソース、およびネットワークインターフェイスを管理するハイパーバイザーで構成されています。各Vmは、ゲストオペレーティングシステム、アプリケーション、または一連のアプリケーションを実行します。

利点:

  • 資源の有効利用
  • 拡張が簡単
  • バックアップと移行が簡単
  • コスト効率
  • 柔軟性

デメリット:

  • リソース割り当てに問題がある
  • 仕入先ロッキン
  • 複雑な構成

3) Container Setup 、他のスタックとの主な違いは、コンテナベースの仮想化がホストOSのカーネルを使用して複数の独立したゲストインスタンスをラム化することです。これらのゲストインスタンスはコンテナと呼ばれます。ホストは、物理サーバーまたはVMのいずれかです。

利点:

  • アイソレーション
  • 軽量
  • リソース有効
  • 移行が簡単
  • セキュリティ
  • 低いオーバーヘッド
  • ミラー製造開発環境

デメリット:

  • 同じアーキテクチャ
  • リソース重いアプリ
  • ネットワークとセキュリティの問題.

コンテナー設定をその前の設定と比較することにより、コンテナー化が今日までで最も速く、最もリソース効率がよく、最も安全な設定であると結論付けることができます。コンテナは、アプリケーションを実行する独立したインスタンスです。 Dockerがコンテナをスピンアップすると、デフォルトのストレージドライバ(Overlayドライバ)で数秒以内に実行されるレイヤと、コンテナにコミットするとその上にコピーオンライトレイヤが作成され、レイヤが実行されます。コンテナの実行 VMの場合、仮想化環境にすべてをロードするのに約1分かかります。これらの軽量インスタンスは簡単に交換、再構築、移動できます。これは私達が生産および開発環境を映すことを可能にし、CI/CDプロセスの途方もない助けです。コンテナーが提供できる利点は非常に説得力があるので、それらは間違いなくここにいます。

18
mohan08p

に関して:-

「一貫した実稼働環境に単純にデプロイするよりも、ソフトウェアをdockerイメージにデプロイする方が簡単なのはなぜですか?

ほとんどのソフトウェアは多くの環境に展開されますが、通常は少なくとも次の3つです。

  1. 個々の開発者PC
  2. 共有開発者環境
  3. 個々のテスターPC
  4. 共有テスト環境
  5. QA環境
  6. UAT環境
  7. 負荷/性能試験
  8. ライブステージング
  9. 製造
  10. アーカイブ

考慮すべき次の要素もあります。

  • 開発者、そして実際にテスターは、仕事の性質上、微妙にまたは非常に異なるPC構成を持っています。
  • 開発者は、企業またはビジネスの標準化ルールの制御を超えてPC上で開発することができます(たとえば、自分のマシン(多くの場合リモート)で開発するフリーランサーや、PCを特定に構成するために「雇用」または「契約」していないオープンソースプロジェクトへの貢献者など)方法)
  • 一部の環境は、負荷分散構成の固定数の複数のマシンで構成されます
  • 多くの実稼働環境では、トラフィックレベルに応じて、クラウドベースのサーバーが動的に(または「弾性的に」)作成および破棄されます。

ご覧のように、組織のサーバーの推定総数は1桁であることがめったになく、3桁であることが非常に多く、簡単に大幅に増やすことができます。

これはすべて、そもそも一貫した環境を作成することは、(グリーンフィールドシナリオでも)ボリュームが大きいだけで十分に難しいことを意味しますが、一貫性を保つことはほとんど不可能ですサーバーの数が多い場合、新しいサーバーの追加(動的または手動)、O/Sベンダー、アンチウイルスベンダー、ブラウザーベンダーなどからの自動更新、開発者またはサーバー技術者による手動ソフトウェアインストールまたは構成変更など。これを繰り返します。環境の一貫性を維持することは事実上(しゃれなし)不可能です(もちろん、純粋主義者にとってはできますが、膨大な時間、労力、および規律が必要です。最初の場所)。

あなたの質問をもっともっと考えてみてください「すべての環境の一貫性を保つのが非常に難しいことを考えると、学習曲線を考慮してもソフトウェアをdockerイメージにデプロイするのは簡単ですか?」。答えは必ず「はい」になると思うと思いますが、見つける方法は1つしかありません。この新しい質問をStack Overflowに投稿してください。

17
Greg Trevellick

仮想マシン の場合、サーバーがあり、そのサーバーにホストオペレーティングシステムがあり、さらにハイパーバイザーがあります。そして、そのハイパーバイザーの上で実行されて、私たちはアプリケーションとその依存バイナリ、そしてそのサーバー上のライブラリーを持つゲストオペレーティングシステムをいくつでも持っています。それはそれで全体のゲストオペレーティングシステムをもたらします。かなりヘビー級です。各物理マシンに実際に配置できる量にも制限があります。

Enter image description here

Dockerコンテナ 一方、わずかに異なります。サーバーがあります。ホストオペレーティングシステムがあります。しかし、 代わりにハイパーバイザー 、この場合は Dockerエンジン があります。この場合、ゲストオペレーティングシステム全体を一緒に持ってくるわけではありません。 私たちは非常に薄いオペレーティングシステムの層を持ってきています 、そしてコンテナはそこにあるカーネルの機能に到達するためにホストOSと対話することができます。そしてそれは私達が非常に軽量の容器を持つことを可能にします。

そこにあるのは、アプリケーションコードとそれが必要とするバイナリとライブラリだけです。また、それらのバイナリやライブラリを実際に使用したい場合は、異なるコンテナ間で共有することもできます。そしてこれが私たちにできることは、たくさんのことです。 はるかに速い起動時間 があります。あなたはそのような数秒で単一のVMを立ち上がることはできません。そして同様に、それらをできるだけ速くダウンさせるのです。それで私たちは非常に素早くスケールアップとスケールダウンをすることができます、そして、後でそれを見るでしょう。

Enter image description here

すべてのコンテナは、それ自身のオペレーティングシステムのコピー上で実行されていると考えています。独自のファイルシステム、独自のレジストリなどを持っていますが、これは一種の嘘です。実際に仮想化されています。

12
Nedzad G

本番環境とステージングでDockerを使用しました。慣れると、マルチコンテナと隔離された環境を構築するのに非常に強力になるでしょう。

DockerはLXC(Linux Container)に基づいて開発されており、多くのLinuxディストリビューション、特にUbuntuで完璧に動作します。

Dockerコンテナは隔離された環境です。 Dockerイメージから作成されたDockerコンテナーでtopコマンドを発行すると、それを見ることができます。

それに加えて、それらはdockerFile設定のおかげで非常に軽量で柔軟です。

たとえば、Dockerイメージを作成してDockerFileを構成し、たとえば実行中に「this」、「apt-get」、「シェルスクリプト」、環境変数などの設定を指定できます。

マイクロサービスプロジェクトとアーキテクチャにおいて、Dockerは非常に実行可能な資産です。 Docker、Docker Swarm、Kubernetes、Docker Composeを使用して、スケーラビリティ、弾力性、弾力性を実現できます。

Dockerに関するもう1つの重要な問題はDocker Hubとそのコミュニティです。たとえば、Prometheus、Grafana、Prometheus-JMX-Exporter、およびDokcerを使用して、カフカを監視するためのエコシステムを実装しました。

そのために、zookeeper、kafka、Prometheus、Grafana、およびjmx-collector用に構成済みDockerコンテナーをダウンロードしてから、それらのいくつかにymlファイルを使用して独自の構成をマウントしました。このアーキテクチャは簡単に複数のサーバーに移動できることを分離とスケーラビリティと弾力性と単一のマシン上でマルチコンテナドッカーを使用してカフカを監視するためのシステム。

Docker Hubサイト以外にもquay.ioという別のサイトがあり、そこに独自のDockerイメージダッシュボードを配置したり、そこからプル/プッシュしたりすることができます。 Docker HubからDockerイメージをインポートしてから停止してから、自分のマシンでquayから実行することもできます。

注:そもそもDockerを学ぶのは複雑で難しいようですが、慣れるとそれなしでは作業できません。

間違ったコマンドを発行したり、コンテナーやすべてのデータや構成を誤って削除したりしたときのDockerの最初の頃を覚えています。

9
Touraj Ebrahimi

Difference between how apps in VM use cpu vs containers

出典:Kubernetes in Action。

6
TastyCode

これが Docker が自分自身を紹介する方法です。

Dockerは、コンテナーの動きを推進する会社であり、ハイブリッドクラウド全体のあらゆるアプリケーションに対応する唯一のコンテナープラットフォームプロバイダーです。今日のビジネスはデジタル化を求められていますが、クラウド、データセンター、およびアプリケーションアーキテクチャの多様化するポートフォリオを合理化しながら、既存のアプリケーションとインフラストラクチャに制約されています。 Dockerは、アプリケーションとインフラストラクチャー、開発者とIT部門の間の真の独立性を可能にし、それらの可能性を解き放ち、より良いコラボレーションと革新のためのモデルを作成します。

だから Docker はコンテナベースで、現在のマシンで実行できる画像とコンテナがあるということです。それは _ vm _ sのようなオペレーティングシステムを含みませんが、Java、Tomcatなどのような異なる作業パックのパックのようです。

コンテナーを理解していれば、Dockerとは何か、また _ vm _ sとどう違うのかがわかります。

それで、コンテナは何ですか?

コンテナイメージは、コード、ランタイム、システムツール、システムライブラリ、設定など、実行に必要なすべてのものを含む、ソフトウェアの軽量でスタンドアロンの実行可能パッケージです。 LinuxベースおよびWindowsベースの両方のアプリケーションで使用可能なコンテナ化ソフトウェアは、環境に関係なく常に同じように動作します。コンテナは、開発環境とステージング環境の違いなど、ソフトウェアを周囲から隔離し、同じインフラストラクチャ上で異なるソフトウェアを実行しているチーム間の競合を減らすのに役立ちます。

Docker

下の画像でわかるように、各コンテナには個別のパックがあり、そのマシンのオペレーティングシステムを共有する単一のマシンで実行されています...安全で出荷が簡単です...

5
Alireza

ここには、VMとコンテナーの違い、およびDockerの起源について明確に説明している、技術的な回答が多数あります。

私にとっては、VMとDockerの根本的な違いは、アプリケーションのプロモーションをどのように管理するかです。

VMでは、アプリケーションとその依存関係を、あるVMから次のDEV、UAT、PRDに昇格させます。

  1. 多くの場合、これらのVMには異なるパッチとライブラリがあります。
  2. 複数のアプリケーションがVMを共有することは珍しくありません。これには、すべてのアプリケーションの構成と依存関係を管理する必要があります。
  3. バックアウトするには、VMで変更を元に戻す必要があります。可能であればそれを復元します。

Dockerを使うと、アプリケーションを、必要なライブラリと共にそれ自身のコンテナの中にまとめ、次に whole コンテナを1つの単位として昇格させることができます。

  1. カーネルを除いて、パッチとライブラリは同一です。
  2. 一般的な規則として、設定を簡単にするためにコンテナごとに1つのアプリケーションしかありません。
  3. バックアウトは、コンテナーの停止と削除で構成されています。

したがって、最も基本的なレベルではVMを使用してアプリケーションとその依存関係を個別のコンポーネントとして宣伝しますが、Dockerを使用するとすべてを一気に宣伝します。

そして、KubernetesやDocker Swarmのようなツールはタスクを非常に単純化しますが、はい。

4
TJA