Dockerを体系的に学ぶ:6段階ロードマップ

この記事にはアフィリエイト広告が含まれています。 冒頭まとめ 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 の差は重要です。既定では実行中のものしか表示されません。停止したコンテナは見えないまま残り続け、名前を占有します。 ...

2026年8月9日 · ErrorLog

ConoHa VPSのDockerでufwが効かない原因と解決策

この記事にはアフィリエイト広告が含まれています。 冒頭まとめ ConoHa VPS で Docker を動かすとき、通信を止めたり通したりする設定は2か所にあります。ひとつは OS の中にある ufw、もうひとつは VPS の外側にあるセキュリティグループです。 ここで噛み合わなくなる理由が1つあります。Docker が -p で公開したポート宛の通信は、ufw が使う規則を迂回します。Docker の公式ドキュメントは、Docker と ufw が互いに相容れない使い方でファイアウォールの規則を使うと明記しており、公開されたコンテナへの通信は nat テーブルで転送されるため、ufw が使う INPUT と OUTPUT のチェーンに到達する前に迂回する、と説明しています(Packet filtering and firewalls)。 この性質から2つのことが言えます。第一に、ufw allow だけでは Docker の公開ポートを制御できません。第二に、ufw deny で拒否しても、Docker の公開ポートを塞いだことにはなりません。 したがって、ufw を変更したのに外部から接続できない場合は、ConoHa のセキュリティグループ側を確認する必要があります。逆に、ufw で塞いだつもりのポートについては、ufw の設定を根拠に安全だと判断できません。 症状の概要 現れ方は2通りあります。 ひとつは、開けたつもりで繋がらない状態です。ufw allow 8080 を実行し、ufw status の一覧にも出ているのに、外部のブラウザや curl から接続できません。 もうひとつは、塞いだつもりで開いている状態です。ufw deny 8080 を設定しても、docker run -p 8080:80 で公開したコンテナには通信が届きうる、という状態です。 どちらも、ufw の表示と実際の通信経路がずれていることから生じます。ufw の一覧はあくまで ufw が管理している規則を示すもので、Docker が別に作る規則は含まれません。 前提として、ConoHa の Docker テンプレートの仕様を押さえておきます。公式ドキュメントによれば、OS は Ubuntu 24.04、Docker CE は 29.2.1 で、OS 内のファイアウォールは既定で22番ポート(SSH)のみ許可となっています。また Minimum RAM は 1024 MB と明記されています(Docker|ConoHaドキュメントサイト)。512 MB のプランはこの最小要件を下回ります。 ...

2026年8月8日 · ErrorLog

Docker の name is already in use:原因と解決策

冒頭まとめ The container name "/web" is already in use を見たとき、動いているコンテナを探しても見つからないことがあります。docker ps に何も出ないのに拒まれる、という状況です。 理由は名前の持ち方にあります。Docker のデーモンは、名前とコンテナ ID の対応を、コンテナ本体とは別の表で管理しています。実装では names という名前の表で、containers の表とは分かれています。名前を確保するのは作成の時点で、その予約を消す処理が呼ばれるのは削除と改名の2か所だけです。 つまり名前は、動いているコンテナが占有しているのではありません。コンテナが存在する限り予約され続けます。停止しても、異常終了しても、作成に失敗して起動前で止まっていても、名前は返りません。docker ps が既定で動いているものだけを表示するため、この食い違いが起きます。 この仕組みが分かると、対処が3つに絞られます。予約しているコンテナを消すか、そのコンテナの名前を変えるか、こちらの名前を変えるかです。強制的に作り直しても、デーモンを再起動しても、原則としてこの3つ以外の道はありません。なお同じコンテナが同じ名前を確保し直す場合は衝突しません。予約の処理は、名前と ID の組が一致していればそのまま通る作りになっています。 もう1つ押さえるべき点があります。名前の一意性はデーモンごとです。ネットワークを分けても、Compose のプロジェクトを分けても、同じデーモンの上なら名前は1つしか使えません。 エラーの概要 出力は次の形です。 docker: Error response from daemon: Conflict. The container name "/web" is already in use by container "e7f8c9a2b1d4...". You have to remove (or rename) that container to be able to reuse that name. 読む場所は2つあります。1つ目は名前の先頭に付いた / です。これは入力の誤りではありません。実装は名前を予約する前に、先頭が / でなければ付け足します。だから表示にも / が現れます。 2つ目は後半のコンテナ ID です。これが予約している当事者で、調査の出発点になります。名前で探しても見つからない場合があるため、この ID で直接照会するのが確実です。 この応答は Docker Engine API では 409 として返ります。名前の衝突以外にも 409 になる場面はあるため、状態コードだけでは区別できません(Docker の 409 エラーの記事)。 ...

2026年8月7日 · ErrorLog

Docker の failed to solve エラー:原因と解決策

冒頭まとめ ERROR: failed to solve: を原因名として検索しているなら、探す場所がずれています。この一行は1つの部品が出した文言ではなく、3か所が順に書き足した結果です。 先頭の ERROR: を付けるのは buildx の入口部分です(cmd/buildx/main.go)。続く failed to solve は、BuildKit のクライアントがビルドサーバーから受け取ったエラーを包む語です(client/solve.go)。コロンより後ろが、失敗した部品の言い分です。 読むのはコロンの直後です。 process "..." なら実行を担う部分、failed to resolve source metadata for ならイメージ参照の解決、failed to compute cache key なら solver、failed to prepare ならキャッシュ管理が書き手です。failed commit on ref に至っては BuildKit ですらなく、同梱の containerd が出しています。 もう1つの読みどころが ------ Dockerfile:3 ------ の囲みです。エラーに Dockerfile 上の位置情報が付いているときだけ出ます(solver/errdefs/source.go)。囲みの有無で、疑う対象が Dockerfile の中身か外側かに分かれます。 エラーの概要 BuildKit のビルドは、Dockerfile を内部表現へ変換する段、イメージ参照を解決する段、コマンドを実行する段、書き出す段の順に進みます。failed to solve は全体を包む外枠で、どの段で止まっても先頭は同じです。区別できるのは後ろだけです。 型1:ステップ見出しと Dockerfile の囲みを伴う > [2/2] RUN apk add --no-cache bash: ... exited with error 127 2 errors ------ Dockerfile:3 -------------------- 1 | FROM alpine:3.23 2 | 3 | >>> RUN apk add --no-cache bash 4 | -------------------- ERROR: failed to build: failed to solve: process "/dev/.buildkit_qemu_emulator /bin/sh -c apk add --no-cache bash" did not complete successfully: exit code: 2 > [2/2] がステップ番号、>>> の行が失敗した命令、区切りの手前の exited with error 127 がコマンド自身の出力です。末尾の exit code: 2 は結果であり、理由ではありません。 ...

2026年8月6日 · ErrorLog

Docker の manifest unknown エラー:原因と解決策

冒頭まとめ manifest unknown は、レジストリとの通信自体は成立しているのに、指定した image reference(タグまたはダイジェスト)に対応する manifest がそのリポジトリで解決できなかったときに出るエラーです。OCI Distribution Specification では、リポジトリに blob または manifest が見つからない場合の応答は 404 Not Found と定められており、この系統のエラーは「サーバーが壊れている」ではなく「参照先が存在するか」を疑うところから始めます(OCI Distribution Specification)。 調査は次の3点を順に確認するのが最短です。 指定したタグまたはダイジェストが、そのリポジトリに実在するか image reference の各要素(レジストリホスト、名前空間、リポジトリ名、タグ、プラットフォーム)が意図したものになっているか 直前の build・tag・push、マルチアーキテクチャの manifest 公開が本当に完了しているか エラーの概要 manifest unknown は、レジストリが「そのリポジトリに、要求された manifest がない」と応答している状態です。名前解決や TLS の失敗とは違い、リクエストはレジストリまで届いています。認証エラーとも異なり、レジストリはリクエストを受け付けたうえで「該当なし」を返しています。 近いエラーとの違いを整理すると、次のように分類できます。 出力の傾向 意味するもの 最初に見る場所 manifest unknown(manifest が見つからない) 参照先のタグ・ダイジェストが存在しない image reference とタグ一覧 denied / unauthorized などの権限系の文言 認証・認可が足りない、または対象が非公開 ログイン状態とアクセス権 接続タイムアウト、名前解決失敗、証明書エラー レジストリまで到達できていない ネットワーク、プロキシ、TLS 設定 500・502・503・504 レジストリ側の障害 レジストリの稼働状況 なお、非公開リポジトリに対して存在を隠すために「見つからない」相当の応答を返すレジストリもあります。権限系と参照先不在の切り分けで迷う場合は、対象レジストリの公式ドキュメントで応答の仕様を確認してください。 本記事が扱う範囲は、docker pull や docker push の時点で発生する、レジストリ上の manifest 解決失敗です。認証・認可エラー、レジストリへの到達性そのものの問題、および Kubernetes の Pod sandbox 作成段階のイベント(FailedCreatePodSandbox など)は、発生する層が異なるため本記事の対象外とします。 ...

2026年8月5日 · ErrorLog

Docker daemon に接続できない:原因と解決策

冒頭まとめ Cannot connect to the Docker daemon は、Dockerの操作役である docker コマンドが、実行役の dockerd と通信できなかったという意味です。 最初に押さえるべきは、このエラーだけでは daemon が停止しているとは限らないことです。Docker公式のトラブルシューティングにも、daemon が動いていない場合だけでなく、クライアントが別の接続先を向いていて、その接続先へ到達できない場合があると書かれています。 一方、次の permission denied は一段具体的です。 permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: dial unix /var/run/docker.sock: connect: permission denied これは、daemon の停止を確認する前に、利用者がソケットへ接続する権限を疑うべき文言です。Linuxでは通常、/var/run/docker.sock を通してDocker APIを呼びます。ソケットが root:docker の所有で、現在の利用者が有効な docker グループに入っていなければ、接続の時点で拒否されます。 2つは同じ接続失敗の系統ですが、同じ原因ではありません。読むべき部分は末尾です。 connect: permission denied → ソケットへの権限を確認する connect: no such file ... → 接続先またはdaemonの起動を確認する connection refused → 接続先に受け手がいるかを確認する つまり、Is the docker daemon running? という問いをそのまま答えにしないことが重要です。まずクライアントがどこへ接続しようとしているかを確定し、次にその接続先でdaemonが動いているか、最後に現在の利用者が接続できるかを見ます。 エラーの概要 Docker Engine は、docker というクライアント、dockerd という常駐処理、両者を結ぶAPIから成ります。docker ps や docker compose up を実行すると、クライアントが選択中の接続先へAPI要求を送ります。 ...

2026年8月5日 · ErrorLog

Docker pull拒否エラー:原因と解決策

冒頭まとめ docker pull、docker run、docker compose up、docker build で次のエラーが出た場合、ログイン不足だけが原因とは限りません。 Error response from daemon: pull access denied for OWNER/IMAGE, repository does not exist or may require 'docker login': denied: requested access to the resource is denied この文は、考えられる原因をそのまま2つ並べています。 repository does not exist → 指定したリポジトリが存在しない may require 'docker login' → 非公開リポジトリで、認証またはpull権限が足りない 重要なのは、access denied と表示されても、リポジトリが存在するとは限らないことです。反対に、repository does not exist と表示されても、削除済みとは限りません。非公開リポジトリは、権限を持たない利用者からは存在を確認できない場合があります。 ただし、Registryの仕様が404と403を同じものとして定義しているわけではありません。CNCF DistributionのRegistry HTTP API V2仕様は、次のように区別しています。 状態 HTTP Registryのエラーコード 認証が必要 401 UNAUTHORIZED 操作を許可されていない 403 DENIED リポジトリ名が存在しない 404 NAME_UNKNOWN リポジトリはあるがタグやdigestがない 404 MANIFEST_UNKNOWN 混同が起きるのは、その手前に認証処理があるためです。Registryは最初に401と WWW-Authenticate を返し、クライアントは指定された認証サービスへ、対象リポジトリの pull 権限を含むトークンを要求します。権限のない主体には、要求した権限を含まないトークンが返ることがあります。その後のRegistry要求は拒否され、Docker CLIは不存在と権限不足の両方を含む案内へまとめます。 ...

2026年8月5日 · ErrorLog

Docker の exec format error:原因と解決策

冒頭まとめ exec format error は Docker が作った文言ではありません。Linux がプログラムを起動する際に返す ENOEXEC という結果を、そのまま表示したものです。 公式のマニュアルには、この結果の意味が1文で書かれています。実行可能ファイルが認識できる形式でない、アーキテクチャが違う、あるいは実行できない何らかの形式上の問題がある、という3つが並記されています。 したがって原因は2系統に分かれます。1つ目は CPU アーキテクチャの不一致です。Docker の公式文書は理由まで説明しています。コンテナはホストのカーネルを共有するため、中で動くコードはホストのアーキテクチャと互換でなければならない。だから linux/amd64 のコンテナを arm64 のホストで(エミュレーションなしに)動かすことはできない、と明記されています。 2つ目は、実行しようとした対象がそもそも実行可能な形式でない場合です。先頭行に実行系の指定が無いスクリプトを直接起動しようとした場合が典型です。 そして重要な境界があります。no such file or directory は別の系統です。マニュアルでは、指定したファイルや、スクリプトの実行系、あるいは必要な共有ライブラリが見つからない場合の結果として区別されています。ファイルは確かにあるのに「無い」と言われる現象は、こちらの系統です。 エラーの概要 実行時に出る文言は、実行系の階層をそのまま反映した形になります。 docker: Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec /entrypoint.sh: exec format error 長く見えますが、読むべきは末尾だけです。unable to start container process: までは実行系が付け加えた前置きで、実装でもこの文言でくるむ処理が確認できます。その後ろの exec <対象>: exec format error が本体です。 ...

2026年8月3日 · ErrorLog

Docker の no space left on device:原因と解決策

冒頭まとめ no space left on device は Docker が判定した結果ではありません。書き込みを試みた先のファイルシステムが返した結果を、そのまま表示したものです。 したがって最初にやるべきことは、対処ではなくどこが満杯なのかの確定です。候補は3つあります。 1つ目はホスト上のデータ保存先です。既定では /var/lib/docker で、イメージ、コンテナ、ボリューム、構築のキャッシュ、そしてログがすべてここに集まります。 2つ目は Docker Desktop の仮想ディスクです。この場合、ホストのディスクに空きがあっても関係ありません。上限は設定で決まっており、その中が満杯になれば同じエラーになります。 3つ目はコンテナの中です。共有メモリ用の領域は既定で 64MiB しかなく、これを超える書き込みでも同じ文言が出ます。 そしてもう1つ、見落とされやすい前提があります。Docker には自動的に減る仕組みがほとんどありません。公式文書によれば、ログの上限は既定で無制限、ボリュームはデータ破壊を避けるため自動削除されません。放置すれば埋まるのは仕様どおりの挙動です。 エラーの概要 文言は操作によって前後が変わりますが、末尾は共通です。 # 構築時 ERROR: failed to solve: failed to create temp dir: mkdir /var/lib/docker/tmp/buildkit-mount123: no space left on device # 起動時 docker: Error response from daemon: mkdir /var/lib/docker/tmp/docker-builder553623694: no space left on device 読むべきはどの経路への書き込みで失敗したかです。/var/lib/docker 配下ならホストのデータ保存先、コンテナ内の経路ならコンテナ側の問題です。 使用量の全体像は専用のコマンドで確認できます。 $ docker system df TYPE TOTAL ACTIVE SIZE RECLAIMABLE Images 15 3 21.71GB 18.17GB (83%) Containers 7 0 5.417kB 5.417kB (100%) Local Volumes 3 0 90.72MB 90.72MB (100%) Build Cache 295 0 20.77GB 20.77GB RECLAIMABLE の欄が、整理によって取り戻せる量です。どの種類が大きいかで、次にやることが決まります。 ...

2026年8月3日 · ErrorLog

Docker の port is already allocated:原因と解決策

冒頭まとめ port is already allocated を見たとき、多くの人は「そのポートで何かが待ち受けている」と考えます。しかし実装を読むと、この文言を出しているのは Docker 自身の割り当て台帳です。 Docker は公開ポートを管理する専用の仕組みを持っており、アドレスとプロトコルごとの対応表を内部に保持しています。要求されたポートをこの台帳と照合し、既に登録されていれば「Bind for アドレス:ポート failed: port is already allocated」という文言のエラーを返します。この時点で、実際に接続を試みてはいません。 したがって、ss や lsof で調べて誰も待ち受けていなくても、このエラーは出ます。台帳と実態がずれている状態です。 一方、基本ソフトウェアの側が拒否した場合、文言は変わります。 Ports are not available: exposing port TCP 0.0.0.0:3000 -> 0.0.0.0:0: listen tcp 0.0.0.0:3000: bind: address already in use port is already allocated は Docker の台帳、address already in use は基本ソフトウェア。この2つを見分けることが、切り分けの出発点になります。 エラーの概要 台帳が断った場合の典型です。 docker: Error response from daemon: driver failed programming external connectivity on endpoint my-app (a1b2c3...): Bind for 0.0.0.0:8080 failed: port is already allocated. 前半の「外部接続の設定に失敗した」は経緯の説明で、読むべきは末尾です。Bind for に続くアドレスとポートが、台帳で衝突した相手を示します。 ...

2026年8月3日 · ErrorLog