Docker入門|インストールと初コンテナ起動
Dockerは、アプリをコンテナという軽い実行環境で動かすための仕組みです。
イメージとコンテナの違い、Docker EngineとDocker Desktopの役割さえ最初に押さえれば、Windows(WSL2)・Mac・Linuxのどれでも導入の道筋はすぐ見えてきます。
この記事は、Dockerをこれから触る人や、入れたのに最初の一歩で止まってしまった人に向けた入門ガイドです。
『Docker Docs Get started』の流れに沿って、docker run hello-world から -p 8080:80 でのnginx公開、ブラウザ確認までを最短で通します。
筆者の現場でも「インストールは終わったのに docker が動かない」は珍しくなく、原因の多くはDocker Desktopがまだ起動していないか、WindowsのWSL2連携が不足しているケースです。
Docker Desktopは起動直後にエンジンの立ち上がり待ちで少し間が空くこともあるので、焦って再インストールするより、状態を見ながら切り分けるほうが早く前に進めます。
Dockerとは何かを最短でつかむ
Dockerは、アプリケーションをコンテナという分離環境で動かすためのプラットフォームです。
コンテナの中には、アプリ本体だけでなく、実行に必要なライブラリや設定もまとめて入れられます。
そのため、開発PCでは動いたのに別の端末では動かない、といった環境差分を減らしやすいのが大きな特徴です。
Docker DocsのWhat is Docker?でも、Dockerはアプリを一貫した環境で配布・実行する仕組みとして説明されています。
筆者は入門時に「Dockerそのもの」をひとつのソフトとして捉えすぎると混乱しやすいと感じてきました。
実際には、Dockerはコンテナを作る仕組み、動かす仕組み、配る仕組みが組み合わさった土台です。
最初の理解としては、アプリを軽い箱に入れて同じ形で動かす仕組みと捉えると、後のコマンドや構成の意味がつながりやすくなります。
コンテナとVMの違い
この差は、起動速度とリソース消費にそのまま表れます。
VM はゲスト OS の起動を伴うため重くなりやすく、メモリやディスクも多く使います。
対してコンテナは OS レベルの分離を用いるため立ち上がりが早いです。
同じマシン上に多数並べても扱いやすい構成になります。
筆者の普段の作業でも、この軽さは体感しやすいポイントです。
| 項目 | コンテナ | VM |
|---|---|---|
| 分離の単位 | アプリ実行環境 | マシン全体 |
| OS | ホストOSのカーネルを共有 | ゲストOSを個別に持つ |
| 起動 | 速い | OS起動ぶん時間がかかる |
| リソース消費 | 比較的少ない | 比較的大きい |
| 向いている場面 | 開発環境、CI/CD、マイクロサービス | OSごと分けたい検証、異なるOSの実行 |
「DockerはVMの一種ですか」と聞かれることがありますが、入門段階ではVMとは別の層の技術として理解したほうが誤解が減ります。
イメージとコンテナの関係
Dockerのもうひとつの基本が、イメージとコンテナの違いです。
ここが曖昧なままだと、docker run や docker ps の意味が見えにくくなります。
イメージは、コンテナを作るためのひな型です。
アプリの実行に必要なファイルや設定がまとまった、読み取り専用のテンプレートと考えるとつかみやすくなります。
たとえばnginxの公式イメージには、Webサーバーを動かすための土台が入っています。
そこから実際に起動されたものがコンテナです。
つまり、イメージが材料、コンテナが動いている実体という関係です。
筆者はここを「イメージ=設計図、コンテナ=動いている実体」と意識するようになってから、操作の混乱が減りました。
同じイメージから複数のコンテナを起動できる、という説明もこの捉え方だと自然に入ってきます。
設計図は1枚でも、そこから同じ建物を何棟も建てられるのと似ています。
たとえば docker run hello-world は、手元にhello-worldイメージがなければ取得し、そのイメージからコンテナを作って実行します。docker run -d -p 8080:80 nginx のようなコマンドでは、nginxイメージからWebサーバーのコンテナを起動し、ホストの8080番ポートをコンテナの80番ポートにつなぎます。
ここで見えているブラウザ表示は、イメージそのものではなく、起動中のコンテナにアクセスした結果です。
Docker DesktopとDocker Engineの違い
初学者が名前で迷いやすいのが、Docker DesktopとDocker Engineです。
どちらも「Docker」と付くので同じものに見えますが、役割は少し違います。
Docker Engineは、Linux上でコンテナを実際に動かす中核です。
CLIから docker コマンドを打つと、裏側ではEngineがイメージ取得やコンテナ起動を処理します。
Ubuntu向けの公式手順でも、docker-ce、docker-ce-cli、containerd.io などを入れてEngineを構成していきます。
Linuxではこの形が基本です。
一方のDocker Desktopは、WindowsやMacでDockerを扱いやすくするための統合アプリです。
Engineを含み、GUIや設定画面、追加ツールもまとめて提供します。
WindowsではWSL2連携が前提になりやすいです。
『Docker Desktop WSL 2 backend on Windows』やMicrosoft LearnのWSLコンテナ解説でも、その流れが公式導線として案内されています。
関係を一枚で描くと、次のイメージです。
Windows / Mac
┌─────────────────────────┐
│ Docker Desktop │
│ ├─ GUI / Settings │
│ ├─ Docker CLI │
│ └─ Docker Engine │
└─────────────────────────┘
Linux
┌─────────────────────────┐
│ Docker CLI │
│ Docker Engine │
│ containerd など │
└─────────────────────────┘
使い分けの感覚は、OSごとにこう整理できます。
-
Windows + WSL2 + Docker Desktop
GUIがあり導入の入口は広めですが、WSL2の準備や統合設定が抜けると止まりやすい構成です。
Windows側とWSL側のどちらからdockerを打つかも最初は混乱ポイントになります。 -
Mac + Docker Desktop
比較的素直に始めやすい構成です。
Apple Silicon搭載Macではarm64対応イメージを選ぶと流れがスムーズで、amd64専用イメージはエミュレーションになるぶん重さが出ます。 -
Linux + Docker Engine
本番環境に近い形で学べる一方、インストール直後は一般ユーザーで
dockerを打つとsudoが必要になる場面があります。
導入後に権限設定まで含めて整える流れが一般的です。
筆者の感覚では、WindowsとMacは「Desktopという入口から入る」、Linuxは「Engineを直接扱う」と覚えると整理しやすくなります。
WSL
Turn on the Docker WSL 2 backend and get to work using best practices, GPU support, and more in this thorough guide.
docs.docker.comDockerの主な用途
Dockerが使われる場面は広いですが、入門段階では4つ押さえると全体像が見えます。
まず代表的なのが開発環境の再現です。
Node.jsのバージョン、ライブラリ、ミドルウェアの組み合わせをイメージとして固定しておけば、別のPCでもほぼ同じ条件で立ち上げられます。
チーム開発で「自分のPCだけ動かない」を減らせるのは、Dockerが広く使われる大きな理由です。
次にCI/CDです。
テストやビルドを毎回同じコンテナ環境で流せるので、実行環境のばらつきが入り込みにくくなります。
継続的インテグレーションのジョブで、アプリ本体用のコンテナとデータベース用のコンテナを並べる構成も定番です。
さらにマイクロサービスとも相性が良いです。
nginx、APIサーバー、DB、キューといった役割ごとにコンテナを分けると、責務の境界が明確になります。
1つの巨大なVMの中に全部を詰め込むより、更新や差し替えの単位が小さくなります。
もうひとつ見逃せないのが、学習用の一時環境です。
試しにMySQLやPostgreSQLを触りたいとき、ローカルOSへ直接インストールせず、コンテナで立ち上げて不要になったら消す、という使い方ができます。
筆者も検証のたびに環境を汚したくない場面ではこの形をよく使います。
短時間だけ試して捨てられるので、手元の環境を崩さずに済みます。
入門の最初は、Dockerを「難しいインフラ技術」と構えるより、同じ環境を手早く作って、不要なら消せる道具として見ると、次の hello-world やWebコンテナの起動まで自然につながります。
インストール前に確認したいこと
導入作業は数分で終わることもありますが、詰まると最初の1時間が設定確認だけで消えます。
そこで先に見ておきたいのが、OSごとに何を前提にするかです。
『Docker』そのものは共通でも、実際の導入経路は Windows、Mac、Linux で分かれます。
ここを揃えておくと、後の docker version や docker run hello-world で原因を切り分けやすくなります。
Windowsでの前提
Windows では、初心者向けの導線としてDocker Desktopと WSL2 の組み合わせを前提に考えるのが素直です。
『Docker Desktop WSL 2 backend on Windows』 でも、この構成が基本ルートとして案内されています。
WSL2 が無効な状態だとDocker Desktopを入れてもその後で止まりやすいので、先に WSL が使える状態かを揃えておくと流れが途切れません。
WSL をこれから有効化する場合は、WSL2 を使う設定まで進んでいるかが分かれ目です。
既定バージョンが 1 のままだと、後から Linux ディストリビューションを入れたときに想定と違う状態になることがあるため、wsl --set-default-version 2 を入れておくと整理しやすくなります。
Ubuntuなどのディストリビューションを使うなら、Docker Desktop側の WSL Integration を有効にして、どの環境から docker コマンドを使うかを揃えるのがコツです。
WSL2 連携では、作業ディレクトリの置き場所でも体感が変わります。
筆者は Windows 側の /mnt/c/... にプロジェクトを置いた状態より、WSL 側の /home/... に置いたほうがファイル I/O が軽く、依存関係の展開や監視処理でも引っかかりが減る場面が多くありました。
Node.js や Python のように細かいファイルをたくさん読む開発では、この差がそのまま待ち時間に出やすいんですよね。
Macでの前提
Mac ではDocker Desktopが基本ルートです。
Windows より前提条件が少なく、アプリを導入して起動し、CLI が使える状態にする流れで進められます。
Compose も同梱されているため、入門段階では追加のコンポーネントを個別に探さなくて済みます。
Apple Silicon を使っている Mac でも、nginx のような公式イメージの多くは arm64 を含むマルチアーキテクチャ対応なので、そのまま動く場面が中心です。
普段の学習用途なら、アーキテクチャを意識せず進められることが多いはずです。
一方で、古いイメージや amd64 専用のイメージを持ってくると no matching manifest のような形で止まることがあります。
この場合は arm64 対応イメージへ切り替えるほうが筋がよく、--platform linux/amd64 での実行は互換性確保の逃げ道と考えるのが現実的です。
エミュレーション経由だと起動が重くなり、メモリ消費も増えやすいため、学習用の最初の1歩では避けたほうが流れが止まりません。
メモリ割り当ても気になるところですが、簡単なコンテナ確認なら 1GB 程度の設定でも足りるケースがあります。hello-world や軽い Web コンテナを触る段階なら、いきなり大きな割り当てを考えなくても出発点としては十分です。
Linuxでの前提
Linux ではDocker Desktopではなく、Docker Engineを公式パッケージで入れる構成が軸になります。
Ubuntu 系なら 『Install Docker Engine on Ubuntu』 の手順に沿って、『docker-ce』『docker-ce-cli』containerd.ioを入れる流れです。
ディストリビューション標準の古い非公式パッケージと混ざると、あとでバージョン差分の切り分けが面倒になるので、公式リポジトリから揃える意味があります。
ここで見落としやすいのが、導入直後の権限です。
初期状態では一般ユーザーで docker を打つと、そのままでは動かず sudo が必要になる構成が普通です。docker グループへの追加は post-install の話なので、最初から「なぜ sudo なしで動かないのか」と悩まなくて済みます。
本番 Linux に近い形で触れるぶん、GUI が面倒を見てくれる範囲は少なく、CLI と権限の感覚をそのまま持つことになります。
Linux は自由度が高い反面、ブログごとに導入方法がばらつきます。
Snap 版や古いパッケージ、手動配置のバイナリが混ざった環境は、初心者の最初の学習には遠回りです。
まずは公式のDocker Engineパッケージで素直に入り、動作確認が取れてから post-install を足していく順番のほうが、原因の切り分けがまっすぐ進みます。
Ubuntu
Jumpstart your client-side server applications with Docker Engine on Ubuntu. This guide details prerequisites and multip
docs.docker.com再起動・権限・ライセンスの注意
導入前提として、管理者権限が必要になる場面は避けられません。
Windows では WSL や仮想化関連の機能を有効にしたあとで再起動が入ることがありますし、Docker Desktopのインストール後にログアウトや再起動を求められる場合もあります。
インストーラーを実行したのにコマンドが見つからないときは、設定ミスより先にこの反映待ちを疑うと切り分けが早くなります。
権限まわりも OS ごとに色が違います。
Windows と Mac はDocker Desktopがまとめて面倒を見てくれる範囲が広い一方、Linux は sudo を含めた権限設計がそのまま表に出ます。
企業ネットワークやプロキシ配下では、インストーラーやイメージのダウンロードが途中で止まることもあり、単純な手順どおりに進まないことがあります。
この種のネットワーク要因は後半のトラブル対処で切り分けますが、初回セットアップに時間がかかる背景としてはよくあります。
ライセンス面では、Docker Desktopは個人利用や小規模組織ならそのまま使えるケースが多いものの、従業員 250 人超または年間売上 1,000 万 USD 超の企業では有料サブスクリプションが必要になる条件があります。
個人学習では深刻な障壁になりにくいものの、業務 PC で触るときは導入経路だけでなく契約条件もセットで見る前提になります。
{{product:2}}
Windows / Mac / Linux でDockerをインストールする
Windows
Windows はDocker DesktopとWSL2の組み合わせが基本です。
GUI があるぶん入口は広いのですが、詰まる場所もだいたい決まっていて、筆者の経験ではDocker Desktop側の設定より先にWSL2の土台を揃えると流れが止まりません。
まずは管理者権限のPowerShellまたはWindows Terminalで、WSL と仮想化まわりを有効にします。
新しめの Windows では次のコマンドで一括導入できます。
wsl --install
すでに WSL を入れている場合でも、既定のバージョンは明示しておくと切り分けが楽です。ここで 2 を指定しておくのがポイントです。
wsl --set-default-version 2
導入状況を確認したいときは、次のコマンドで状態を見られます。
wsl --status
wsl --list --verbose
この段階で再起動やサインアウトが入ることがあります。
コマンド自体は通っていても、Windows の機能有効化が反映される前だと次へ進んだときに不整合が出るため、ここは素直に反映待ちを挟むほうが結果的に早いです。
その後にDocker Desktop for Windowsをインストールして起動します。
起動直後は裏でDocker Engine相当の環境が立ち上がるまで少し待ち時間があるので、タスクバーに常駐しただけで完了と判断しないほうが混乱しません。
Docker Desktopが起動したら、Settings > Resources > WSL Integration を開き、既定ディストリビューションとの連携を ON にします。
筆者は Windows で docker が不安定なとき、ここで既定ディストリビューションだけでも連携を有効にすると、拍子抜けするほど素直に動く場面を何度も見ています。
CLI は WSL 側で打てるのにコンテナが見えない、逆に Desktop は動いているのにシェルからつながらない、といった初歩的な食い違いはこの設定で解けることが多いです。
WSL 側のシェルから確認するなら、Ubuntu などのディストリビューションを開いて次を実行します。
docker version
ここで client だけでなく server 側も返ってくれば、Windows と WSL の橋渡しまで通っています。
Mac
Mac はDocker Desktop for Macを入れて起動するのが最短ルートです。
Windows と違って WSL のような前提設定がないため、導入の重心はアプリのインストールと初回権限付与にあります。
インストール後、初回起動ではシステム権限やネットワーク関連の許可を求められるので、それを終えてからバックグラウンドでエンジンが立ち上がるのを待ちます。
操作を始める目安は、メニューバーのDocker Desktopアイコンが Running になっていることです。
ここが起動途中のまま docker version を打つと、クライアントは見えてもサーバーに接続できず、設定ミスと勘違いしがちです。
ターミナルでの確認は次の 1 行で足ります。
docker version
Apple Silicon 搭載の Mac では、まず arm64 に対応した公式イメージを選ぶのが近道です。nginx のような定番イメージはマルチアーキテクチャ対応が進んでいるので、そのまま動くケースが中心です。
反対に、古い amd64 専用イメージを無理に持ち込むと no matching manifest で止まりやすく、--platform linux/amd64 で逃がすことはできても、起動が重くなりメモリ消費も増えます。
入門段階では、まず公式イメージを優先して選ぶほうが余計な切り分けを抱えずに済みます。
Ubuntu
Ubuntu 系 Linux ではDocker Engineを公式リポジトリから入れる構成が基本です。
OS 標準の古いパッケージや別経路の導入物が残っていると、docker コマンドは存在するのにエンジンが違う、といったややこしい状態になりやすいため、まず旧版を外して土台を揃えます。
Install Docker Engine on Ubuntuの流れに沿うと筋が通ります。
最初に、旧版や競合パッケージを削除します。
for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get remove -y $pkg; done
次に、公式リポジトリを追加するための準備をします。
sudo apt-get update
sudo apt-get install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL [https://download.docker.com/linux/ubuntu/gpg](https://download.docker.com/linux/ubuntu/gpg) -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
続いて、APT の参照先に『Docker』公式リポジトリを登録します。
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] [https://download.docker.com/linux/ubuntu](https://download.docker.com/linux/ubuntu) \
$(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
リポジトリ追加後にパッケージ一覧を更新し、『docker-ce』『docker-ce-cli』containerd.ioを入れます。
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
インストール直後の確認は、まず sudo 付きで行うのが安全です。
筆者は Linux では最初から権限まわりを整えようとせず、まず sudo で確実に動かすところまで進め、そのあと必要なら docker グループを足します。
この順番だと、問題が権限なのか、サービス起動なのか、パッケージ競合なのかを素直に切り分けられます。
sudo docker version
sudo docker run hello-world
一般ユーザーで docker を打ちたい場合は post-install として docker グループを使います。設定自体は次のコマンドで入れられます。
sudo groupadd docker
sudo usermod -aG docker $USER
この変更は次回ログイン後に有効になります。
いま開いているシェルでは反映前のことがあるので、その場で docker が通らなくても手順ミスとは限りません。
まず sudo docker ... で基盤を確認してから進めるほうが、Linux では遠回りになりません。
初回起動チェック
OS ごとの導入が終わったら、共通の確認として docker version を実行します。
ここで見たいのは、Client だけでなく Server も表示されることです。
Docker Desktop系ではアプリを起動した直後にまだサーバー側が立ち上がっておらず、少し待つと通るケースがよくあります。
docker version
Ubuntu で docker グループをまだ設定していない段階なら、ここだけ sudo を付けます。
sudo docker version
期待する状態は、クライアント情報とサーバー情報の両方が並ぶことです。
クライアントしか出ないときは、Mac と Windows ではDocker Desktopの起動待ち、Windows では WSL 連携、Ubuntu ではサービスか権限の順に見ると整理しやすくなります。
導入直後のチェックは docker run hello-world まで進めたくなりますが、まず docker version で client/server の両方を確認しておくと、どの層で止まっているかをつかみやすくなります。
{{product:2}}
最初のコンテナを起動する
バージョン確認
インストール直後は、まず docker version か docker --version で実行環境を見ます。
ここで初心者の方に先に押さえてほしいのは、単にバージョン文字列が出るだけで安心しないことです。docker --version は CLI の確認にはなりますが、Docker のサーバー側まで動いているかは分かりません。
導入直後の切り分けには docker version のほうが向いています。
docker version
Linux でまだ権限設定前なら、前のセクションで触れた通り sudo を付けます。
sudo docker version
出力の中に Client と Server の両方が見えれば、CLI と Docker Engine もしくはDocker Desktopのバックエンドまで到達できています。
逆に Client しか出ない、あるいは server related のエラーが出る場合は、まだコンテナを起動する前の段階で止まっています。
筆者の体感では、Mac や Windows でDocker Desktopを起動した直後にこの確認をすると、画面上は立ち上がっているように見えても、裏側の起動がまだ追いついておらず一度失敗することがあります。
とくに hello-world を急いで打つとエラーになり、数十秒後に同じコマンドを打つと通る、という流れは珍しくありません。
この段階で焦って設定を崩すより、まず docker version で Server が出るかを見ると状況をつかみやすくなります。
hello-worldを実行する
Server 側まで見えているなら、最初の 1 本として hello-world を動かします。
docker run hello-world
Linux で権限設定前ならこちらも sudo 付きです。
sudo docker run hello-world
このコマンドで起きることは、実は 1 ステップではありません。
ローカルに hello-world イメージがまだ無ければ、Docker はまずレジストリからイメージを取得し、そのあとコンテナを 1 回だけ起動して、メッセージを表示して終了します。
初回に自動取得が走るので、何かを事前にダウンロードしておく必要はありません。
画面に Hello from Docker! と出れば成功です。
そこまでのログには、イメージを見つけられなかったので取得したこと、取得したイメージからコンテナを起動したことが順に表示されます。
要するに、docker run は「必要ならイメージを pull して、そこからコンテナを作って実行する」コマンドだと、この 1 回で体験できます。
補足として、実行後の状態は次のコマンドでも確認できます。
docker images
docker ps -a
docker images では取得済みイメージの一覧が見え、hello-world が残っています。docker ps -a では、実行してすぐ終了した hello-world コンテナの履歴が見えます。
初回は「動いたのにもう消えたのでは」と感じやすいのですが、これは短いメッセージを出して正常終了するコンテナなので、この表示が合っています。
docker runの主要オプション
hello-world は最小の例ですが、今後よく使う docker run のオプションはこの時点で 3 つだけ覚えておくと流れがつながります。
筆者は最初に全部覚えるより、名前を付ける、裏で動かす、ポートを開けるの 3 つに絞る説明をよくします。
docker run --name my-hello hello-world
--name はコンテナに名前を付けるオプションです。
ランダム名ではなく my-hello のように自分で決めた名前で扱えるので、docker ps -a で見たときに何を動かしたか追いやすくなります。
docker run -d --name web nginx
-d はバックグラウンド実行です。
端末を占有せず、裏で起動し続けるコンテナに使います。hello-world のようにすぐ終了するものでは意味が薄いですが、Web サーバーの nginx のような常駐プロセスでは基本形になります。
docker run -d --name web -p 8080:80 nginx
-p はポート公開で、8080:80 は ホストの 8080 番をコンテナの 80 番につなぐという意味です。
ブラウザで http://localhost:8080 にアクセスすると、コンテナ内の Web サーバーへ届きます。
Docker Docs Get startedでも、まずはコンテナを動かして手元のブラウザで確認する流れが案内されていて、入門の最初の成功体験として相性がいい構成です。
3 つを並べると、次のイメージです。
起動できたら、ブラウザで http://localhost:8080 を開きます。nginxのデフォルトページが表示されれば成功です。
-d: 端末の前面ではなくバックグラウンドで動かす-p 8080:80: ホストのポートをコンテナのポートへ転送する
docker run は長く見えても、実際には「どう呼ぶか」「前面か背面か」「外から入れるか」を指定しているだけです。
最初のうちはこの 3 つが読めれば、サンプルコマンドの意味を追えるようになります。
失敗時のチェックリスト
hello-world が通らないときは、原因を広く疑うより、止まりやすい場所を順番に見たほうが早く切り分けられます。
- Docker Desktopがまだ起動しきっていない
- Windows で WSL2 の設定や連携が未完了になっている
- Linux で権限不足のまま
sudoなしで実行している - イメージ取得時にネットワークへ出られていない
Windows では WSL2 バックエンド前提の構成で止まることがあるため、Docker DesktopとWSL 2 backend on Windowsの公式説明が役立ちます。
WSL 側の動作確認も含めるなら、Microsoft Learnの WSL コンテナ入門も整理された導線です。
エラーメッセージの読み方も単純です。
サーバーに接続できない系なら、Desktop 未起動やサービス未起動、WSL 連携の問題が先に来ます。
permission denied なら Linux の権限です。
pull 関連や名前解決の失敗なら、ネットワークか DNS の層を疑います。
Apple Silicon の Mac で古いイメージを試したときに no matching manifest が出たら、そのイメージが arm64 を持っていないケースがあります。
この場合は arm64 対応イメージを使うほうが素直です。
手元の状態確認としては、docker images でイメージ取得まで進んだか、docker ps -a でコンテナ作成までは進んだかを見ると、どこで止まったかを把握できます。
イメージがあるのにコンテナ実行で落ちているのか、そもそも取得前で止まっているのかが分かれるだけでも、次に見る場所が絞れます。
Webコンテナを起動してブラウザで確認する
nginxの公式イメージで起動する
hello-world で「Docker コマンドが動く」ことを確認したら、次はブラウザで見える Web サーバーを起動すると、コンテナの便利さが一段つかみやすくなります。
ここではnginxの公式イメージを使います。
公式イメージは出所が明確で、更新も継続されており、arm64 を含むマルチアーキ対応のものが多いので、Apple Silicon の Mac でも素直に試しやすい構成です。
まずは次のコマンドを実行します。
docker run -d -p 8080:80 --name web nginx
この 1 行には、前のセクションで触れた要素がそのまま入っています。--name web はコンテナ名、-d はバックグラウンド起動、-p 8080:80 はホストのポートとコンテナのポートをつなぐ指定です。nginx は取得するイメージ名で、ローカルに無ければ Docker が自動で取得してから起動します。
起動できたら、ブラウザで http://localhost:8080 を開きます。
nginxのデフォルトページが表示されれば成功です。
筆者も入門の説明ではこの手順をよく使いますが、端末にメッセージが出るだけの hello-world より、「ブラウザで実際に見える」ほうが Docker の用途を一気に想像しやすくなります。
手元の Mac や Windows で Web サーバーを汚さずに立ち上げて、使い終わったら消せる、という感覚がここでつながります。
学習全体の流れは『Docker Docs Get started』でも段階的に整理されていて、最初にコンテナを触ってから Web アプリへ進む導線になっています。
この段階では、まず 1 台の Web コンテナを手元で見える形にするだけで十分です。
だからブラウザで開くのは http://localhost:8080 になります。
-p 8080:80 は、初学者が最初につまずきやすい部分です。
左がホスト、右がコンテナです。
つまり、手元の PC の 8080 番に来た通信を、コンテナ内の 80 番へ転送しています。
localhost:8080(ホスト) -> container:80(コンテナ)
ここを逆に覚えると、ブラウザで開くポートとコンテナが待ち受けるポートの関係が崩れて、急に分かりにくくなります。
筆者も初学者向けに教えるとき、この左右を逆に書いてしまう場面をよく見ます。host:container の順だと図で一度整理すると、その後の -p 3000:3000 や -p 5432:5432 も読み解きやすくなります。
なお、コンテナの中でnginxが待ち受けているのは標準の 80 番です。
一方、ホスト側も 80 を使う必要はありません。
すでに別のアプリが使っていることもあるので、入門では 8080 にずらす形が扱いやすいです。
だからブラウザで開くのは http://localhost:8080 になります。
このとき、「イメージ側で EXPOSE 80 と書いてあるなら自動で見えるのでは」と思うかもしれませんが、EXPOSE はあくまでメタデータです。
外からアクセスできるようにするには、実行時に -p を付けてホストとの対応を明示します。
ここは Dockerfile と docker run の役割が分かれるところです。
このときブラウザで開くのは http://localhost:8080 です。
ホスト側のポートを変更している場合は、そのポート番号に置き換えてください(例: -p 8081:80 の場合は http://localhost:8081 を開きます)。
コンテナが動いているかを確認するには、まず docker ps を使います。
docker ps
実行すると、web という名前のコンテナ、使用中のイメージ、起動状態、公開ポートが一覧で見えます。0.0.0.0:8080->80/tcp のような表示が出ていれば、ホストの 8080 がコンテナの 80 に結びついていると読めます。
起動直後の様子をもう少し見たいときは、ログも確認できます。
docker logs web
nginxは起動時の情報やアクセスログを出すので、ブラウザで localhost:8080 を開いたあとに docker logs web を見ると、リクエストが届いた形跡も追えます。
Web サーバーが「ただ存在する」だけでなく、実際に通信を受けていると分かる瞬間で、このあたりからコンテナが開発や検証に使われる理由が見えてきます。
使い終わったら停止と削除もすぐできます。
docker stop web
docker rm web
docker stop web でコンテナを止めて、docker rm web で一覧から取り除きます。
仮に失敗しても、ホスト OS にnginxを直接インストールしたわけではないので、後片付けが軽いのが Docker の良さです。
筆者は設定検証や一時的な再現環境を作るとき、この「起動して、見て、消す」までが短いことにいちばん恩恵を感じます。
TIP
docker ps は「今動いているもの」、docker ps -a は「停止済みも含めた履歴」です。
停止したのに見当たらないときは、この 2 つを使い分けると状況を切り分けやすくなります。
{{product:2}}
Get started
Get started with Docker
docs.docker.comhttpdイメージの代替例
Apache HTTP Serverの公式イメージでも同じ流れを試せます。たとえば次の 1 行で起動できます。
docker run -d -p 8080:80 --name web httpd:latest
localhost:8080 をブラウザで開いてデフォルトページを確認する流れはnginxと同じです。
公式イメージを使っておけば、どちらの Web サーバーでも「イメージを取って、コンテナを起動して、ポートを公開し、ブラウザで確認する」という Docker の基本操作は共通だとつかめます。
よくあるエラーと対処法
Docker Desktopが起動していない
error during connect: This error may indicate that the docker daemon is not running のような表示が出たら、まずDocker Desktop本体や Docker Engine が動いていない状態を疑います。
Windows と Mac では、Docker の CLI だけ先に開いていて、裏側のエンジン起動がまだ終わっていない場面がよくあります。
タスクトレイやメニューバーにDocker Desktopのアイコンが出ていても、内部エンジンが立ち上がるまで少し待つ必要があります。
筆者は経験上、wsl --shutdown で一度 WSL 全体を停止してからDocker Desktopを再起動すると復旧することがありました。
ただし注意点として、wsl --shutdown は WSL 内で動いているすべてのプロセス(開発中のシェルやサービスを含む)を終了させます。
まずは Docker Desktop の再起動やログ確認を試し、それでも改善しない場合に経験則として wsl --shutdown を使う、という順番で試してください。
参考(操作の副作用や管理コマンドの説明): Microsoft Learn — WSL 管理チュートリアルMicrosoft Learn — WSL 管理チュートリアル。
Linux ではDocker Desktopではなく Docker Engine を直接使う構成が多いので、まずサービス状態を確認します。
筆者の経験上、wsl --shutdown で一度 WSL 全体を停止してからDocker Desktopを再起動すると復旧することがありました。
ただし wsl --shutdown は WSL 内で動いているすべてのプロセス(開発中のシェルやサービスを含む)を強制終了します。
まずは Docker Desktop の再起動やログ確認を試し、それでも改善しない場合に「筆者の経験則として」wsl --shutdown を使う、という順番で対処してください。
参考: Microsoft Learn — WSL 管理チュートリアルMicrosoft Learn — WSL 管理チュートリアル。
sudo systemctl status docker
停止しているなら、次のように起動します。
```bash
sudo systemctl start docker
sudo systemctl enable docker
ここで docker version や docker run hello-world が通るなら、原因はデーモン未起動だったと判断できます。
『Install Docker Engine on Ubuntu』 でも、Linux ではサービス管理と post-install の整理が入口になります。
{{product:2}}
WSL2未設定/未更新
Windows で WSL 2 installation is incomplete のようなエラーが出る場合は、Docker そのものより先に WSL2 の前提がそろっていません。
Docker Desktopは Windows 上で WSL2 バックエンドを使う前提が強いため、ここが未設定だと最初のコンテナ起動で止まりがちです。
典型的には、既定バージョンが 2 になっていない、WSL 本体が古い、またはDocker Desktopの WSL Integration が無効のまま、という3つが並びます。
順番に直すなら、まず既定バージョンを 2 に設定し、更新を入れます。
wsl --set-default-version 2
wsl --update
そのうえでDocker Desktopの設定画面から WSL Integration を有効にします。
Windows では Docker の不調に見えて、実際には WSL 層が古いだけというケースが多いです。
『Docker Desktop WSL 2 backend on Windows』 の説明どおり、Docker と WSL は別物ではなく、起動基盤としてつながっています。
権限不足
permission denied や Got permission denied while trying to connect to the Docker daemon socket は、Linux で最も遭遇しやすいエラーのひとつです。
Docker コマンド自体は見つかっているのに、ソケットへ接続する権限が足りません。
この段階では、まず sudo を付けて確実に動くかを見るのが近道です。
sudo docker ps
筆者は Linux で原因を追うとき、まず sudo で通る状態を確認してから、権限設定の問題か、別の問題かを分けます。
この方針だと「Docker が壊れている」のか「今のユーザーに権限がない」のかがすぐ分かれます。
いきなり設定を触り回るより、失敗地点がはっきりします。
恒久的に sudo なしで使うなら、ユーザーを docker グループへ追加します。
sudo usermod -aG docker $USER
この変更は次回ログイン後に有効になります。
追加直後に同じシェルで試しても反映されていないことがあるので、そこで混乱しやすいです。
まず sudo で動くか、そのあとグループ設定を反映した新しいログインセッションで docker ps を試す、という順番にすると迷いません。
ポート競合
bind: address already in use は、公開したいホスト側ポートを別のプロセスがすでに使っている状態です。
たとえば前のセクションで触れた 8080:80 を試したとき、ローカルで別の Web サーバーや開発ツールが 8080 をつかんでいると、このエラーになります。
Windows では次のコマンドで使用中プロセスを特定できます。
netstat -ano | findstr 8080
Mac と Linux ではこちらです。
lsof -i :8080
PID が分かったら、そのプロセスを止めるか、Docker 側のホストポートを変えます。
たとえば -p 8081:80 にずらせば、コンテナ内の 80 はそのままで、ブラウザ側だけ localhost:8081 に変わります。
Docker の問題に見えて、実際はローカルの開発サーバー、IDE のプレビュー機能、Apache HTTP Serverなどが先に待ち受けていることも珍しくありません。
NOTE
docker ps は「今動いているもの」、docker ps -a は「停止済みも含めた履歴」です。
停止したのに見当たらないときは、この 2 つを使い分けると状況を切り分けやすくなります。
古いdocker contextの整理
NOTE
docker ps は「今動いているもの」、docker ps -a は「停止済みも含めた履歴」です。
停止したはずのコンテナが見当たらないときは、この 2 つを使い分けると状況を切り分けやすくなります。
docker context ls
いま使うべき環境が通常のローカル Docker なら、既定のコンテキストへ戻します。
docker context use default
不要な wsl などのコンテキストが残っていて混乱のもとになっているなら、削除もできます。
docker context rm wsl
特に Windows ではDocker Desktop再インストールや WSL 再構成のあと、このあたりが静かに残っていることがあります。
エラー文そのものは接続失敗としか出ないので見落としやすいのですが、docker context ls を一度挟むだけで原因が見えることがあります。
ネットワーク/プロキシの影響
docker pull や docker run の途中でイメージ取得に失敗する場合は、ネットワークやプロキシ設定も候補に入ります。
社内ネットワークや学校の回線では、レジストリへの通信が途中で止まることがありますし、一時的な取得失敗もあります。
そういうときは、まず時間を置いて再試行すると通ることがあります。
プロキシを使う環境では、Docker Desktopやシェル側のプロキシ設定がそろっていないと、ブラウザでは見えるのに Docker だけ pull できないという状態になります。
初回検証では、独自イメージよりnginxのような公式イメージを先に使うほうが、問題がネットワークなのか、イメージ側なのかを切り分けやすくなります。
Apple Silicon 搭載の Mac では、ネットワークエラーに見えて実際はアーキテクチャ非対応ということもあります。no matching manifest for linux/arm64/v8 のようなエラーは、レジストリに arm64 向けイメージがない状態です。
この場合は arm64 対応の公式イメージを選ぶのが第一候補で、nginxのようにマルチアーキ対応しているものならそのまま通せます。
既存の amd64 専用イメージをどうしても使うなら、--platform linux/amd64 を付けて動かす方法もありますが、起動が重くなり、開発中の反応も鈍くなります。
学習段階では、まず arm64 に素直に対応した公式イメージへ寄せたほうが詰まりません。
次に学ぶと理解が深まること
基本コマンド
最初の一歩を終えたら、起動したコンテナを「見る」「止める」「消す」操作まで覚えると、Docker がぐっと道具として手になじみます。
入門直後は docker run だけで満足しがちですが、実際には後片付けまで含めて一連の流れです。
まず覚えたいのは次の5つです。
docker ps
docker images
docker stop <コンテナ名またはID>
docker rm <コンテナ名またはID>
docker rmi <イメージ名またはID>
docker ps は、いま動いているコンテナの一覧を確認するコマンドです。
Web コンテナを起動したあとに docker ps を見ると、コンテナ名、状態、ポート公開の内容が分かります。
ブラウザで表示できないときも、まずここを見る癖を付けると切り分けが速くなります。
docker images は、ローカルに保存されているイメージの一覧です。nginx を試したあとに残っているイメージを見たいときに使います。
コンテナは止めても、イメージは別に残るという感覚がここでつかめます。
docker stop は、動いているコンテナを停止します。たとえば my-nginx という名前で起動していたなら、次のように実行します。
docker stop my-nginx
停止しただけではコンテナの定義は残るので、不要になったら docker rm で削除します。
docker rm my-nginx
イメージ自体ももう使わないなら、docker rmi で削除できます。
docker rmi nginx
この一連の操作に慣れると、「試して、止めて、消して、また作る」が自然に回ります。
筆者も新しいツールを触るときは、まず公式イメージを起動して、docker ps と docker images で状態を眺めるところから始めます。
Dockerfileの最小例
次に進むなら、『Dockerfile』は避けて通れません。
これは「このアプリ実行環境をどう作るか」を文章で定義するファイルです。
手元で一度作った環境を、別のPCやチームのメンバーの環境でも同じ形で再現できるようになります。
最小限の雰囲気をつかむなら、次の例で十分です。
FROM nginx:latest
RUN mkdir -p /usr/share/nginx/html
COPY ./index.html /usr/share/nginx/html/index.html
EXPOSE 80
FROM はベースイメージの指定です。
この例ではnginxを土台にしています。RUN はイメージを組み立てる途中でコマンドを実行する命令で、ディレクトリ作成やパッケージ導入に使います。COPY は手元のファイルをイメージの中へ入れる命令で、今回は index.html を Web 公開ディレクトリへ配置しています。EXPOSE 80 は「このコンテナは 80 番ポートを使う」という宣言で、ポート公開そのものは別途 docker run -p か Compose 側で行います。
このファイルを置いたディレクトリでイメージを作るときは、たとえばこう書けます。
docker build -t my-web .
手で毎回同じ設定を打ち直す代わりに、『Dockerfile』へ残しておく。この習慣が付くと、開発環境の再現性が一段上がります。
Dockerfile を書くベストプラクティス — Docker-docs-ja 24.0 ドキュメント
docs.docker.jpComposeの最小例
コンテナが1つだけなら docker run でも十分ですが、Web アプリとデータベース、管理画面とメッセージブローカのように、複数をまとめて立ち上げたくなる場面はすぐに来ます。
そこで使うのが『Docker Compose』です。
現在は docker-compose より docker compose が標準的です。
たとえば Web と DB をまとめて起動する最小イメージは、次のようになります。
services:
web:
image: nginx:latest
ports:
- "8080:80"
db:
image: postgres:latest
environment:
POSTGRES_PASSWORD: example
この compose.yaml を置いた場所で、次のコマンドを実行します。
docker compose up -d
これだけで複数コンテナをまとめて起動できます。
停止と片付けも docker compose down で一括です。
設定をファイルに寄せておくと、「どのイメージを使うか」「どのポートを開けるか」「どの環境変数を渡すか」が1か所に集まるので、手順書よりも実行可能な形で残せます。
筆者はスマートホームの検証で、この恩恵を何度も受けています。
Web UI と MQTT ブローカを Compose で一緒に起動できるだけで、実験の準備が手入力の連続作業から構成ファイルの実行に変わります。
毎回コンテナ名やポートを思い出さなくて済むので、試したいことに意識を向けられます。
同じ『Dockerfile』と『Compose』があれば、ノートPCでもデスクトップでも、チームの別メンバーの端末でも、ほぼ同じ開発環境をそのまま立ち上げられます。
ここが Docker のいちばん強い使いどころです。
環境差分の説明に時間を使うより、構成をファイルで共有したほうが早く、再現も正確です。
WARNING
Docker Desktopを使っている環境では Compose が同梱されていることが多いですが、組織のポリシーや古いバージョンだと別途インストールが必要な場合があります。docker compose version でバージョン確認をしてから利用してください。
Compose のインストール — Docker-docs-ja 24.0 ドキュメント
docs.docker.jp学習リソース
独学で次へ進むなら、まずDocker DocsのGet startedを一周するのが近道です。
公式の入門ワークショップとして整理されていて、約45分で基礎をひと通り触れる流れになっています。
断片的な記事を渡り歩くより、用語と操作が一本につながります。
入口としてはDocker Docs Get started入口としてはDocker Docs Get startedを読むのがいちばん効率的です。
NOTE
IT企業でのシステムエンジニア経験を経て、スマートホーム導入のコンサルティングに転身。Home AssistantやESPHomeを使った自宅オートメーションを日々研究中。