はじめに
この実験では、docker-compose.yamlファイルで定義されたサービスイメージをレジストリにプッシュするためにdocker compose pushコマンドを使用する方法を学びます。まず、サービスイメージを含むdocker-compose.yamlファイルを準備し、これらのイメージをビルドします。最後に、これらのサービスイメージをレジストリにプッシュする練習を行い、プッシュプロセス中に発生する可能性のある障害への対処方法も学びます。
サービスイメージを含む docker-compose.yaml ファイルの準備
このステップでは、マルチコンテナ Docker アプリケーションを定義・管理するためのdocker-compose.yamlファイルを作成する方法を学びます。Docker Compose は、マルチコンテナ Docker アプリケーションを定義・実行するためのツールです。Compose では YAML ファイルを使用してアプリケーションのサービスを設定し、単一のコマンドで設定からすべてのサービスを作成・起動できます。
まず、プロジェクトディレクトリに移動します:
cd ~/project
次に、nanoエディタを使用してdocker-compose.yamlファイルを作成します。このファイルには web サービスと db サービスの 2 つのサービスを定義します。
nano docker-compose.yaml
以下の内容をdocker-compose.yamlファイルに貼り付けます:
version: "3.8"
services:
web:
image: nginx:latest
ports:
- "80:80"
db:
image: postgres:latest
environment:
POSTGRES_PASSWORD: mysecretpassword
このファイルの内容を解説します:
version: '3.8'- Docker Compose ファイルフォーマットのバージョンを指定services:- アプリケーションを構成する様々なサービスを定義web:-webという名前のサービスを定義image: nginx:latest-webサービスがnginx:latestDocker イメージを使用することを指定(ローカルにない場合、Docker Hub から取得)ports:- ホストマシンのポート 80 をコンテナのポート 80 にマッピングdb:-dbという名前のサービスを定義image: postgres:latest-dbサービスがpostgres:latestDocker イメージを使用することを指定environment:- コンテナ内の環境変数を設定(ここでは PostgreSQL データベースのPOSTGRES_PASSWORDを設定)
Ctrl + X、次にY、そしてEnterを押してファイルを保存します。
作成したファイルの内容はcatコマンドで確認できます:
cat docker-compose.yaml
このコマンドは作成したdocker-compose.yamlファイルの内容を表示し、内容を確認することができます。
サービスイメージのビルド
前のステップでは、docker-compose.yamlファイルで既存の Docker イメージを使用してサービスを定義しました。このステップでは、Dockerfile を使用してサービスのカスタム Docker イメージをビルドし、docker-compose.yamlファイルに統合する方法を学びます。
まず、web サービスのためのシンプルなディレクトリとその中に Dockerfile を作成します。まだプロジェクトディレクトリにいない場合は移動します:
cd ~/project
webという名前のディレクトリを作成し、その中に移動します:
mkdir web
cd web
次に、webディレクトリ内にDockerfileという名前の Dockerfile をnanoエディタで作成します:
nano Dockerfile
以下の内容をDockerfileに貼り付けます:
FROM ubuntu:latest
RUN apt-get update && apt-get install -y nginx
COPY index.html /var/www/html/
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
この Dockerfile は以下の処理を行います:
FROM ubuntu:latest: 最新の Ubuntu ベースイメージから開始RUN apt-get update && apt-get install -y nginx: パッケージリストを更新し Nginx をインストールCOPY index.html /var/www/html/:index.htmlファイル (後で作成) を Nginx の Web ルートディレクトリにコピーEXPOSE 80: コンテナのポート 80 を公開CMD ["nginx", "-g", "daemon off;"]: コンテナ起動時に実行するコマンドを指定 (Nginx をフォアグラウンドで起動)
Ctrl + X、次にY、そしてEnterを押して Dockerfile を保存します。
次に、Dockerfile がコピーするindex.htmlファイルを作成します。~/project/webディレクトリに留まり、ファイルを作成します:
nano index.html
以下のシンプルな HTML コンテンツをindex.htmlに貼り付けます:
<!doctype html>
<html>
<head>
<title>Hello from Docker!</title>
</head>
<body>
<h1>Welcome to my Dockerized Nginx!</h1>
<p>This page is served from a custom Docker image.</p>
</body>
</html>
Ctrl + X、次にY、そしてEnterを押してindex.htmlファイルを保存します。
次に、docker-compose.yamlファイルがあるプロジェクトのルートディレクトリに戻ります:
cd ~/project
docker-compose.yamlファイルを修正して、webサービスを事前ビルドされたイメージではなく、作成した Dockerfile からビルドするようにします。docker-compose.yamlファイルを編集用に開きます:
nano docker-compose.yaml
webサービスの定義を、imageではなくbuild命令を使用するように変更します:
version: "3.8"
services:
web:
build: ./web
ports:
- "80:80"
db:
image: postgres:latest
environment:
POSTGRES_PASSWORD: mysecretpassword
ここで、build: ./webは Docker Compose に、docker-compose.yamlファイルからの相対パス./webにある Dockerfile を使用してwebサービスのイメージをビルドするように指示します。
Ctrl + X、次にY、そしてEnterを押して修正したdocker-compose.yamlファイルを保存します。
これで、docker-compose buildコマンドを使用してdocker-compose.yamlファイルで定義されたイメージをビルドできます。Docker Compose が事前にインストールされていないため、まずインストールする必要があります。
sudo apt-get update
sudo apt-get install docker-compose-plugin -y
Docker Compose プラグインをインストールした後、docker composeコマンド (新しいバージョンではハイフンではなくスペース) を使用できます。
docker compose build
このコマンドはdocker-compose.yamlファイルを読み込み、./webディレクトリ内のDockerfileに基づいてwebサービスのイメージをビルドします。また、dbサービスのためにpostgres:latestイメージがまだ存在しない場合は取得します。webイメージのビルドプロセスを示す出力が表示されます。
ビルドが完了したら、システム上の Docker イメージをリスト表示して、新しくビルドされたイメージを確認できます。
docker images
プロジェクトディレクトリとサービス名に関連した名前のイメージ (例:project-web) とpostgresイメージが表示されるはずです。
レジストリへのサービスイメージのプッシュ
前のステップでは、web サービスのカスタム Docker イメージをビルドしました。ここでは、これらのイメージを Docker レジストリにプッシュする方法を学びます。Docker レジストリは Docker イメージの保存・配布システムです。Docker Hub はパブリックレジストリで、プライベートレジストリも運用可能です。イメージをレジストリにプッシュすることで、他のユーザーと共有したり、異なるマシンにデプロイしたりできます。
プッシュする前に通常、イメージにレジストリアドレス、ユーザー名、イメージ名を含むタグを付与します。この実験では簡略化のため、ローカルレジストリや認証不要のレジストリへのプッシュをシミュレートします。実際の環境ではまずdocker loginでレジストリにログインします。
まず、web サービス用にビルドしたイメージを確認するため、イメージ一覧を表示します。まだプロジェクトディレクトリにいない場合は移動します:
cd ~/project
Docker イメージを一覧表示:
docker images
project-webのような名前のイメージが表示されるはずです。正確な名前はプロジェクトディレクトリ名によって若干異なる場合があります。
次に、project-webイメージにタグを付け、レジストリにプッシュできるようにします。仮想のレジストリアドレスyour-registry.example.comを使用します。実際のレジストリにプッシュする場合はこのアドレスを実際のものに置き換えてください。この演習ではローカルレジストリをシミュレートするためlocalhost:5000を使用します。
docker tag project-web localhost:5000/my-web-app:latest
このコマンドはproject-webイメージにlocalhost:5000/my-web-app:latestという名前のタグを付けます。localhost:5000はレジストリアドレス、my-web-appはリポジトリ名、latestはタグです。
再度イメージを一覧表示して新しいタグを確認できます:
docker images
これでproject-webイメージが元のタグとlocalhost:5000/my-web-app:latestの 2 つのタグで表示されるはずです。
次に、タグ付けしたイメージをシミュレートしたローカルレジストリにプッシュします。
docker push localhost:5000/my-web-app:latest
実際には実行されていないローカルレジストリをシミュレートしているため、このコマンドは接続エラーで失敗する可能性が高いです。これはdocker pushコマンド自体に焦点を当てているため、このステップでは想定通りです。次のステップでこのような失敗への対処方法を学びます。
実際にレジストリが動作している環境では、このコマンドでイメージレイヤーがレジストリにアップロードされます。
失敗を無視してサービスイメージをプッシュ
前のステップでは、カスタム Web サービスイメージをシミュレートされたレジストリにプッシュしようとしましたが、レジストリが実行されていなかったため失敗した可能性があります。一部のシナリオでは、複数のイメージをプッシュしようとし、1 つのプッシュが失敗しても続行したい場合があります。これは自動化スクリプトや複数のレジストリにプッシュする場合に便利です。
Docker Compose はdocker-compose.yamlファイルで定義されたすべてのサービスイメージをプッシュする方法を提供します。デフォルトでは、1 つのイメージのプッシュが失敗するとコマンド全体が停止します。しかし、docker compose pushコマンドで--ignore-pull-failuresフラグを使用できます。名前はプル失敗の無視を示唆していますが、docker compose pushのコンテキストでは、Compose のバージョンと状況に応じてプッシュ失敗の処理方法にも影響します。スクリプトで個々のプッシュ失敗を処理するより直接的な方法は、サービスを反復処理して各プッシュを試行し、各プッシュのエラーを処理することです。
まず、docker-compose.yamlファイルで定義されたサービスを一覧表示しましょう。まだプロジェクトディレクトリにいない場合は移動します:
cd ~/project
docker-compose.yamlファイルでサービス名 (webとdb) を確認できます。
cat docker-compose.yaml
次に、docker-compose.yamlファイルで定義されたすべてのサービスをプッシュしてみましょう。dbサービスは Docker Hub のpostgres:latestイメージを使用し、webサービスはローカルでビルドされlocalhost:5000用にタグ付けされています。
docker compose push
このコマンドはwebイメージ (localhost:5000へ) とpostgresイメージ (Docker Hub へ) の両方をプッシュしようとします。localhost:5000へのプッシュは以前と同様に失敗する可能性が高いです。postgresの Docker Hub へのプッシュは、インターネットに接続されており、プッシュ先のレジストリにイメージがまだ存在しない場合に成功する可能性があります (ただし通常、postgresのような公式イメージを自身のレジストリにプッシュすることはありません)。コマンドはlocalhost:5000に接続できないため失敗を報告する可能性が高いです。
失敗を無視する方法を示すために、複数のサービスがあり、1 つが失敗しても続行したいシナリオを考えてみましょう。docker compose pushには、プル失敗を処理する方法と同様に、すべてのサービスのプッシュ失敗を一度に無視する直接的なフラグはありませんが、スクリプトでサービスを反復処理して各プッシュを試行することで同様の動作を実現できます。
例えば、各サービスを個別にプッシュしようとし、エラーが発生しても続行するスクリプトを作成できます。しかし、この実験の目的とプッシュ操作中の潜在的な失敗を処理する概念を示すために、ターゲットレジストリに到達できない場合の失敗を強調するdocker compose pushコマンドの結果に焦点を当てます。
ここでの重要なポイントは、イメージのプッシュが CI/CD パイプラインの重要なステップであり、(ネットワーク問題や認証問題などの) 潜在的な失敗を処理することが重要であることを理解することです。docker compose pushはデフォルトで最初のエラーで停止するかもしれませんが、スクリプトやより高度なシナリオでは、個々のプッシュ結果を処理するロジックを実装します。
docker compose pushコマンドが実行されたことを確認しましょう。
grep "docker compose push" ~/.zsh_history
これにより、Docker Compose を使用してイメージをプッシュしようとしたことが確認できます。コマンド自体の出力にはwebサービスのプッシュ失敗が表示されます。
まとめ
この実験では、マルチコンテナ Docker アプリケーションを定義するdocker-compose.yamlファイルの作成方法を学びました。具体的には、Web サーバー(nginx) やデータベース (PostgreSQL) などのサービスを、それぞれのイメージ、ポート、環境変数と共に設定しました。その後、docker-compose.yamlファイルの定義に基づいてこれらのサービスイメージをビルドする練習を行いました。
さらに、docker compose pushコマンドを使用してビルドしたサービスイメージを Docker レジストリにプッシュする方法を学びました。また、--ignore-push-failuresフラグを使用することで、一部のイメージのアップロードが失敗した場合でもプッシュ操作を継続する方法についても学習しました。



