Docker イメージの操作

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

はじめに

この実験では、コンテナを作成して実行するための基盤となる Docker イメージについて詳しく見ていきます。Docker Hub からイメージをプル(取得)する方法、異なるバージョンのイメージを使用したコンテナの実行、イメージの一覧表示と削除、イメージレイヤーの仕組み、イメージの検索、そして基本的なイメージのタグ付け方法を学びます。このハンズオン体験を通じて、Docker イメージを効果的に扱うために不可欠なスキルを習得できます。Docker が初めての方でも、各ステップで詳細な説明を行いますので、安心して進めてください。

Docker Hub からのイメージのプル

Docker Hub は、コードにおける GitHub のような、Docker イメージの公開リポジトリです。ここでは、多くの人気のあるソフトウェアアプリケーションやオペレーティングシステムのビルド済みイメージを見つけることができます。まずは、公式の Nginx イメージをプル(ダウンロード)することから始めましょう。

システムのターミナルを開いてください。次のようなプロンプトが表示されているはずです。

labex:project/ $

では、Nginx イメージをプルしましょう。次のコマンドを入力して Enter キーを押します。

docker pull nginx

このコマンドは、Docker Hub から Nginx イメージの最新バージョン(latest)をダウンロードするように Docker に指示します。次のような出力が表示されるはずです。

Using default tag: latest
latest: Pulling from library/nginx
5040bd298390: Pull complete
d7a91cdb22f0: Pull complete
9cac4850e5df: Pull complete
Digest: sha256:33ff28a2763feccc1e1071a97960b7fef714d6e17e2d0ff573b74825d0049303
Status: Downloaded newer image for nginx:latest

ここで何が起きているのかを解説します。

  1. "Using default tag: latest" - バージョンを指定しない場合、Docker は最新バージョンを希望していると判断します。
  2. 続く数行は、Docker がイメージの異なる「レイヤー(層)」をダウンロードしている様子を示しています。各レイヤーは、ファイルシステムへの変更セットを表します。
  3. "Digest" は、この特定のバージョンのイメージに対する一意の識別子です。
  4. 最後の行は、イメージのダウンロードが正常に完了したことを示しています。

イメージをダウンロードできたので、システム上に存在するか確認しましょう。ローカルにあるすべての Docker イメージを一覧表示することで確認できます。

docker images

次のような出力が表示されるはずです。

REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
nginx         latest    605c77e624dd   2 weeks ago    141MB

この出力の意味は以下の通りです。

  • REPOSITORY: イメージの名前 (nginx)
  • TAG: イメージのバージョン (latest)
  • IMAGE ID: このイメージの一意の識別子
  • CREATED: このバージョンのイメージが作成された時期
  • SIZE: イメージが占有しているディスク容量

数値が多少異なっていても心配いりません。重要なのは nginx のエントリが表示されていることです。

システムに他にどのようなイメージがあるか気になるかもしれません。 "jenkins/jenkins" や "gcr.io/k8s-minikube/kicbase" といったエントリが見える場合がありますが、これらはプリインストールされているイメージであり、この実験では使用しません。

異なるバージョンのイメージの実行

Docker では、タグ(Tag)を使用することで、イメージの特定のバージョンを実行できます。タグは、イメージの特定のバージョンに対するエイリアス(別名)のようなものです。Python イメージを使ってこの概念を理解しましょう。

まず、最新の Python イメージをプルします。

docker pull python

Nginx をプルしたときと同様の出力が表示されます。これにより、Python の最新バージョンがダウンロードされます。

次に、特定のバージョン(例えば 3.7)の Python をプルしてみましょう。

docker pull python:3.7

python の後に :3.7 を付け加えたことに注目してください。これにより、Docker は最新版ではなく、明示的にバージョン 3.7 をプルします。

Python イメージを一覧表示して、異なるバージョンを確認してみましょう。

docker images python

次のような出力が表示されるはずです。

REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
python       3.7       1f1a7b570fbd   2 weeks ago    907MB
python       latest    98ccd1643c71   2 weeks ago    920MB

これで 2 つの Python イメージが用意されました。1 つは latest タグ(この実験を行う時期によって Python 3.9 や 3.10 などになります)、もう 1 つは 3.7 タグです。

これらの異なるバージョンを使用してコンテナを実行し、違いを確認してみましょう。

docker run --rm python:latest python --version

このコマンドはいくつかの処理を同時に行います。

  1. docker run は新しいコンテナを作成して起動します。
  2. --rm は、コンテナが終了した後に自動的に削除するように Docker に指示します。
  3. python:latest は、使用するイメージを指定します。
  4. python --version は、コンテナ内で実行するコマンドです。

出力に最新の Python バージョンが表示されるはずです。

次に、Python 3.7 でも同じことを行います。

docker run python:3.7 python --version

今回は、出力に Python 3.7.x(x は 3.7 の最新パッチバージョン)が表示されるはずです。

これらのコマンドは、異なるイメージタグを使用することで、同じソフトウェアの異なるバージョンを使い分けられることを示しています。これは、特定のバージョンの Python(または他のソフトウェア)を必要とするアプリケーションを実行する際に非常に便利です。

イメージの一覧表示と削除

Docker を使い続けると、時間の経過とともにイメージが蓄積されていきます。これらのイメージを管理する方法、つまり一覧表示する方法や、不要になったものを削除する方法を知っておくことは重要です。

まず、システム上のすべてのイメージを一覧表示してみましょう。

docker images

これまでにプルした Nginx や Python イメージを含む、すべてのイメージのリストが表示されます。

ここで、スペースを確保するために Python 3.7 イメージを削除したいとします。これには docker rmi コマンド(rmi は remove image の略)を使用します。

docker rmi python:3.7

コマンドが成功すると、次のような出力が表示されます。

Untagged: python:3.7
Untagged: python@sha256:1f93c63...
Deleted: sha256:1f1a7b57...
Deleted: sha256:8c75ecde...
...

しかし、代わりに次のようなエラーメッセージが表示されることがあります。

Error response from daemon: conflict: unable to remove repository reference "python:3.7" (must force) - container <container_id> is using its referenced image <image_id>

このエラーは、そのイメージから作成されたコンテナ(実行中または停止中)が存在する場合に発生します。Docker はシステムの整合性を保つため、使用中のイメージが削除されるのを防ぎます。

これを解決するには、まずそのイメージを使用しているコンテナを削除する必要があります。すべてのコンテナ(停止しているものを含む)を一覧表示しましょう。

docker ps -a

python:3.7 イメージから作成されたコンテナを探してください。見つかった場合は、docker rm コマンドを使用して削除します。

docker rm <container_id>

<container_id> は、削除したいコンテナの実際の ID に置き換えてください。

コンテナを削除した後、再度イメージの削除を試みます。

docker rmi python:3.7

今度は成功するはずです。

Python イメージを再度一覧表示して、イメージが削除されたことを確認しましょう。

docker images python

リストに Python 3.7 イメージが表示されなくなっているはずです。

イメージレイヤーの理解

Docker イメージは、レイヤー化されたファイルシステム(Layered Filesystem)を使用して構築されています。各レイヤーはファイルシステムへの変更セットを表します。このレイヤー化されたアプローチにより、Docker はストレージとネットワークの使用を効率化できます。この概念を探ってみましょう。

まず、先ほどプルした Nginx イメージのレイヤーを確認します。

docker inspect --format='{{.RootFS.Layers}}' nginx

次のような出力が表示されます。

[sha256:2edcec3590a4ec7f40cf0743c15d78fb39d8326bc029073b41ef9727da6c851f sha256:e379e8aedd4d72bb4c529a4ca07a4e4d230b5a1d3f7a61bc80179e8f02421ad8 sha256:b5357ce95c68acd9c9672ec76e3b2a2ff3f8f62a2bcc1866b8811572f4d409af]

これらの長い文字列(SHA256 ハッシュと呼ばれます)のそれぞれが、イメージ内のレイヤーを表しています。各レイヤーは、イメージの構築に使用された Dockerfile 内のコマンドに対応しています。

レイヤーをより深く理解するために、簡単なカスタムイメージを作成してみましょう。まず、現在のディレクトリに Dockerfile という名前の新しいファイルを作成します。

nano Dockerfile

このファイルに、以下の内容を追加します。

FROM nginx
RUN echo "Hello from custom layer" > /usr/share/nginx/html/hello.html

この Dockerfile は 2 つのことを行います。

  1. 先ほどプルした Nginx イメージをベースとして開始します (FROM nginx)。
  2. イメージに新しいファイルを追加します (RUN echo...)。

ファイルを保存して終了します(nano の場合は、Ctrl+X、次に Y、最後に Enter を押します)。

では、このイメージをビルド(構築)しましょう。

docker build -t custom-nginx .

出力例:

Sending build context to Docker daemon  2.048kB
Step 1/2 : FROM nginx
 ---> 5ef79149e0ec
Step 2/2 : RUN echo "Hello from custom layer" > /usr/share/nginx/html/hello.html
 ---> Running in 2fa43e649234
Removing intermediate container 2fa43e649234
 ---> 73b62663b5c3
Successfully built 73b62663b5c3
Successfully tagged custom-nginx:latest

このコマンドは、Dockerfile に基づいて新しいイメージをビルドし、custom-nginx というタグを付けます。末尾の . は、現在のディレクトリにある Dockerfile を探すよう Docker に指示しています。

次に、作成したカスタムイメージのレイヤーを確認してみましょう。

docker inspect --format='{{.RootFS.Layers}}' custom-nginx

このイメージには、元の Nginx イメージよりも 1 つ多くのレイヤーがあることに気づくでしょう。この追加されたレイヤーは、RUN コマンドによって行われた変更を表しています。

レイヤーの理解が重要な理由は以下の通りです。

  1. レイヤーはキャッシュされるため、類似したイメージのビルドが高速化されます。
  2. レイヤーはイメージ間で共有されるため、ディスク容量を節約できます。
  3. イメージをプッシュまたはプルする際、変更されたレイヤーのみを転送すれば済みます。

Docker Hub でのイメージ検索

Docker Hub には膨大なイメージのコレクションがホストされています。Docker Hub のウェブサイトでイメージを検索することもできますが、Docker はターミナルから直接イメージを検索するためのコマンドラインツールも提供しています。

まず、Nginx イメージを検索してみましょう。

docker search nginx

これにより、Nginx に関連するイメージのリストが返されます。出力にはいくつかの列が含まれています。

  • NAME: イメージの名前
  • DESCRIPTION: イメージの簡単な説明
  • STARS: Docker Hub でそのイメージが獲得したスターの数(人気の指標)
  • OFFICIAL: Docker によってメンテナンスされている公式イメージかどうか
  • AUTOMATED: GitHub リポジトリなどから自動的にビルドされたイメージかどうか

例えば、次のような結果が表示されます。

NAME                              DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
nginx                             Official build of Nginx.                        15763     [OK]
jwilder/nginx-proxy               Automated Nginx reverse proxy for docker c...   2088                 [OK]
...

通常、公式の Nginx イメージがリストの先頭に表示されます。

次に、特定のバージョンの Python を検索してみましょう。

docker search python:3.8

この検索は期待通りには機能しないことに気づくでしょう。docker search は特定のタグ(3.8 など)の検索をサポートしていません。代わりに、名前に "python:3.8" が含まれるイメージを検索しようとします。

特定のバージョンのイメージを見つけるには、通常以下の方法が推奨されます。

  1. 一般的なイメージ名で検索する(例:docker search python)。
  2. Docker Hub のウェブサイトにアクセスして詳細情報を確認する。
  3. docker pull でイメージをダウンロードしてから、ローカルで詳細を確認する。

docker search はイメージを素早く見つけるための便利な方法ですが、より詳細な情報が必要な場合は Docker Hub のウェブサイトの方が役立つことが多いです。

イメージの保存と読み込み

Docker では、イメージを tar ファイルとして保存し、後で読み込むことができます。これは、レジストリを使用せずにシステム間でイメージを転送したり、イメージのバックアップを作成したりする場合に便利です。

まず、Nginx イメージをファイルに保存してみましょう。

docker save nginx > nginx.tar

このコマンドは、Nginx イメージを現在のディレクトリにある nginx.tar という名前のファイルに保存します。> 記号は、docker save コマンドの出力をファイルにリダイレクトするために使用されます。

現在のディレクトリの内容を一覧表示して、ファイルが作成されたことを確認できます。

ls -lh nginx.tar

nginx.tar ファイルとそのサイズ(100MB 以上あるはずです)が表示されるはずです。

次に、イメージを持っていないシステムに転送する状況をシミュレートするために、システムから Nginx イメージを削除します。

docker rmi nginx

イメージが消えたことを確認します。

docker images nginx

結果が表示されないはずであり、これは Nginx イメージがシステムから削除されたことを示しています。

では、tar ファイルからイメージを読み込んで戻しましょう。

docker load < nginx.tar

< 記号は、nginx.tar ファイルの内容を docker load コマンドの入力としてリダイレクトするために使用されます。

読み込みが完了したら、Nginx イメージが戻っているか確認します。

docker images nginx

削除前と同じように、リストに Nginx イメージが再び表示されるはずです。

イメージの保存と読み込みのプロセスは、次のような場合に非常に役立ちます。

  • インターネット接続のないシステムにイメージを転送する
  • 特定のバージョンのイメージをバックアップする
  • レジストリを使用せずにカスタムイメージを他者と共有する

イメージのタグ付けの基本

タグ付け(Tagging)は、Docker イメージにエイリアスを作成する方法です。これは一般的に、イメージのバージョニングや整理に使用されます。イメージにタグを付ける方法を見ていきましょう。

まず、Nginx イメージに新しいタグを作成します。

docker tag nginx:latest my-nginx:v1

このコマンドは、nginx:latest と同じイメージを指す新しいタグ my-nginx:v1 を作成します。各部分の意味は以下の通りです。

  • nginx:latest は、ソース(元となる)イメージとタグです。
  • my-nginx は、新しく作成するイメージ名です。
  • v1 は、新しく割り当てるタグです。

イメージを一覧表示して、新しいタグを確認しましょう。

docker images

リストに nginx:latestmy-nginx:v1 の両方が表示されるはずです。これらが同じ「Image ID」を持っていることに注目してください。これは、これらが実際には同じイメージであり、単に異なる名前が付いているだけだからです。

この新しいタグを使用してコンテナを実行できます。

docker run -d --name my-nginx-container my-nginx:v1

このコマンドは以下のことを行います。

  • -d は、コンテナをデタッチドモード(バックグラウンド)で実行します。
  • --name my-nginx-container は、新しいコンテナに名前を付けます。
  • my-nginx:v1 は、コンテナ作成に使用するイメージとタグです。

コンテナが実行されているか確認します。

docker ps

実行中のコンテナリストに自分のコンテナが表示されるはずです。

タグ付けが便利な理由はいくつかあります。

  1. バージョン管理:イメージにバージョン番号(v1, v2 など)を付けることができます。
  2. 環境の分離:異なる環境(dev, staging, prod)ごとにイメージにタグを付けることができます。
  3. 可読性:カスタムタグを使用することで、そのイメージが何のためのものかを明確にできます。

タグは単なるエイリアスであることを忘れないでください。タグを付けても新しいイメージが作成されるわけではなく、既存のイメージを指す新しい名前が作成されるだけです。

まとめ

この実験では、Docker イメージの操作に関するさまざまな側面を学びました。習得した内容は以下の通りです。

  1. Docker Hub からのイメージのプル
  2. 異なるバージョンのイメージを使用したコンテナの実行
  3. イメージの一覧表示と削除
  4. イメージレイヤーの仕組みの理解
  5. Docker Hub でのイメージ検索
  6. イメージの保存と読み込み
  7. 基本的なイメージのタグ付け

これらのスキルは、プロジェクトで Docker イメージを効果的に管理するための基礎となります。Docker の学習を続ける中で、コンテナ化されたアプリケーションの構築やデプロイにおいて、これらの操作が不可欠であることを実感するでしょう。

Docker イメージは Docker の動作の核心です。イメージは、アプリケーションをパッケージ化して配布するための、一貫性があり、ポータブルで効率的な方法を提供します。これらのイメージ操作をマスターすることで、Docker を使いこなすための大きな一歩を踏み出しました。

引き続きこれらのコマンドを練習し、さまざまなイメージを試してみてください。Docker を使えば使うほど、より快適に、そして熟練して扱えるようになります。ハッピー・ドッカリング!