🖥️

【3-2】Docker実践入門!基本コマンドからデータ永続化・ネットワーク・連携まで

に公開

はじめに

前回はDockerの概念整理とインストールを完了し、docker run hello-worldが成功するところまで進めました。今回は日常的に使うための基本コマンド(イメージ取得、コンテナ起動・停止・削除、ログ確認、リソース監視)を実践しつつ、実運用のキモである「データの永続化(Volume)」と「コンテナ間通信(Network)」まで到達します。最後にMySQLとphpMyAdminの連携で総仕上げを行います。

1. イメージ操作: アプリの"ミールキット"を取り寄せる

まずは公式レジストリ(Docker Hub)から必要なイメージを取得し、一覧を確認します。

1.1 イメージのダウンロード(pull)

docker pullコマンドで、必要なイメージをローカルに持ってきます。

# 軽量なWebサーバーであるNginxのイメージを取得
docker pull nginx

# OSのイメージをバージョン(タグ)を指定して取得
docker pull ubuntu:22.04

# 非常に軽量なLinuxディストリビューションであるAlpineの最新版を取得
docker pull alpine:latest

1.2 イメージの一覧確認(images)

ダウンロードしたイメージはdocker imagesで確認できます。

docker images

実行結果の例:

REPOSITORY   TAG     IMAGE ID      CREATED        SIZE
nginx        latest  xxxxxxxxxxxx  2 weeks ago    142MB
ubuntu       22.04   xxxxxxxxxxxx  3 weeks ago     77.8MB
alpine       latest  xxxxxxxxxxxx  4 weeks ago      7.34MB
hello-world  latest  xxxxxxxxxxxx  5 months ago      9.14kB

Alpine Linuxの圧倒的な小ささが分かりますね。

2. コンテナのライフサイクル管理

ここからは、イメージを元にコンテナを実際に動かし、その起動から削除までを管理していきます。

2.1 バックグラウンド実行: Nginx Webサーバーの起動

Webサーバーのように裏側で動き続けてほしいアプリケーションは、-dオプションでバックグラウンド実行します。

docker run -d --name my-nginx -p 8080:80 nginx
  • -d: バックグラウンドで実行
  • --name my-nginx: 分かりやすい名前を付与
  • -p 8080:80: ホスト(例: us01)の8080番ポートからコンテナの80番へ転送

ブラウザで http://192.168.3.101:8080 にアクセスして確認してみます。

【実践トラブル①】ERR_SSL_PROTOCOL_ERRORで繋がらない?

ここで早速トラブル発生。ブラウザに「このサイトは安全に接続できません」というエラーが表示されてしまいました。

エラーコードはERR_SSL_PROTOCOL_ERROR。これは、ブラウザが暗号化されたHTTPS通信を試みている証拠です。しかし、私たちが起動したNginxコンテナは、暗号化されていないHTTP通信で待ち受けています。

これは、ブラウザがURLを自動的にhttps://に書き換えてしまったことが原因でした。
解決策として、ブラウザのプライベートウィンドウ(シークレットモード)を開き、改めてhttp://192.168.3.101:8080と手入力することで、無事にNginxの歓迎ページが表示されました。単純なミスですが、非常に良い学びとなりました。

2.2 対話モード実行: コンテナの中に入る

次に、コンテナの中に入って直接コマンドを操作してみます。-itオプションを使います。

docker run -it --name my-ubuntu ubuntu:22.04 /bin/bash
【実践トラブル②】コンテナ名が既に使用されている?

Conflict. The container name "/my-ubuntu" is already in use...と表示された場合、以前のコンテナが「停止」状態で残っている可能性があります。

解決手順:

  1. docker ps -aで停止中も含め一覧確認
  2. docker rm my-ubuntuで古いコンテナを削除
  3. docker run -it ...を再実行

「停止」と「削除」は別操作である点を理解できました。

プロンプトがroot@xxxxxxxxxxxx:/#に変われば成功です。lscat /etc/os-releaseを試し、exitで抜けます。

2.3 状態確認・ログ・制御(ps, logs, stop/start)

コンテナの状態を確認し、制御する方法を学びます。

# 実行中のコンテナを確認
docker ps

# 停止中のコンテナも含めて確認
docker ps -a

# my-nginxのアクセスログを確認
docker logs my-nginx

# my-nginxを停止
docker stop my-nginx

# 停止したmy-nginxを再開
docker start my-nginx

2.4 後片付け(rm, rmi)

不要になったコンテナとイメージを削除します。

# 停止しているmy-ubuntuコンテナを削除
docker rm my-ubuntu

# ubuntu:22.04イメージを削除
docker rmi ubuntu:22.04

注意: 実行中もしくは依存コンテナがあるイメージは削除できません。先にコンテナをrmしましょう。

2.5 リソース監視(stats)

最後に、実行中のコンテナがどれくらいリソースを使っているか見てみましょう。

docker stats

CPUやメモリ使用状況をリアルタイム表示します。Ctrl+Cで終了します。

3. データの永続化: Docker Volumeを使いこなす

コンテナは本来、破棄と作成を繰り返す「使い捨て」の思想で作られています(これをImmutableと言います)。しかし、データベースのデータやユーザーがアップロードしたファイルなど、消えては困るデータはどうすればよいのでしょうか。その答えが「ボリューム」です。

ボリュームは、Dockerが管理する、コンテナとは独立した専用のデータ保管領域です。

3.1 ボリュームの作成とマウント

まずはボリュームを作成し、コンテナに接続(マウント)してみましょう。

# "my-data"という名前のボリュームを作成
docker volume create my-data

# ボリュームをコンテナ内の/dataディレクトリに接続して起動
docker run -it --name data-test -v my-data:/data ubuntu:22.04
  • -v my-data:/data: 「my-dataボリュームをコンテナの/dataへマウント」という意味。/dataへのI/Oはホスト側のmy-dataへ保存されます。

3.2 データが消えないことを確認

コンテナ内でテストファイルを作成し、コンテナを削除してもデータが残ることを確認します。

# コンテナ内でファイルを作成
root@xxxxxxxx:/# echo "persistent data" > /data/test.txt
root@xxxxxxxx:/# exit

# コンテナを削除
adm-labuser@us01:~$ docker rm data-test

# 別の新しいコンテナを、同じボリュームに接続して起動
adm-labuser@us01:~$ docker run -it --name data-test2 -v my-data:/data ubuntu:22.04

# 新しいコンテナ内でファイルが残っているか確認
root@yyyyyyyy:/# cat /data/test.txt
persistent data

persistent dataと表示されました!コンテナを削除してもボリューム内のデータは残ります。実運用で必須の機能です。

4. コンテナ間の通信: Docker Networkで連携する

実際のアプリケーションは、Webサーバー、APサーバー、DBサーバーのように、複数のコンテナが連携して動作します。これらのコンテナ同士が安全に通信するために、Dockerは専用の仮想ネットワークを作成する機能を提供しています。

4.1 ネットワーク作成とコンテナ接続

# "my-network"という名前のネットワークを作成
docker network create my-network

# 2つのNginxコンテナを同じネットワークに接続して起動
docker run -d --name web1 --network my-network nginx
docker run -d --name web2 --network my-network nginx

# web1からweb2へ"名前"で疎通確認
docker exec web1 ping web2

docker execは実行中コンテナ内でコマンドを実行する命令です。このpingコマンドで、またしても学びの深いトラブルに遭遇しました。

【実践トラブル③】ping: command not found?

pingを実行するとexecutable file not foundというエラーが出ました。ネットワークの問題ではなく、Nginxコンテナの中にpingコマンド自体が存在しないのが原因でした。

これは、Dockerの公式イメージが 「軽量性」と「安全性」 のために、アプリケーションの実行に不要なツールを意図的に削ぎ落として作られているためです。汎用的なUbuntuイメージとは思想が違うのです。

解決策:
docker exec -it web1 /bin/bashでコンテナの中に入り、apt-get update && apt-get install -y iputils-pingを実行して、手動でpingコマンドをインストールしました。(apt-getを使ったのは、最小構成のイメージとの互換性を考慮してのことです。)
これにより、無事にweb2への疎通を確認できました。「Dockerイメージは最小構成である」という重要な原則を学ぶ良い機会となりました。

5. 実用例: MySQLとphpMyAdminの連携

最後に、学んだ知識の集大成として、データベース(MySQL)と管理ツール(phpMyAdmin)の2つのコンテナを連携させます。

# MySQLコンテナを起動。-eで初期パスワードを設定
docker run -d --name my-mysql -e MYSQL_ROOT_PASSWORD=password mysql:8.0

# phpMyAdminコンテナを起動し、MySQLコンテナにリンク。ポートを8081に公開
docker run -d --name my-phpmyadmin --link my-mysql:db -p 8081:80 phpmyadmin/phpmyadmin
  • -e: コンテナへ環境変数を渡す(ここではMySQLのrootパスワード)
  • --link my-mysql:db: phpMyAdmin側からdbというホスト名でmy-mysqlへ接続可能
    • 注: --linkは古い機能。実務では前述のdocker networkで同一ネットワークに接続し、ホスト名解決する方法が推奨

ブラウザでhttp://192.168.3.101:8081にアクセスし、サーバーdb、ユーザーroot、パスワードpasswordでログインできれば成功です!

まとめ

これでコンテナを自由に操作する土台は整いました。しかし、毎回長大なdocker runコマンドをいくつも手で打つのは現実的ではありません。

次回は、複数コンテナの構成をYAMLで一元管理できるDocker Composeを扱い、手入力のdocker run地獄から脱却します。記事の中で定義、依存関係、環境変数、ボリューム/ネットワークの宣言的管理まで段階的に実践していきます!

Discussion