DUICUO

これはおそらく、Docker を使い始めるための最も詳細かつ入念にまとめられたガイドです。

コンピュータ技術の急速な発展に伴い、Docker は中国で急成長しています。

Dockerは、特に大手インターネット企業で広く利用されており、企業によっては面接で有利に働くこともあります。信じられないなら、下の図を見てください。

これは、ある求人サイトで見かけたJava開発エンジニアの求人です。採用条件の一つに、Dockerの知識があることが採用の決め手となるとありました。インターネット企業において、Dockerの知識がいかに重要かがよく分かります。

市場にはすでに優れた Docker チュートリアルが数多く存在しますが、その基礎となる原則の多くは初心者にとってまだ理解しにくいものであり、明確に説明されていないように思います (私自身もかなり混乱しています)。

初心者がよくある落とし穴に陥らないように、私の学習経験と CTF 参加者の観点からこのチュートリアルを書き、Docker を理解して習得できるように導きます。

Dockerとは何ですか?

では、Docker とは一体何でしょうか? Docker を理解する前に、コンテナと仮想マシンという 2 つの概念を区別する必要があります。

読者の多くは仮想マシンを使ったことがあるかもしれませんが、コンテナの概念にはあまり馴染みがないかもしれません。VMwareやVisualBoxなどの従来の仮想マシンでは、ハードウェアを含むマシン全体をシミュレートする必要があります。

各仮想マシンには独自のオペレーティング システムが必要であり、仮想マシンを起動すると、事前に割り当てられたすべてのリソースが使用されるようになります。

各仮想マシンには、アプリケーション、必要なバイナリとライブラリ、完全なユーザー オペレーティング システムが含まれています。

コンテナ テクノロジーは、ハードウェア リソースとオペレーティング システムをホスト マシンと共有し、リソースの動的な割り当てを可能にします。

コンテナはアプリケーションとそのすべての依存関係を含みますが、カーネルは他のコンテナと共有します。コンテナは、ホストオペレーティングシステム内のユーザー空間で個別のプロセスとして実行されます。

コンテナ テクノロジーはオペレーティング システムを仮想化し、分離されたリソースを持つプロセスでアプリケーションとその依存関係を実行できるようにする方法です。

コンテナを使用すると、アプリケーションのコード、構成、依存関係を使いやすいビルディング ブロックに簡単にパッケージ化できるため、環境の一貫性、運用効率、開発者の生産性、バージョン管理など、多くの目標を達成できます。

コンテナを使用すると、デプロイメント環境に関係なく、アプリケーションを迅速かつ確実に、一貫してデプロイできるようになります。

コンテナにより、リソースをより細かく制御できるようになり、インフラストラクチャの効率も向上します。

次の画像は、両者の違いを明確に示しています。

Dockerは、コンテナを利用するためのシンプルで使いやすいインターフェースを提供するLinuxコンテナの一種です。現在、最も人気のあるLinuxコンテナソリューションです。

Linuxコンテナは、Linuxから開発されたもう一つの仮想化技術です。簡単に言うと、Linuxコンテナは完全なオペレーティングシステムをシミュレートするのではなく、プロセスを分離し、通常のプロセスの外側に保護層を配置します。

コンテナ内のプロセスの場合、アクセスするすべてのリソースは仮想化されているため、基盤となるシステムからの分離が実現されます。

Dockerはアプリケーションとその依存関係を1つのファイルにパッケージ化します。このファイルを実行すると、仮想コンテナが作成されます。

プログラムは、実際の物理マシン上で実行されるのと同じように、この仮想コンテナ内で実行されます。Dockerを使えば、環境の問題を心配する必要はありません。

全体的に、Dockerのインターフェースは非常にシンプルで、ユーザーはコンテナを簡単に作成・使用し、アプリケーションをコンテナ内に配置することができます。また、コンテナは、通常のコード管理と同様に、バージョン管理、コピー、共有、変更が可能です。

Dockerの利点

Docker には、従来の仮想化方法に比べていくつかの利点があります。

  • Dockerは数秒で起動します。一方、仮想マシンの起動には通常数分かかります。
  • Docker は必要なリソースが少なくて済みます。Docker はオペレーティングシステムレベルで仮想化を行います。Docker コンテナはパフォーマンスの低下をほとんど伴わずにカーネルとやり取りするため、ハイパーバイザー層を介してカーネルレベルとやり取りする仮想化よりも優れたパフォーマンスを発揮します。
  • Dockerはより軽量です。Dockerのアーキテクチャは、単一のカーネルとアプリケーションライブラリを共有できるため、メモリ使用量が最小限に抑えられます。同じハードウェア環境上で、Dockerは仮想マシンよりもはるかに多くのイメージを実行できるため、システム使用率が非常に高くなります。
  • 仮想マシンと比較すると、Docker の分離は弱くなります。Docker はプロセス間の分離を提供しますが、仮想マシンはシステムレベルの分離を提供します。
  • セキュリティ。Dockerのセキュリティも脆弱です。Dockerのテナントルートはホストマシンのルートに相当します。コンテナ内のユーザーが通常のユーザー権限からルート権限に昇格すると、ホストマシンのルート権限を直接取得し、制限のない操作を実行できるようになります。

仮想マシン テナントのルート権限は、ホスト マシンのルート仮想マシン権限とは別であり、仮想マシンは Intel の VT-d や VT-x などのリング 1 ハードウェア分離テクノロジを利用します。

この分離テクノロジーは仮想マシンが突破して相互にやり取りすることを防ぐことができますが、コンテナには現在、ハードウェア分離の形式がまったくないため、攻撃に対して脆弱です。

  • 管理性。Dockerの集中管理ツールはまだ成熟していません。様々な仮想化技術には成熟した管理ツールがあり、例えばVMware vCenterは包括的な仮想マシン管理機能を提供しています。
  • 高可用性と回復性。Docker によるサービスの高可用性のサポートは、迅速な再デプロイメントによって実現されます。
  • 仮想化には、負荷分散、高可用性、フォールトトレランス、移行、データ保護といった、成熟した実績のあるセキュリティメカニズムが備わっています。VMwareは、仮想マシンの99.999%の高可用性を保証し、ビジネスの継続性を確保します。
  • 迅速な作成と削除。仮想化の作成は数分、Dockerコンテナの作成は数秒で完了します。Dockerの迅速な反復処理機能により、開発、テスト、デプロイメントにかかる時間を大幅に短縮できます。
  • 配信とデプロイメント。仮想マシンはイメージを通じて一貫した環境配信を実現できますが、イメージの配布を体系的に整理することはできません。一方、Dockerはコンテナの構築プロセスをDockerfileに文書化することで、クラスター内での迅速な配布とデプロイメントを可能にします。

次の表は、従来の仮想マシンと比較したコンテナの利点を明確に示しています。

Dockerの3つの基本概念

上の図からわかるように、Docker には 3 つの基本概念が含まれています。

  • 画像(鏡像)
  • 容器
  • リポジトリ

イメージは Docker がコンテナを実行するための前提条件であり、リポジトリはイメージを保存する場所です。つまり、イメージが Docker の中核であることは明らかです。

画像(鏡像)

では、Docker イメージとは一体何でしょうか?Docker イメージは、コンテナの実行に必要なプログラム、ライブラリ、リソース、構成ファイルを提供するだけでなく、実行時に用意されたいくつかの構成パラメータ(匿名ボリューム、環境変数、ユーザーなど)も含む特殊なファイルシステムと見なすことができます。

イメージには動的なデータは含まれておらず、その内容は作成後も変更されません。イメージとは、基本的に読み取り専用レイヤーの集合を統合したビューです。この定義は少し分かりにくいかもしれませんが、次の図がイメージの定義を理解するのに役立ちます。

左側から見ると、複数の読み取り専用レイヤーが重なり合っているのがわかります。最下層を除き、各レイヤーにはその下のレイヤーへのポインタがあります。これらのレイヤーはDocker内の実装の詳細であり、ホストのファイルシステムからアクセスできます。

Union File System テクノロジーは、さまざまなレイヤーを単一のファイル システムに統合し、これらのレイヤーの統一されたビューを提供します。

これにより、複数のレイヤーの存在が隠され、ユーザーの観点からは1つのファイルシステムしか存在しないように見えます。この様子は、画像の右側に示されています。

容器

コンテナの定義はイメージの定義とほぼ同じです。どちらもレイヤーセットの統合されたビューです。唯一の違いは、コンテナの最上位レイヤーが読み取りと書き込み可能であることです。

コンテナの定義にはコンテナを実行するかどうかは記載されていないため、実際にはコンテナ = イメージ + 読み取り/書き込みレイヤーとなります。

リポジトリ

Dockerリポジトリは、Dockerイメージファイルを一元的に保存する場所です。イメージをビルドすれば、現在のホスト上で簡単に実行できます。

ただし、このイメージを他のサーバーで使用する必要がある場合は、イメージを保存および配布するための集中型サービスが必要であり、Docker Registry はそのようなサービスです。

「リポジトリ」と「レジストリ」という用語は互換的に使用され、厳密に区別されない場合があります。

Docker リポジトリの概念は Git に似ており、レジストリ サーバーは GitHub のようなホスティング サービスとして理解できます。

実際、Docker レジストリには複数のリポジトリを含めることができ、各リポジトリには複数のタグを含めることができ、各タグはイメージに対応します。

したがって、イメージ リポジトリは、以前使用したコード リポジトリと同様に、Docker がイメージ ファイルを集中的に保存する場所です。

通常、リポジトリには同じソフトウェアの異なるバージョンのイメージが含まれており、ソフトウェアの異なるバージョンに対応するためにタグがよく使用されます。

ソフトウェアイメージのバージョンは、<リポジトリ名>:<タグ> という形式で指定できます。タグが指定されていない場合は、Latest がデフォルトのタグとして使用されます。

倉庫は2つのタイプに分けられます。

  • 公共倉庫
  • プライベート(専用倉庫)

Docker レジストリは、ユーザーに公開され、イメージを管理できるパブリック レジストリ サービスです。

これらの公開サービスでは通常、ユーザーは公開されている画像を無料でアップロードおよびダウンロードできますが、ユーザーが非公開画像を管理するための有料サービスも提供される場合があります。

パブリックサービスに加えて、ユーザーはローカルにプライベートDockerレジストリを設定することもできます。Dockerは、プライベートレジストリサービスとして直接使用できる公式Dockerレジストリイメージを提供しています。

ユーザーが独自のイメージを作成したら、Pushコマンドを使用してパブリックまたはプライベートリポジトリにアップロードできます。次にこのイメージを別のマシンで使用したいときは、リポジトリからプルするだけで済みます。

主に、イメージ、コンテナ、リポジトリなどの一般的な Docker の概念について詳しく説明し、従来の仮想化方法の観点から Docker の利点についても説明しました。

次の図は、Docker のアーキテクチャの概要を明確に示しています。

Dockerはクライアント/サーバーアーキテクチャを採用しています。DockerクライアントはDockerサーバーと連携し、Dockerイメージの構築、実行、配布を行います。

Docker クライアントとサーバーは同じマシン上で実行することも、RESTful、ストック、または Web インターフェースを介してリモート Docker サーバーと通信することもできます。

この図は、Dockerクライアント、サーバー、そしてDockerリポジトリ(Docker HubとDocker Cloud)を示しています。デフォルトでは、DockerはDocker Centralリポジトリからイメージファイルを探します。

リポジトリ管理イメージを使用するというこの設計コンセプトは、Gitに似ています。もちろん、このリポジトリは設定を変更することで指定でき、独自のプライベートリポジトリを作成することもできます。

Dockerのインストールと使用方法

Docker のインストールと使用には、主にシステム アーキテクチャとカーネル サポートに関していくつかの前提条件があります。

システム アーキテクチャに関しては、Docker が当初からサポートしてきた x86-64 以外にも、他のシステム アーキテクチャのサポートが継続的に改善され、進化しています。

Docker には、CE と EE という 2 つの主要なバージョンがあります。CE はコミュニティ エディションで、無料で 7 か月間サポートされます。EE はセキュリティを重視したエンタープライズ エディションで、有料で、24 か月間サポートされます。

インストール前に、Dockerの最新のサポート情報については公式ドキュメントをご覧ください。公式ドキュメントはこちらです。

  1. https://docs.docker.com/install/

Docker には、カーネルでサポートされている機能、つまりカーネル構成オプション (Cgroup や Namespace 関連のオプション、およびその他のネットワーク ドライバーやストレージ ドライバーなど) に対しても特定の要件があります。

Docker ソース コードには、カーネル構成を検出してガイドする検出スクリプトが用意されています。このスクリプトは次の場所にあります。

  1. https://raw.githubusercontent.com/docker/docker/master/contrib/ check-config.sh

前提条件が満たされると、インストールは非常に簡単になります。

Docker CE のインストール手順については、公式ドキュメントを参照してください。

  • macOS: https://docs.docker.com/docker-for-mac/install/
  • Windows: https://docs.docker.com/docker-for-windows/install/
  • Ubuntu: https://docs.docker.com/install/linux/docker-ce/ubuntu/
  • Ubuntu: https://docs.docker.com/install/linux/docker-ce/debian/
  • CentOS: https://docs.docker.com/install/linux/docker-ce/centos/
  • フェドラ: https://docs.docker.com/install/linux/docker-ce/fedora/
  • その他の Linux ディストリビューション: https://docs.docker.com/install/linux/docker-ce/binaries/

ここでは CentOS 7 を例として使用します。

環境の準備:

Alibaba Cloud サーバー (1 コア、2GB RAM、1Mbps 帯域幅)

CentOS 7.4 64ビット

Docker-CE は CentOS 7 の 64 ビット バージョンをサポートしており、少なくとも 3.10 のカーネル バージョンが必要なので、まず古いバージョンの Docker をアンインストールする必要があります。

  1. $ sudo yum 削除 docker \
  2. docker-client \
  3. docker-client-最新\
  4. docker-common\
  5. docker-最新\
  6. docker-latest-logrotate \
  7. docker-logrotate \
  8. docker-selinux \
  9. docker-engine-selinux \
  10. dockerエンジン

依存パッケージをインストールするには、次のインストール コマンドを実行します。

  1. $ sudo yum インストール -y yum-utils \
  2. デバイスマッパーの永続データ \
  3. lvm2

すでに事前にインストールしていたので、最新バージョンがすでにインストールされていることが示されています。

Dockerをインストールする

DockerパッケージはデフォルトのCentOS-Extrasソフトウェアリポジトリに既に含まれています。そのため、Dockerをインストールするには、次のyumコマンドを実行するだけです。

  1. $ sudo yum インストール docker

もちろん、テスト環境や開発環境では、Dockerはインストールプロセスを簡素化する便利なインストールスクリプトを提供しています。このスクリプトはCentOSシステムへのインストールに使用できます。

  1. curl -fsSL get.docker.com -o get-docker.shsh get-docker.sh

詳細については、docker-install スクリプトを参照してください。

  1. https://github.com/docker/docker-install

このコマンドを実行すると、スクリプトはすべての準備を自動的に完了し、Docker CE の Edge バージョンをシステムにインストールします。

インストール後、次のコマンドを実行して、インストールが成功したかどうかを確認します。

  1. docker バージョンまたは docker 情報

Docker バージョン情報が返されると、Docker のインストールが正常に完了したことが確認されます。

Docker-CEを起動します。

  1. $ sudo systemctl docker を有効にする$ sudo systemctl docker を起動する

Docker の簡単な使用例: Hello World

サーバーが毎日クラッシュし、Docker に問題が発生したため、次のデモは Kali Linux 環境に基づいています。

「Hello World」というシンプルなイメージファイルを通して、Dockerの魅力を体験してみましょう!

次のコマンドを直接実行して、hello-world という名前のイメージ ファイルをリポジトリからローカル マシンに取得します。

  1. docker pull ライブラリ/hello-world

`docker pull images` はイメージ ファイルを取得します。`library/hello-world` はリポジトリ内のイメージ ファイルの場所です。ここで、`library` はイメージ ファイルを含むグループであり、`hello-world` はイメージ ファイルの名前です。

キャプチャが成功すると、ローカル マシンに次の画像ファイルが表示されます。

  1. Dockerイメージ

次のような結果が見られます。

これで、hello-world イメージファイルを実行できます。

  1. docker で hello-world を実行する

次のような結果が見られます。

このメッセージが表示された後、「hello world」の実行は停止し、コンテナは自動的に終了します。ただし、MySQLイメージなどのサービスを提供しているコンテナは、自動的に終了しない場合があります。

簡単でしょう?上記のように、Dockerは非常に強力です。さらに、UbuntuやApacheなどのイメージをプルすることもできます。これについては、今後のチュートリアルで説明します。

Dockerは、イメージの作成と更新のためのシンプルで実用的なコマンドセットを提供しています。事前に作成されたアプリケーションイメージをネットワークから直接ダウンロードし、Docker RUNコマンドで直接使用することができます。

RUN コマンドを使用してイメージが正常に実行されると、Docker コンテナになります。

コンテナは軽量なサンドボックスと捉えることができます。Dockerはコンテナを使用してアプリケーションの実行と分離を行います。コンテナはDockerイメージに影響を与えることなく、起動、停止、削除できます。

次の図を見てみましょう。

Dockerクライアントは、DockerユーザーがDockerとやり取りする主な手段です。Dockerコマンドラインを使用してコマンドを実行すると、Dockerクライアントはこれらのコマンドをサーバーに送信し、サーバーはそれを実行します。

DockerコマンドはDocker APIを使用します。Dockerクライアントは複数のサーバーと通信できます。

Dockerコンテナの仕組みを分析します。Dockerコンテナの動作原理を理解することで、独自のコンテナを管理できるようになります。

Dockerアーキテクチャ

上記のレッスンでは、Dockerの基本的なアーキテクチャについて簡単に説明しました。Dockerはクライアント/サーバーアーキテクチャを採用していることを学びました。

Docker クライアントが Docker サーバーと対話する場合、Docker サーバーが Docker イメージの構築、実行、配布を担当することが理解されています。

Docker クライアントとサーバーが同じマシン上で実行できることがわかっているので、RESTful、ストック、またはネットワーク インターフェイスを介してリモート Docker サーバーと通信できます。

次の図は、Docker のアーキテクチャの概要を明確に示しています。

Docker のコア コンポーネントは次のとおりです。

  • Dockerクライアント
  • Dockerデーモン
  • Dockerイメージ
  • Dockerレジストリ
  • Dockerコンテナ

Dockerはクライアント/サーバーアーキテクチャを採用しています。クライアントはサーバーにリクエストを送信し、サーバーはコンテナの構築、実行、配布を担当します。

クライアントとサーバーは同じホスト上で実行でき、クライアントはソケットまたは REST API を介してリモート サーバーと通信することもできます。

REST API とは何かなど、まだ理解していない部分もあるかもしれませんが、心配しないでください。後の記事で詳しく説明します。

Dockerクライアント

Dockerクライアント(Dockerクライアントとも呼ばれます)は、本質的にはDockerが提供するコマンドラインインターフェース(CLI)ツールです。多くのDockerユーザーがDockerを操作するための主な手段となっています。

クライアントはアプリケーションをビルド、実行、停止できるほか、Docker ホストとリモートで対話することもできます。

最も一般的に使用される Docker クライアントは Docker コマンドであり、これを使用すると、ホスト上で Docker コンテナーを簡単に構築および実行できます。

Dockerデーモン

Dockerデーモンは、Linuxのバックグラウンドサービスとして実行されるサーバーコンポーネントです。Dockerの中核となるバックグラウンドプロセスであり、デーモンプロセスとも呼ばれます。

Docker クライアントからの要求に応答し、これらの要求をシステム コールに変換してコンテナー管理操作を完了する役割を担います。

このプロセスはバックグラウンドでAPIサーバーを起動し、Dockerクライアントから送信されたリクエストの受信を担当します。受信したリクエストはDockerデーモン内のルーティングメカニズムによってディスパッチおよびスケジュールされ、特定の関数によって実行されます。

大まかに分けると次の3つの部分に分けられます。

  • Dockerサーバー
  • エンジン
  • 仕事

Docker デーモンのアーキテクチャは次のとおりです。

Docker デーモンは、Docker サーバー モジュールを介して Docker クライアントからの要求を受け入れ、エンジンで要求を処理し、要求の種類に基づいて指定されたジョブを作成して実行するものと考えることができます。

Docker デーモンは Docker ホスト上で実行され、コンテナの作成、実行、監視、およびイメージの構築と保存を担当します。

プロセスの機能は次のいずれかになります。

  • Docker レジストリからイメージを取得します。
  • Graphdriver はコンテナ イメージに対してローカリゼーション操作を実行します。
  • networkdriver を使用してコンテナのネットワーク環境を構成します。
  • execdriver は、コンテナ内で実行されるタスクを実行するために使用されます。

Docker デーモンと Docker クライアントはどちらも実行可能ファイル Docker を通じて起動されるため、起動プロセスは非常に似ています。

Docker 実行ファイルが実行されると、異なるコマンドライン フラグ パラメータによって 2 つのコードが区別され、最終的にそれぞれの対応する部分が実行されます。

Docker デーモンを起動するには、通常、次のコマンドを使用します。

  1. docker --daemon=truedocker –d  
  2. docker -d = true  

次に、Docker の main() 関数は上記のコマンドの対応する Flag パラメータを解析し、最終的に Docker デーモンの起動を完了します。

次の図は、Docker デーモンの起動プロセスを明確に示しています。


デフォルトでは、Dockerデーモンはローカルホストからのクライアントリクエストにのみ応答できます。リモートクライアントからのリクエストを許可するには、設定ファイルでTCPリスニングを有効にする必要があります。

以下の手順に従って設定できます。

① 設定ファイル /etc/systemd/system/multi-user.target.wants/docker.service を編集し、環境変数 ExecStart の後に -H tcp://0.0.0.0 を追加して、任意の IP からのクライアント接続を許可します。

② Dockerデーモンを再起動します。

  1. systemctlデーモンリロード
  2. systemctl で docker.service を再起動します。

③ 次のコマンドを使用してリモートサーバーと通信できます。

  1. docker -H サーバーのIPアドレス情報

-H オプションはサーバーホストを指定するために使用され、info サブコマンドは Docker サーバーに関する情報を表示するために使用されます。

Dockerイメージ

Docker イメージは、コンテナ実行時に必要なプログラム、ライブラリ、リソース、構成ファイルを提供するだけでなく、実行時に用意されたいくつかの構成パラメータ (匿名ボリューム、環境変数、ユーザーなど) も含む特別なファイル システムと見なすことができます。

Dockerイメージには動的なデータは含まれておらず、ビルド後に内容が変更されることはありません。Dockerイメージは、Dockerコンテナを作成するために使用できる読み取り専用のテンプレートと考えることができます。

画像を生成する方法は複数あります。

  • ゼロから画像を作成する
  • 他の人が作成した既成画像をダウンロードして使用します。
  • 既存のイメージ上に新しいイメージを作成します。

イメージの内容や作成手順をDockerfileと呼ばれるテキストファイルに記述し、`docker build`を実行することができます。このコマンドは Docker イメージをビルドできます。

Dockerレジストリ

Docker レジストリは Docker イメージを保存するためのリポジトリであり、Docker エコシステムにおけるその位置は次の図に示されています。

docker push、docker pull、docker search を実行すると、Docker デーモンは実際に Docker レジストリと通信します。

Dockerコンテナ

Docker コンテナは、Docker イメージの実行中のインスタンスです。プロジェクト プログラムが実際に実行され、システム リソースを消費し、サービスを提供する場所です。

Dockerコンテナはシステムのハードウェア環境を提供します。Dockerイメージ(あらかじめ作成されたシステムディスク)とプロジェクトコードを使用して、サービスの実行と提供を行うことができます。

Dockerコンポーネントが連携してコンテナを実行する仕組み

読者の皆さんは、ここまで読んでDockerインフラストラクチャについてかなり理解されているかと思います。私たちが初めて実行したコンテナを覚えていますか?

ここで、hello-world の例を使用して、Docker のさまざまなコンポーネントがどのように連携するかを理解してみましょう。

コンテナの起動プロセスは次のとおりです。

  • Docker クライアントは `docker run` コマンドを実行します。
  • Docker デーモンは、hello-world イメージがローカル マシンに存在しないことを検出しました。
  • デーモンは Docker Hub からイメージをダウンロードします。
  • ダウンロードが完了しました。hello-world イメージがローカルに保存されました。
  • Docker デーモンがコンテナを起動します。

具体的なプロセスは次のデモ図で確認できます。

Docker イメージから、hello-world がローカル マシンにダウンロードされたことがわかります。

実行中のコンテナを表示するには、Docker Ps または Docker Container ls を使用します。hello-world はメッセージを出力した後、実行を停止し、コンテナも自動的に終了していることがわかります。つまり、確認した時点では実行中のコンテナは見つかりません。

Dockerコンテナのワークフローを明確に分析しました。コンテナ内でDockerコンポーネントを連携して実行するプロセスは、概ね以下のプロセスに分けられることがお分かりいただけると思います。

  • Docker クライアントは `docker run` コマンドを実行します。
  • Docker デーモンは、必要なイメージがローカルで利用できないことを検出しました。
  • デーモンは Docker Hub からイメージをダウンロードします。
  • ダウンロードが完了すると、画像はローカルに保存されます。
  • Docker デーモンがコンテナを起動します。

これらのプロセスを理解すれば、コマンドの理解も難しくなくなるでしょう。それでは、よく使われるDockerコマンドの操作をいくつか説明します。

よく使われるDockerコマンド

`docker -h` を使用すると、コマンドの詳細なヘルプドキュメントを表示できます。ここでは、日常的によく使用する可能性のあるコマンドのみを説明します。

たとえば、Docker イメージをプルする必要がある場合は、次のコマンドを使用できます。

  1. docker pull イメージ名

`image_name` はイメージの名前です。Docker Hubからイメージをダウンロードする場合は、次のコマンドを使用します。

  1. docker pull centos:latest

cento: lastest はイメージの名前です。Dockerデーモンは、必要なイメージがローカルに存在しないことを検出すると、Docker Hubから自動的にイメージをダウンロードします。ダウンロードが完了すると、イメージはデフォルトで /var/lib/docker ディレクトリに保存されます。

次に、ホスト上に存在するイメージの数を確認する場合は、次のコマンドを使用します。

  1. Dockerイメージ

現在実行中のコンテナを確認するには、次のコマンドを使用します。

  1. docker ps -a

`-a` オプションは、現在使用されていないコンテナも含め、現在実行中のすべてのコンテナを表示します。コンテナを起動、再起動、停止するにはどうすればよいですか?

次のコマンドを使用できます。

  1. docker start コンテナ名/コンテナID
  2. docker コンテナ名/コンテナIDを再起動します
  3. docker stop コンテナ名/コンテナID

この時点でこのコンテナに入りたい場合は、`attach` コマンドを使用できます。

  1. docker attach コンテナ名/コンテナID

このコンテナ内でイメージを実行し、そのイメージ内で bash シェルを呼び出す場合は、次のコマンドを使用できます。

  1. docker run -t -i コンテナ名/コンテナID /bin/bash

この時点で特定のイメージを削除したい場合、そのイメージはコンテナによって参照(実行)されているため、参照されているコンテナが破棄(削除)されない限り、イメージを削除することはできません。

まず、このコンテナを停止する必要があります。

  1. docker psdocker stop コンテナ名/コンテナID

次に、次のコマンドを使用してこのコンテナを削除します。

  1. docker rm コンテナ名/コンテナID

次に、この時点で画像を削除します。

  1. docker rmi イメージ名

よく使われるDockerコマンドの説明はこれで終わりです。これらのコマンドについては、今後の記事でも引き続き取り上げていきます。

Dockerfile とは何ですか?

Dockerの基本的な概念については既にいくつか触れました。CTFの観点から見ると、Dockerfilesを使ってイメージを定義し、そのイメージに基づいてコンテナを実行し、現実世界の脆弱性シナリオをシミュレートすることができます。

したがって、Dockerfileはイメージとコンテナの鍵となることは間違いありません。また、Dockerfileを使うことでイメージのコンテンツ定義も非常に容易になります。では、Dockerfileとは一体何なのでしょうか?

Dockerfileは、Dockerイメージを自動的にビルドするための設定ファイルです。ユーザーはDockerfileを使用することで、カスタムイメージを迅速に作成できます。Dockerfile内のコマンドは、Linuxのシェルコマンドと非常によく似ています。

次の図は、Docker イメージ、コンテナ、および Dockerfile の関係を視覚的に示しています。

上の図からわかるように、Dockerfileを使用すると、イメージをカスタマイズし、Dockerコマンドを使って実行することでコンテナを起動できます。Dockerfileはコマンドステートメントの行で構成され、「#」で始まるコメント行をサポートしています。

一般的に、Dockerfile は次の 4 つの部分に分けられます。

  • ベースイメージ(親イメージ)情報コマンドFROM。
  • メンテナー情報コマンド MAINTAINER。
  • ミラー操作コマンドには、RUN、EVN、ADD、WORKDIR などがあります。
  • コンテナの起動命令には、CMD、ENTRYPOINT、USER が含まれます。

以下は簡単な Dockerfile の例です。

  1. Python:2.7MAINTAINER Angel_Kitty <[email protected]>からコピー . /app
  2. ワークディレクトリ /app
  3. pip install -r requirements.txt を実行します。
  4. EXPOSE 5000ENTRYPOINT [ "python" ]CMD [ "app.py" ]

上記のプロセスを分析してみましょう。

  • Docker Hub から Python 2.7 のベースイメージをプルします。
  • メンテナーに関する情報を表示します。
  • 現在のディレクトリをコンテナ内の /App ディレクトリにコピーし、ローカル ホスト ディレクトリをコピーします。 (Dockerfile を含むディレクトリへの相対パス) がコンテナに追加されます。
  • 作業パスを /App として指定します。
  • 依存関係をインストールします。
  • ポート5000を公開します。
  • アプリを起動します。

この例は、Python Flask アプリ(Flask は Python 用の軽量 Web フレームワーク)を起動するための Dockerfile です。この例を見れば、Dockerfile の構成とコマンドの記述手順について基本的な理解が得られると思います。

よく使われるDockerfileの指示

上記の例に基づいて、Dockerfileの構成と命令の記述プロセスの基本を理解できました。これらのよく使われるコマンドを理解することで、Dockerfileをより使いやすくなります。

Dockerfile 内のすべてのコマンドは、INSTRUCTION 引数、命令 (INSTRUCTION) は大文字と小文字を区別しませんが、大文字の使用が推奨されるという形式に従っています。これは SQL 文に似ていると思いませんか?これらの命令セットについて、正式に説明しましょう。

から

FROM は基になる画像を指定するために使用され、一般的な形式は FROM または FORM です。

すべてのDockerfileはFROMで始まる必要があります。FROMコマンドは、Dockerfileがベースとして使用するイメージを指定します。FROM以降のすべての命令は、FROMコマンドに基づいてイメージを作成します。

`FROM` コマンドは、同じ Dockerfile 内で複数回使用して複数のイメージを作成できます。例えば、Python 2.7 のベースイメージを指定するには、次のように記述します。

  1. Python:2.7から

メンテナー

MAINTAINER はミラー作成者と連絡先情報を指定するために使用され、その一般的な形式は MAINTAINER です。

ここでは自分の ID とメールを設定しました:

  1. メンテナー Angel_Kitty <[email protected]>

コピー

COPY は、ローカル ホスト マシンからデータをコピーするために使用されます。 (Dockerfileを含むディレクトリへの相対パス)をコンテナに

ローカルディレクトリをコピー元ディレクトリとして使用する場合は、COPY を使用することをお勧めします。一般的な形式は COPY です。

たとえば、現在のディレクトリをコンテナ内の /app ディレクトリにコピーする場合は、次のようにします。

  1. コピー . /app

ワークディレクトリ

WORKDIR は、RUN、CMD、および ENTRYPOINT コマンドと組み合わせて使用​​され、現在の作業パスを設定します。

複数のパスを設定できます。相対パスの場合は、前回のWORKDIRコマンドからの相対パスになります。デフォルトのパスは/です。一般的な形式はWORKDIR /path/to/work/dirです。

たとえば、/app パスを設定すると、次の操作を実行できます。

  1. ワークディレクトリ /app

走る

RUN 用于容器内部执行命令。每个RUN 命令相当于在原有的镜像基础上添加了一个改动层,原有的镜像不会有变化。一般格式为RUN

例如我们要安装Python 依赖包,我们做法如下:

  1. pip install -r requirements.txt を実行します。

さらす

EXPOSE 命令用来指定对外开放的端口。一般格式为EXPOSE [ ...]。

例如上面那个例子,开放5000端口:

  1. エクスポーズ5000

エントリーポイント

ENTRYPOINT 可以让你的容器表现得像一个可执行程序一样。一个Dockerfile 中只能有一个ENTRYPOINT,如果有多个,则最后一个生效。

ENTRYPOINT 命令也有两种格式:

  • ENTRYPOINT ["executable", "param1", "param2"] :推荐使用的Exec 形式。
  • ENTRYPOINT command param1 param2 :Shell 形式。

例如下面这个,我们要将Python 镜像变成可执行的程序,我们可以这样去做:

  1. ENTRYPOINT [ "python" ]

司令官

CMD 命令用于启动容器时默认执行的命令,CMD 命令可以包含可执行文件,也可以不包含可执行文件。

不包含可执行文件的情况下就要用ENTRYPOINT 指定一个,然后CMD 命令的参数就会作为ENTRYPOINT 的参数。

CMD 命令有三种格式:

  • CMD ["executable","param1","param2"]:推荐使用的exec 形式。
  • CMD ["param1","param2"]:无可执行程序形式。
  • CMD command param1 param2:Shell 形式。

一个Dockerfile 中只能有一个CMD,如果有多个,则最后一个生效。而CMD 的Shell 形式默认调用/bin/sh -c 执行命令。

CMD 命令会被Docker 命令行传入的参数覆盖:docker run busybox /bin/echo Hello Docker 会把CMD 里的命令覆盖。

例如我们要启动/app ,我们可以用如下命令实现:

  1. CMD [ "app.py" ]

当然还有一些其他的命令,我们在用到的时候再去一一讲解一下。

构建Dockerfile

我们大体已经把Dockerfile 的写法讲述完毕,我们可以自己动手写一个例子:

  1. mkdir static_web
  2. cd static_web
  3. touch Dockerfile

然后vi Dockerfile 开始编辑该文件,输入i 开始编辑。以下是我们构建的Dockerfile 内容:

  1. nginxから
  2. MAINTAINER Angel_Kitty <[email protected]>
  3. RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/ index .html

编辑完后按esc 退出编辑,然后:wq写入,退出。

我们在Dockerfile 文件所在目录执行:

  1. docker build -t angelkitty/nginx_web:v1 .

我们解释一下:

  • -t 是为新镜像设置仓库和名称
  • angelkitty 为仓库名
  • nginx_web 为镜像名
  • :v1 为标签(不添加为默认latest )

我们构建完成之后,使用Docker Images 命令查看所有镜像,如果存在REPOSITORY 为Nginx 和TAG 是v1 的信息,就表示构建成功。

接下来使用docker run 命令来启动容器:

  1. docker run --name nginx_web -d -p 8080:80 angelkitty/nginx_web:v1  

这条命令会用Nginx 镜像启动一个容器,命名为nginx_web ,并且映射了8080 端口。

这样我们可以用浏览器去访问这个Nginx 服务器:http://localhost:8080/ 或者http://本机的IP 地址:8080/,页面返回信息: