「自分のマシンでは動くのに本番で動かない」を潰したのが Docker です。アプリと依存関係をまとめて固め、どこでも同じ状態で起動できるようにした。それだけのことですが、影響は大きなものでした。
どこから来たのか

もとは dotCloud という PaaS スタートアップの社内ツールでした。LXC (Linux Containers) のラッパーとして作られたもので、2013年の PyCon US で Solomon Hykes がデモしたのが最初の公開です。オープンソースとして出た後の広がり方は、社内ツールの想定を完全に超えていました。
なぜ VM ではなくこちらが残ったか
当時の標準は VMware や VirtualBox のような仮想マシンでした。違いは単純です。
- VM: ゲスト OS を丸ごと積む。サイズは GB 単位、起動に分単位。
- コンテナ: ホストのカーネルを共有する。サイズは MB 単位、起動はミリ秒。
コンテナ技術自体は Docker の発明ではありません。LXC も cgroups も先にありました。Docker がやったのは、それを Dockerfile という一枚のファイルと数個のコマンドに落とし込んだことです。使える人の数が一気に変わりました。
何を入れるか
Mac や Windows で動かすにはランタイムが要ります。
- Docker Desktop: 公式。機能は一通り揃っていますが、常駐時のリソース消費は軽くありません。
- OrbStack: Mac 向け。起動が速くメモリも控えめで、Docker Desktop からの移行もほぼそのまま通ります。Mac ならこちらを試す価値があります。
最初に覚えるコマンド
動作確認
docker run hello-world
ローカルにイメージがなければ Docker Hub から取得し、実行してメッセージを出して終了します。数秒で終わります。
Web サーバーを起動する
docker run -d -p 8080:80 --name my-nginx nginx
-d はバックグラウンド実行、-p 8080:80 は手元の 8080 番をコンテナの 80 番に繋ぐ指定です。http://localhost:8080 で Nginx の初期ページが出ます。ホストに Nginx は入っていません。
状態を見る、中に入る
docker ps docker exec -it my-nginx bash
docker ps は起動中のものだけを出します。落ちたコンテナを探すときは -a を付けてください。デバッグでは、なぜ落ちたのかを docker logs my-nginx で見るほうが早く済みます。
片付ける
docker stop my-nginx docker rm my-nginx
Dockerfile
手打ちのコマンドは再現できません。イメージの作り方はファイルに書きます。
FROM node:20-alpine WORKDIR /app COPY package.json . RUN npm install COPY . . CMD ["npm", "start"]
FROM は土台のイメージです。alpine は Alpine Linux ベースの軽量版で、イメージサイズがかなり小さくなります。
WORKDIR はこれ以降の作業ディレクトリです。存在しなければ作られます。
COPY package.json . と COPY . . が二回に分かれているのが、この Dockerfile で一番重要なところです。Docker は行単位でキャッシュを持ち、ある行の入力が変わるとその行以降を全部やり直します。ソースコードを先に全部コピーしてしまうと、コードを一文字直しただけで npm install からやり直しになります。変更頻度の低いものを先に置く、というのがこの並びの理由です。
CMD は起動時に実行されるコマンドで、これが終了するとコンテナも終了します。
ビルドします。
docker build -t my-app .
複数のコンテナをまとめる
実際のアプリには DB もキャッシュも要ります。docker run を並べて管理するのは現実的ではないので、Compose に書きます。
# compose.yaml services: web: build: . ports: - "3000:3000" db: image: postgres environment: POSTGRES_PASSWORD: password
docker compose up で全部立ち上がります。サービス名がそのままホスト名になるので、web からは db という名前で Postgres に接続できます。
なお、上の例はローカル用です。パスワードを直接書いているので、そのまま本番に持っていってはいけません。