この記事にはアフィリエイト広告が含まれています。
冒頭まとめ
Dockerのエラーを検索して1件ずつ直しているのに、次の日には別のエラーで止まる。この繰り返しから抜けるには、覚える順序を変える必要があります。
Dockerのエラーの多くは、4つの境界のどこかで起きています。ホストとコンテナの境界、イメージとコンテナの境界、コンテナ間の境界、そして書き込み可能レイヤーと永続領域の境界です。エラー文はこの境界のどれで止まったかを示していますが、境界の存在を知らないと文言が読めません。
したがって学ぶ順序は、コマンドの数ではなく境界の数で決まります。この記事では、コンテナとイメージ、Dockerfileとビルド、ポートとネットワーク、ボリューム、Compose、ログとトラブルシューティングの6段階に分けて示します。
各段階には「次へ進む目安」を置きました。目安を満たさないまま先へ進むと、後の段階のエラーが前の段階の理解不足として現れます。急がずに順に進めてください。
エラーを個別に直すだけでは理解しにくい理由
検索で見つかる対処は、多くの場合その環境で有効だった手順です。なぜ有効だったかは書かれていないことがあります。
たとえば docker compose down -v を実行すれば起動時のエラーが消える、という手順があったとします。これはボリュームを削除して初期化し直す操作なので、確かにエラーは消えます。しかし同時にデータも消えます。ボリュームが何であるかを知らないまま実行すると、次は「データが消えた」という別の問題に変わります。
同じことがポートの公開でも起きます。-p 8080:80 を -p 80:80 に変えたら繋がった、という手順は、どちらの数字がホスト側でどちらがコンテナ側かを知らなければ再現できません。
エラー文そのものも同じです。Dockerのエラーは、どの部品が返したのかを示しています。CLIが返したのか、デーモンが返したのか、コンテナの中のプロセスが返したのかで、直す場所が変わります。この区別は、次に説明する全体像を知っていれば読み取れます。
最初に理解するべきDockerの全体像
先に部品の関係を押さえます。ここを飛ばすと、後のすべての段階で判断がぶれます。
Dockerはクライアントとサーバーに分かれています。公式ドキュメントによれば、docker コマンドがDockerクライアントで、利用者が最もよく使う操作の入口です。実際の作業はDockerデーモン(dockerd)が行い、イメージ、コンテナ、ネットワーク、ボリュームといったオブジェクトを管理します。両者はREST APIを使い、UNIXソケットまたはネットワークインターフェース経由で通信します。クライアントとデーモンは同じマシンで動かすことも、別のマシンに置くこともできます(Docker overview)。
この構造から、エラーの読み分けが1つ決まります。Cannot connect to the Docker daemon のような文言は、クライアントがデーモンへ届いていないという意味です。コンテナの設定を見直しても変わりません。逆に、コンテナの中のアプリケーションが出したエラーは、Dockerの設定ではなくアプリケーションの問題です。
もう1つの軸がイメージとコンテナの関係です。イメージは読み取り専用の層の集まりで、コンテナはその上に書き込み可能な層を1つ載せて動かしたものです。公式ドキュメントは、コンテナの中で作られたファイルは既定でこの書き込み可能なコンテナレイヤーに保存され、そのレイヤーはコンテナごとに固有だと説明しています(Data persistence overview)。
この2つの軸、つまりクライアントとデーモンの関係、イメージとコンテナの関係が、以降のすべての段階の土台になります。
まずは手元の環境が動いているかを確認してください。
docker version
出力はクライアント側とサーバー側に分かれます。サーバー側が表示されなければ、デーモンへ届いていません。この時点で次へ進んでも、以降のコマンドはすべて失敗します。
学習ステップ1:コンテナとイメージ
何を理解する段階か:イメージが設計図、コンテナがそれを動かした実体であること、そして両者が別々に管理されていることです。
なぜエラー解決に必要か:「イメージを更新したのに反映されない」という状況は、古いコンテナが動き続けているだけであることが多くあります。イメージとコンテナが別物だと分かっていないと、この判断ができません。
最低限覚える概念:イメージ、コンテナ、コンテナの状態(作成済み、実行中、停止)、そして名前とIDの関係です。
実際に試すコマンド:
# 手元にあるイメージを一覧する
docker images
# イメージからコンテナを作って起動する
docker run -d --name web nginx
# 実行中のコンテナを一覧する
docker ps
# 停止中を含めて一覧する(-a を付けないと停止中は見えない)
docker ps -a
# コンテナの詳細な設定を確認する
docker inspect web
# 実行中のコンテナの中でコマンドを実行する
docker exec -it web sh
docker ps と docker ps -a の差は重要です。既定では実行中のものしか表示されません。停止したコンテナは見えないまま残り続け、名前を占有します。
次の段階へ進む目安:docker ps -a の出力を見て、どれが実行中でどれが停止中かを説明できること。docker inspect の出力から、そのコンテナが使っているイメージ名を取り出せることです。
関連して発生しやすいエラー:The container name "/web" is already in use by container "..." は、停止したコンテナが名前を握っている状態です。No such container は、指定した名前やIDのコンテナが存在しない状態を指します。
学習ステップ2:Dockerfileとビルド
何を理解する段階か:イメージがどう作られるか、そして層として積み上がることです。
なぜエラー解決に必要か:ビルド時のエラーと実行時のエラーは別物です。この区別ができないと、docker run で直すべきものを Dockerfile で直そうとしたり、その逆をしたりします。
最低限覚える概念:Dockerfile の各命令が層を作ること、ビルド文脈(送られるファイルの範囲)、そしてキャッシュが効く条件です。
実際に試すコマンド:
# カレントディレクトリの Dockerfile からイメージを作る
docker build -t myapp:dev .
# 作られたイメージを確認する
docker images myapp
# キャッシュを使わずに作り直す(原因の切り分けに使う)
docker build --no-cache -t myapp:dev .
末尾の . はビルド文脈の指定です。ここで指定した範囲の外にあるファイルは COPY できません。「ファイルがあるのにコピーできない」という詰まりは、ここが原因のことがあります。
次の段階へ進む目安:Dockerfile を1行変えたときに、どこから作り直されるかを説明できることです。
関連して発生しやすいエラー:failed to solve で始まる文言はビルドの失敗です。no such file or directory がビルド中に出た場合は、ビルド文脈の外を参照しています。
学習ステップ3:ポートとネットワーク
何を理解する段階か:3種類のポートと、localhost が指す先が実行場所によって変わることです。
なぜエラー解決に必要か:「繋がらない」という症状は、この段階の理解不足で起きるものが最も多くなります。
最低限覚える概念:
第一に、コンテナ内部のポートです。コンテナの中で動くプロセスが待ち受けている番号で、コンテナの外からは直接見えません。
第二に、ホストへ公開するポートです。公式ドキュメントによれば、--publish または -p フラグは、コンテナのポートをDockerホストのポートへ対応付ける規則をホスト側に作ります。-p 8080:80 はホストの8080番をコンテナの80番へ対応付けるという意味で、左がホスト、右がコンテナです(Publishing and exposing ports)。同じページには -p 192.168.1.100:8080:80 のように、ホスト側の待ち受けアドレスを限定できることも記載されています。
第三に、Compose内のサービス間通信です。これは次の段階で扱います。
そして localhost の意味です。コンテナの中で localhost と書けば、そのコンテナ自身を指します。ホストで動くデータベースには届きません。逆にホストのブラウザで localhost:8080 と入力すれば、ホストの8080番を指し、公開設定があればコンテナへ転送されます。同じ文字列が、書いた場所によって別のものを指します。
実際に試すコマンド:
# ポートを公開してコンテナを起動する(左がホスト、右がコンテナ)
docker run -d --name web -p 8080:80 nginx
# 公開状況を確認する
docker ps --format '{{.Names}}\t{{.Ports}}'
# Docker が管理しているネットワークを一覧する
docker network ls
# コンテナがどのネットワークに属しているかを確認する
docker inspect web --format '{{json .NetworkSettings.Networks}}'
次の段階へ進む目安:コンテナの中の設定ファイルに書く接続先と、ホストのブラウザに入力する接続先が違う理由を説明できることです。
関連して発生しやすいエラー:port is already allocated はホスト側の番号が別のプロセスに使われている状態です。connection refused は、届いた先で誰も待ち受けていない状態を指します。
学習ステップ4:ボリュームとデータ永続化
何を理解する段階か:コンテナを削除すると消えるデータと、残るデータの違いです。
なぜエラー解決に必要か:この区別を知らないまま「作り直せば直る」という対処を続けると、いずれデータを失います。
最低限覚える概念:既定ではコンテナ内で作られたファイルは書き込み可能なコンテナレイヤーに保存され、そのレイヤーはコンテナごとに固有です。公式ドキュメントは、このレイヤーからデータをホストや別のコンテナへ取り出すのは容易ではないとも述べています(Data persistence overview)。
これに対してボリュームは、Dockerが作成して管理する永続的なデータ保存先です。ボリュームを作るとDockerホスト上のディレクトリに保存され、それがコンテナへマウントされます(Volumes)。コンテナとは別に管理されるため、コンテナを削除してもボリュームは残ります。
つまり、残したいデータはボリュームに置き、消えてよい一時ファイルだけをコンテナレイヤーに置く、という設計になります。
実際に試すコマンド:
# ボリュームを一覧する
docker volume ls
# ボリュームをマウントしてコンテナを起動する
docker run -d --name db -v pgdata:/var/lib/postgresql/data postgres:16
# コンテナを削除してもボリュームが残ることを確認する
docker rm -f db
docker volume ls
# ボリュームの保存場所などを確認する
docker volume inspect pgdata
docker volume rm や docker compose down -v は、この永続領域を削除する操作です。実行前に、そのボリュームに何が入っているかを docker volume inspect と実際のディレクトリで確認してください。docker system prune -a も同様で、内容を確認せずに実行すると、必要なイメージやネットワークまで消えます。
次の段階へ進む目安:コンテナを削除して作り直したときに、どのデータが残りどのデータが消えるかを、実際に手を動かして確認できることです。
関連して発生しやすいエラー:「再起動したらデータが消えた」という症状は、エラーとしては出ません。ボリュームを使っていなかっただけです。逆に「古い設定が残っている」という症状は、消したつもりのボリュームが残っていることがあります。
学習ステップ5:Docker Compose
何を理解する段階か:Composeが長いコマンドの短縮ではなく、複数コンテナの構成を宣言する仕組みであることです。
なぜエラー解決に必要か:Composeを使い始めると、ネットワークとボリュームが自動で作られます。何が自動で作られているかを知らないと、前の2段階で覚えたことが使えません。
最低限覚える概念:compose.yaml は、どのサービスをどう組み合わせるかを書いたものです。Composeはこれを読んで、必要なネットワーク、ボリューム、コンテナを作ります。
サービス間通信の仕組みは押さえておいてください。公式ドキュメントによれば、Composeは既定でアプリケーション用のネットワークを1つ作り、各サービスのコンテナをそこへ参加させます。ネットワーク名は <プロジェクト名>_default で、各サービスは自分の名前を内部のDNSサーバーへ登録するため、コンテナ同士はサービス名で直接到達できます。IPアドレスの指定や手動の設定は不要です(Networking in Compose)。
同じページには、web と db という2つのサービスがある場合、web は postgres://db:5432 でデータベースへ接続でき、ホストからは公開設定に応じて postgres://localhost:8001 でアクセスできる、という例が示されています。ここが前段階の localhost の話と繋がります。コンテナ間はサービス名、ホストからは公開したポートです。
さらに、コンテナのIPアドレスはネットワークのサブネットから起動のたびに動的に割り当てられ、再起動や再作成をまたいで保持されないため、IPではなく名前で参照するように、とも書かれています。
プロジェクト名は既定でディレクトリ名から取られます。別の場所にある同名のディレクトリで作業すると、同じプロジェクトとして扱われます。--project-name フラグまたは COMPOSE_PROJECT_NAME 環境変数で上書きできます。
実際に試すコマンド:
# 構成を起動する(-d はバックグラウンド実行)
docker compose up -d
# 解釈後の構成を確認する(変数展開後の内容が見える)
docker compose config
# 構成に含まれるコンテナの状態を確認する
docker compose ps
# 停止して、作られたコンテナとネットワークを削除する
docker compose down
docker compose down は既定でボリュームを削除しません。削除するには -v を付けます。この違いは前段階の内容と直結します。
次の段階へ進む目安:compose.yaml を読んで、起動後に何個のコンテナと何個のネットワークが作られるかを、実行前に言えることです。
関連して発生しやすいエラー:Conflict. The container name ... is already in use は、同じプロジェクト名の古いコンテナが残っている場合に起きます。サービス間の接続で could not translate host name のような名前解決の失敗が出る場合は、接続先にサービス名ではなく localhost を書いている可能性があります。
学習ステップ6:ログ確認とトラブルシューティング
何を理解する段階か:エラーが出たときに、どの順番で何を見るかです。
なぜエラー解決に必要か:ここまでの5段階は、この順序を実行するための前提知識です。順序が決まっていれば、初めて見るエラーでも調べる範囲を絞れます。
確認の順序:
第一に、実行したコマンドそのものを確認します。打ち間違い、ディレクトリの取り違え、オプションの位置の誤りは、この時点で見つかります。
第二に、表示されたエラー全文を読みます。要約された1行だけでなく、その下の行まで含めてです。Dockerのエラーは、どの部品が返したかを示す情報を含んでいます。
第三に、対象コンテナの状態を確認します。実行中なのか、停止しているのか、そもそも作られていないのかで、次に見る場所が変わります。
docker ps -a
docker inspect <コンテナ名> --format '{{.State.Status}} {{.State.ExitCode}}'
第四に、ログを見ます。コンテナの中のプロセスが出力した内容はここに集まります。
# 直近の100行を表示する
docker logs --tail 100 <コンテナ名>
# 時刻を付けて追従表示する
docker logs -f -t <コンテナ名>
第五に、ポート、ネットワーク、ボリュームを確認します。ここまでで原因が分からない場合、接続経路か保存先に問題があります。
docker ps --format '{{.Names}}\t{{.Ports}}'
docker network ls
docker volume ls
第六に、Dockerデーモン側の状態を確認します。個別のコンテナではなく、Docker自体が正常かどうかを見ます。
docker info
docker version
docker version でサーバー側が表示されない場合、ここまでの確認は意味を持ちません。デーモンへの接続から見直してください。
次の段階へ進む目安:初めて見るエラーに対して、この6段階のどこから調べるかを即座に決められることです。
避けるべき対処:権限のエラーに対して chmod 777 を当てる、Dockerソケットへ無制限の権限を与える、docker system prune -a を内容の確認なしに実行する、ファイアウォールを無効にする、本番環境でポートを無条件に全公開する、といった手順は、症状を消しても原因を残します。特に後ろの3つは、失ったデータや開いた経路を後から戻せません。
独学と動画講座の使い分け
ここまでの6段階は、公式ドキュメントと手元の環境だけでも進められます。実際、この記事で参照した仕様はすべて公式ドキュメントに書かれています。
独学が向いているのは、目的が明確な場合です。特定のエラーを直す、特定の機能の仕様を確認する、といった作業は、公式ドキュメントを直接読むのが最短です。
一方で、独学では順序を組み立てる部分が自分の負担になります。何を先に学ぶべきか、どこまで理解したら次へ進んでよいかを、自分で判断し続ける必要があります。この記事はその順序を示すために書いていますが、実際に手を動かす部分は残ります。
動画講座は、この順序と手を動かす部分がまとめて用意されている点が違います。環境構築から演習までが一続きになっているため、途中で詰まって止まる回数を減らせます。反面、自分に必要な部分だけを選んで進めるのは難しくなります。
どちらが適しているかは、いま何に時間を取られているかで決まります。仕様が分からなくて止まっているなら公式ドキュメント、何から手を付けるか決められなくて止まっているなら講座、という切り分けが実際的です。
学習後に自力で確認できるようにしたいこと
到達点を具体的に置いておきます。以下を自分の環境で確認できるようになっていれば、この記事の範囲は終わりです。
docker version の出力から、クライアントとサーバーのどちらで問題が起きているかを判断できる。docker ps -a の出力から、停止中のコンテナが名前を占有している状況を見つけられる。-p の左右がどちらを指すかを説明でき、コンテナの中から見た localhost とホストから見た localhost の違いを説明できる。コンテナを削除したときに消えるデータと残るデータを、実際に試して確認できる。compose.yaml を読んで、作られるコンテナとネットワークの数を実行前に言える。初めて見るエラーに対して、コマンド、エラー全文、コンテナの状態、ログ、ネットワークとボリューム、デーモンの順で調べられる。
これらは知識の暗記ではなく、手を動かして確認する操作です。読んだだけでは身に付かない部分なので、手元の環境で1つずつ試してください。
まとめ
Dockerのエラーが繰り返し起きるのは、コマンドを知らないからではなく、境界を知らないからです。ホストとコンテナ、イメージとコンテナ、コンテナ同士、そして消えるデータと残るデータ。この4つの境界を押さえると、エラー文の読み方が変わります。
学ぶ順序は、コンテナとイメージ、Dockerfileとビルド、ポートとネットワーク、ボリューム、Compose、トラブルシューティングです。それぞれに「次へ進む目安」を置いたのは、飛ばした段階が後から別の顔で現れるからです。
公式ドキュメントは仕様の確認先として最も確実です。一方で、学ぶ順序を自分で組み立てる負担が大きいと感じる場合は、順序と演習がまとまった教材を使う選択肢もあります。
Dockerを体系的に学べるUdemy講座を確認する(PR)
内容や価格、対象範囲はリンク先のページで確認してください。自分がいまどの段階で止まっているかを踏まえて、必要な範囲が含まれているかを見るのが選び方の基準になります。
参考資料
免責事項:本記事の内容は、執筆時点の公開情報をもとに作成したものです。ソフトウェアや講座の内容、価格、提供条件は予告なく変更されることがあります。最新の情報はDocker公式ドキュメントおよびリンク先の講座ページをご確認ください。本記事の情報を利用した結果生じたいかなる損害についても、著者および運営者は責任を負いかねます。