【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...と表示された場合、以前のコンテナが「停止」状態で残っている可能性があります。
解決手順:
-
docker ps -aで停止中も含め一覧確認 -
docker rm my-ubuntuで古いコンテナを削除 -
docker run -it ...を再実行
「停止」と「削除」は別操作である点を理解できました。
プロンプトがroot@xxxxxxxxxxxx:/#に変われば成功です。lsやcat /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