初めてのコンテナを実行する

DockerDockerBeginner
オンラインで実践に進む

This tutorial is from open-source community. Access the source code

💡 このチュートリアルは英語版からAIによって翻訳されています。原文を確認するには、 ここをクリックしてください

はじめに

この実験では、初めての Docker コンテナを実行します。

コンテナは、孤立して実行されるプロセス(またはプロセスのグループ)にすぎません。孤立は、Linux ネームスペース、コントロール グループ (cgroups)、seccomp および SELinux を介して達成されます。Linux ネームスペースとコントロール グループは Linux カーネルに組み込まれていることに注意してください!Linux カーネル自体以外は、コンテナには特別なものはありません。

コンテナを便利にするのは、それを取り囲むツールです。これらの実験では、コンテナを使ってアプリケーションを構築するために広く採用されているツールである Docker を使用します。Docker は、開発者とオペレータに対して、Docker エンジンがある任意の環境でコンテナを構築、配信、実行するためのフレンドリーなインターフェイスを提供します。Docker クライアントは Docker エンジンが必要なので、代替策として Podman を使用することもできます。Podman は、デーモンレス コンテナ エンジンであり、OCI コンテナを開発、管理、実行することができ、root としてまたは rootless モードでコンテナを実行することができます。これらの理由から、私たちは Podman を推奨しますが、採用率のため、この実験では依然として Docker を使用しています。

この実験の最初の部分では、初めてのコンテナを実行し、それを調べる方法を学びます。Linux カーネルから得られるネームスペースの孤立を目の当たりにすることができます。

最初のコンテナを実行した後、コンテナの他の使い方について深掘りします。Docker Store ではこれらの例をたくさん見つけることができますが、同じホスト上でいくつかの異なる種類のコンテナを実行します。これにより、同一ホスト上で複数のコンテナを衝突なしに実行できるという、孤立の利点を確認することができます。

この実験ではいくつかの Docker コマンドを使用します。利用可能なコマンドの完全なドキュメントについては、公式ドキュメント を参照してください。

これは Guided Lab です。学習と実践を支援するためのステップバイステップの指示を提供します。各ステップを完了し、実践的な経験を積むために、指示に注意深く従ってください。過去のデータによると、この 初級 レベルの実験の完了率は 90%です。学習者から 92% の好評価を得ています。

はじめに

LabEx VM 上でターミナルを開き、docker -h を実行すると、Docker CLI のヘルプ ページが表示されます。

$ docker -h
Flag shorthand -h has been deprecated, please use --help

Usage: docker [OPTIONS] COMMAND

A self-sufficient runtime for containers

...

Management Commands:
builder Manage builds
config Manage Docker configs
container Manage containers
engine Manage the docker engine
image Manage images
network Manage networks
node Manage Swarm nodes
plugin Manage plugins
secret Manage Docker secrets
service Manage services
stack Manage Docker stacks
swarm Manage Swarm
system Manage Docker
trust Manage trust on Docker images
volume Manage volumes

Docker コマンド ラインを使用して、Docker Engine のいくつかの機能を管理できます。この実験では、主に container コマンドに焦点を当てます。

LabEx VM 上に podman をインストールします。

sudo apt-get update
sudo apt-get install podman -y

podman がインストールされている場合、比較のために代替コマンドを実行できます。

sudo podman -h

また、docker version を使用して、Docker インストールのバージョンを確認できます。

docker version

Client:
Version: 20.10.21
...

Server:
Engine:
Version: 20.10.21
...

Docker は ClientServer: Docker Engine の両方をインストールすることに注意してください。たとえば、同じコマンドを podman に対して実行すると、CLI バージョンのみが表示されます。なぜなら、podman はデーモンレスで実行され、実行中のコンテナを作成するために OS とインターフェイスするために OCI 準拠のコンテナ ランタイム (runc、crun、runv など) に依存するからです。

sudo podman version --events-backend=none
Version: 3.4.4
API Version: 3.4.4
Go Version: go1.17.3
Built: Thu Jan 1 08:00:00 1970
OS/Arch: linux/amd64

初めてのコンテナを実行する

初めてのコンテナを実行するために、Docker CLI を使用します。

LabEx VM 上でターミナルを開きます。

コマンドを実行します。

docker container run -t ubuntu top

docker container run コマンドを使用して、top コマンドを使って ubuntu イメージでコンテナを実行します。-t フラグは、top が正常に機能するために必要な疑似 TTY を割り当てます。

$ docker container run -it ubuntu top
Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu
aafe6b5e13de: Pull complete
0a2b43a72660: Pull complete
18bdd1e546d2: Pull complete
8198342c3e05: Pull complete
f56970a44fd4: Pull complete
Digest: sha256:f3a61450ae43896c4332bda5e78b453f4a93179045f20c8181043b26b5e79028
Status: Downloaded newer image for ubuntu:latest

docker run コマンドは最初に、docker pull を行って、ubuntu イメージをホストにダウンロードします。ダウンロードが完了すると、コンテナが起動します。実行中のコンテナの出力は次のようになります。

top - 20:32:46 up 3 days, 17:40,  0 users,  load average: 0.00, 0.01, 0.00
Tasks:   1 total,   1 running,   0 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.1 sy,  0.0 ni, 99.9 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  2046768 total,   173308 free,   117248 used,  1756212 buff/cache
KiB Swap:  1048572 total,  1048572 free,        0 used.  1548356 avail Mem

PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
      1 root      20   0   36636   3072   2640 R   0.3  0.2   0:00.04 top

top は、システム上のプロセスを表示し、リソース消費に基づいて並べ替える Linux ユーティリティです。この出力には単一のプロセスのみが表示されます。それは top プロセス自体です。このリストにホストの他のプロセスは表示されません。これは PID ネームスペースの孤立のためです。

コンテナは、Linux ネームスペースを使用して、他のコンテナやホストからのシステム リソースの孤立を提供します。PID ネームスペースは、プロセス ID の孤立を提供します。コンテナ内で top を実行すると、コンテナの PID ネームスペース内のプロセスが表示されることに気付きます。これは、ホスト上で top を実行した場合とは大きく異なります。

私たちは ubuntu イメージを使用していますが、重要なことは、私たちのコンテナに独自のカーネルはありません。コンテナはホストのカーネルを使用し、ubuntu イメージは、ubuntu システム上で利用可能なファイル システムとツールを提供するためにのみ使用されます。

docker container exec でコンテナを調べる

docker container exec コマンドは、新しいプロセスで実行中のコンテナのネームスペースに「入る」方法です。

新しいターミナルを開きます。Terminal > New Terminal を選択します。

新しいターミナルで、docker container ls コマンドを使用して、先ほど作成した実行中のコンテナの ID を取得します。

$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b3ad2a23fab3 ubuntu "top" 29 minutes ago Up 29 minutes goofy_nobel

次に、その ID を使用して、docker container exec コマンドを使ってそのコンテナ内で bash を実行します。bash を使用し、ターミナルからこのコンテナと対話したいので、疑似ターミナルを割り当てながら対話型モードで実行するために -it フラグを使用します。

$ docker container exec -it ID < CONTAINER > bash
root@b3ad2a23fab3:/#

では、完成です!私たちは docker container exec コマンドを使用して、bash プロセスでコンテナのネームスペースに「入りました」。bash とともに docker container exec を使用することは、Docker コンテナを調べるための一般的なパターンです。

ターミナルの接頭辞の変化に注意してください。たとえば、root@b3ad2a23fab3:/。これは、私たちがコンテナの「中」で bash を実行していることを示しています。

: これは、別のホストや VM に ssh 接続するのと同じではありません。bash プロセスと接続するために ssh サーバーは必要ありません。コンテナは、カーネル レベルの機能を使用して孤立を実現し、コンテナはカーネルの上で実行されます。私たちのコンテナは、同じホスト上で孤立して実行されるプロセスのグループにすぎず、docker container exec を使用して、bash プロセスでその孤立状態に入ることができます。docker container exec を実行した後、孤立して実行されるプロセスのグループ(すなわち、私たちのコンテナ)には topbash が含まれます。

同じターミナルから、ps -ef を実行して実行中のプロセスを調べます。

root@b3ad2a23fab3:/## ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 20:34? 00:00:00 top
root 17 0 0 21:06? 00:00:00 bash
root 27 17 0 21:14? 00:00:00 ps -ef

top プロセス、bash プロセス、および ps プロセスのみが表示されるはずです。

比較のために、コンテナを終了し、ホスト上で ps -ef または top を実行します。これらのコマンドは、Linux または Mac で機能します。Windows の場合、実行中のプロセスを tasklist を使用して調べることができます。

root@b3ad2a23fab3:/## exit
exit
$ ps -ef
## たくさんのプロセスが表示されます!

技術的な詳細
PID は、コンテナにシステム リソースの孤立を提供する Linux ネームスペースの 1 つにすぎません。他の Linux ネームスペースには、以下が含まれます。

  • MNT - 他のネームスペースに影響を与えることなく、ディレクトリをマウントおよびアンマウントします。
  • NET - コンテナに独自のネットワーク スタックがあります。
  • IPC - メッセージ キューなどの孤立したプロセス間通信メカニズム。
  • User - システム上のユーザーの孤立したビュー。
  • UTC - 各コンテナでホスト名とドメイン名を設定します。

これらのネームスペースは一緒になって、コンテナに孤立を提供し、同じシステム上で実行される他のコンテナと安全に競合することなく一緒に実行できるようにします。次に、コンテナのさまざまな使い方と、同じホスト上で複数のコンテナを実行する際の孤立の利点を示します。

: ネームスペースは Linux カーネルの機能です。しかし、Docker を使用すると、Windows と Mac でもコンテナを実行できます... どのように機能するのでしょうか?秘密は、Docker 製品または Docker エンジンに埋め込まれている Linux サブシステムにあります。Docker はこの Linux サブシステムを新しいプロジェクトにオープンソース化しました。LinuxKit。コンテナを多くの異なるプラットフォームで実行できることは、コンテナに Docker ツールを使用する利点の 1 つです。

Windows で Linux サブシステムを使用して Linux コンテナを実行する他に、Windows OS 上のコンテナ プリミティブの作成により、ネイティブ Windows コンテナが可能になりました。ネイティブ Windows コンテナは、Windows 10 または Windows Server 2016 以降で実行できます。

: この演習をコンテナ化されたターミナルで実行し、ターミナルで ps -ef コマンドを実行した場合、exec コマンドを終了した後も、依然として限定された一連のプロセスが表示されます。ローカル マシンのターミナルで ps -ef コマンドを実行して、すべてのプロセスを表示してみることができます。

<ctrl>-c を入力して、top プロセスを実行しているコンテナをクリーンアップし、すべてのコンテナを一覧表示して、それらの ID でコンテナを削除します。

docker ps -a

docker rm <CONTAINER ID>

複数のコンテナを実行する

Docker Hub を探索する

Docker Hub は、Docker イメージの公開中央レジストリであり、コミュニティおよび公式イメージが含まれています。

イメージを検索する際には、「Docker Certified」、「Verified Publisher」、「公式イメージ」のフィルターがあります。「Docker Certified」フィルターを選択すると、エンタープライズ向けに準備され、Docker Enterprise Edition 製品でテストされたイメージが見つかります。本番環境に展開する予定の独自のイメージを作成する際には、Docker Store からの検証されていないコンテンツを使用しないようにすることが重要です。これらの検証されていないイメージには、セキュリティ上の脆弱性や、場合によっては悪意のあるソフトウェアが含まれている可能性があります。

この実験のステップ 2 では、Docker Hub からのいくつかの検証済みイメージを使用してコンテナを起動します。nginx ウェブ サーバーと mongo データベースです。

Nginx サーバーを実行する

Docker Hub からの 公式 Nginx イメージ を使用してコンテナを実行しましょう。

docker container run --detach --publish 8080:80 --name nginx nginx

ここではいくつかの新しいフラグを使用しています。--detach フラグにより、このコンテナをバックグラウンドで実行します。publish フラグにより、コンテナ内のポート 80(nginx の既定のポート)を、ホスト上のポート 8080 を介して公開します。NET ネームスペースにより、コンテナのプロセスに独自のネットワーク スタックが与えられます。--publish フラグは、コンテナを介したネットワーキングをホストに公開する機能です。

どのようにしてポート 80 が nginx の既定のポートであることを知るのでしょうか?Docker Hub の ドキュメント に記載されているからです。一般的に、検証済みイメージのドキュメントは非常に充実しており、それらのイメージを使用してコンテナを実行する際には参照することが望ましいです。

また、--name フラグを指定しています。これにより、コンテナに名前を付けることができます。すべてのコンテナには名前がありますが、指定しない場合、Docker がランダムに割り当てます。独自の名前を指定することで、コンテナの ID ではなく名前を参照することができるため、コンテナに対して後続のコマンドを実行するのが簡単になります。たとえば、docker container inspect nginx の代わりに docker container inspect 5e1 を使用できます。

これが初めて nginx コンテナを実行するため、Docker Store から nginx イメージをダウンロードします。Nginx イメージから作成される後続のコンテナは、ホスト上にある既存のイメージを使用します。

Nginx は軽量なウェブ サーバーです。LabEx VM の Web 8080 タブで nginx サーバーにアクセスできます。切り替えてページを更新すると、nginx の出力が表示されます。

step 2 nginx

mongo DB サーバーを実行する

次に、mongoDB サーバーを実行します。Docker Hub からの 公式 mongoDB イメージ を使用します。latest タグ(指定しない場合の既定値)ではなく、mongo イメージの特定のバージョン:4.4 を使用します。

docker container run --detach --publish 8081:27017 --name mongo mongo:4.4

同様に、これが初めて mongo コンテナを実行するため、Docker Store から mongo イメージをダウンロードします。--publish フラグを使用して、ホスト上の 27017 mongo ポートを公開します。ホスト マッピングに 8080 以外のポートを使用する必要があります。なぜなら、そのポートは既にホスト上で公開されているからです。再度、Docker Hub の 公式ドキュメント を参照して、mongo イメージの使用に関する詳細を取得してください。

Web ブラウザで 0.0.0.0:8081 を使用して mongoDB の出力を確認します。MongoDB からの警告メッセージが返されるはずです。

MongoDB server output warning

docker container ls で実行中のコンテナを確認します。

$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d6777df89fea nginx "nginx -g 'daemon..." Less than a second ago Up 2 seconds 0.0.0.0:8080- nginx > 80/tcp
ead80a0db505 mongo "docker-entrypoint..." 17 seconds ago Up 19 seconds 0.0.0.0:8081- mongo > 27017/tcp
af549dccd5cf ubuntu "top" 5 minutes ago Up 5 minutes priceless_kepler

ホスト上に Nginx ウェブ サーバー コンテナと MongoDB コンテナが実行されていることがわかります。これらのコンテナが互いに通信するように構成されていないことに注意してください。

コンテナに与えた「nginx」と「mongo」の名前と、ubuntu コンテナに生成されたランダムな名前(私の場合は「priceless_kepler」)が表示されます。また、--publish フラグで指定したポート マッピングも確認できます。これらの実行中のコンテナの詳細情報を取得するには、docker container inspect [コンテナ ID] コマンドを使用できます。

おそらく気付いたことですが、mongo コンテナは docker-entrypoint コマンドを実行しています。これは、コンテナが起動する際に実行される実行可能ファイルの名前です。mongo イメージは、DB プロセスを開始する前にいくつかの事前設定が必要です。github で確認することで、このスクリプトが何を行うかを正確に把握できます。通常、Docker Store ウェブサイトのイメージ説明ページから github ソースへのリンクを見つけることができます。

コンテナは独立しており、孤立しているため、異なるシステムまたはランタイムの依存関係を持つコンテナ間の潜在的な競合を回避できます。たとえば、Java 7 を使用するアプリケーションと Java 8 を使用する別のアプリケーションを同じホストに展開する場合。または、すべてが既定のリッスン ポートとしてポート 80 を持つ複数の nginx コンテナを実行する場合(--publish フラグを使用してホストに公開する場合、ホストに選択されるポートは一意である必要があります)。Linux ネームスペースのおかげで、孤立の利点が得られます。

: これらのプロセスを実行するために、ホストに何かをインストールする必要はありません(Docker 以外)!各コンテナには、コンテナ内で必要な依存関係が含まれているため、ホストに直接何かをインストールする必要はありません。

同じホスト上で複数のコンテナを実行することで、単一のホスト上で利用可能なリソース(CPU、メモリなど)を最大限に活用できます。これにより、企業にとって大幅なコスト削減が可能になります。

Docker Hub から直接イメージを実行することは時々便利ですが、カスタム イメージを作成し、公式イメージをこれらのイメージの起点として参照する方がもっと便利です。実験 2 で独自のカスタム イメージを構築する方法について詳しく見ていきましょう。

クリーンアップ

この実験を完了すると、ホスト上に多数の実行中のコンテナが残ります。これらをクリーンアップしましょう。

まず、docker container ls を使用して実行中のコンテナの一覧を取得します。

$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d6777df89fea nginx "nginx -g 'daemon..." 3 minutes ago Up 3 minutes 0.0.0.0:8080- nginx > 80/tcp
ead80a0db505 mongo "docker-entrypoint..." 3 minutes ago Up 3 minutes 0.0.0.0:8081- mongo > 27017/tcp
af549dccd5cf ubuntu "top" 8 minutes ago Up 8 minutes priceless_kepler

次に、リスト内の各コンテナに対して docker container stop [コンテナ ID] を実行します。事前に指定したコンテナの名前を使用することもできます。

$ docker container stop d67 ead af5
d67
ead
af5

: ID の一意性を保つために必要な桁数だけを参照すればよいことに注意してください。ほとんどの場合、3 桁で十分です。

停止したコンテナを削除する

docker system prune は、システムをクリーンアップするための非常に便利なコマンドです。停止したコンテナ、未使用のボリュームとネットワーク、およびダングリング イメージを削除します。

$ docker system prune
WARNING! This will remove:
- all stopped containers
- all volumes not used by at least one container
- all networks not used by at least one container
- all dangling images
Are you sure you want to continue? [y/N] y
Deleted Containers:
7872fd96ea4695795c41150a06067d605f69702dbcb9ce49492c9029f0e1b44b
60abd5ee65b1e2732ddc02b971a86e22de1c1c446dab165462a08b037ef7835c
31617fdd8e5f584c51ce182757e24a1c9620257027665c20be75aa3ab6591740

Total reclaimed space: 12B

まとめ

この実験では、初めての Ubuntu、Nginx および MongoDB コンテナを作成しました。

要点

  • コンテナは、Linux ネームスペースとコントロール グループで構成されており、他のコンテナやホストからの孤立を提供します。
  • コンテナの孤立特性のおかげで、単一のホスト上に多数のコンテナをスケジュールでき、競合する依存関係を心配する必要がありません。これにより、単一のホスト上で複数のコンテナを実行しやすくなります。そのホストに割り当てられたリソースを最大限に活用し、最終的にサーバーコストを節約できます。
  • 独自のイメージを開発する際には、Docker Store からの検証されていないコンテンツを使用しないでください。これらのイメージには、セキュリティ上の脆弱性や、場合によっては悪意のあるソフトウェアが含まれている可能性があります。
  • コンテナには、その中でプロセスを実行するために必要なすべてが含まれているため、ホストに直接追加の依存関係をインストールする必要はありません。