第46章:CMD(起動コマンド)▶️
この章のゴール🏁
- Dockerfileの
CMDが「起動したときにデフォルトで何を実行するか」を決めるものだと説明できる🙂 CMDの おすすめの書き方(exec形式) を使って、Todo API をちゃんと起動できる🚀- 「一時的に別コマンドで起動する(上書き)」ができるようになる🎮
1) CMDってなに?ざっくり一言で😄📝
CMD は 「このイメージを起動したら、基本はコレを実行してね」 という “デフォルト起動コマンド” を決める命令だよ▶️
ポイントはこれ👇
- Dockerfileの 最後の
CMDだけが有効(前に書いたのは上書きされる)🧹 docker runで 起動時にコマンドを指定するとCMDを上書きできる🎯RUNと違って、CMDはビルド時に実行されない(起動時に効く)⚡
これらは公式のDockerfileリファレンスにまとまってるよ📚(Docker Documentation)
2) CMDの書き方は3つある(でも初心者は2つ覚えればOK)🧠✨
Dockerfileの CMD には代表的に3パターンあるよ👇(公式定義)(Docker Documentation)
- exec形式(推奨) ✅
- 例:
CMD ["node", "dist/server.js"] - “配列(JSON)”で書くやつ。シグナル(停止指示)が届きやすくて安定🧯
- exec形式(ENTRYPOINTへのデフォルト引数) 🧩
- 例:
CMD ["--port", "3000"] ENTRYPOINTとセット運用する時に使う(この章では「そういう使い道もある」くらいでOK)🙂
- shell形式(非推奨寄り) ⚠️
- 例:
CMD node dist/server.js - 実は内部的にシェル経由になりやすく、停止シグナルがアプリに届かない事故などが起きやすい…😵
迷ったら exec形式だけ覚える でOK!🙆♂️
3) なんでexec形式が推奨なの?(超重要:止め方がきれいになる)🧯🛑
コンテナを止めるとき、docker stop みたいな停止操作は PID 1(コンテナの一番えらいプロセス) にシグナルを送るのが基本だよ📌
でも shell形式やシェルスクリプト経由だと、シグナルが子プロセスに転送されず、アプリが SIGTERM を受け取れないことがあるんだ😱(Snyk)
さらに Docker のCLIリファレンスにも「PID 1 の扱いは特殊で、デフォルト動作のシグナルが無視されることがある」って注意があるよ🧠(Docker Documentation)
なので、この章では exec形式で、アプリ本体を “直に起動” する を基本ルールにするよ✅
4) ハンズオン:Todo API を CMD で起動させる▶️🧪
ここからは「Todo API(Node/TS)」を想定して、よくある2パターンを作るよ😊
(どっちを選ぶかは、今のプロジェクトの package.json の scripts 次第!)
パターンA:ビルド済み(dist)を node で起動する(おすすめ)🏆
TypeScriptを dist/ に出して起動する構成なら、これが一番スッキリ✨
Dockerfileの最後に👇を置く:
CMD ["node", "dist/server.js"]
コツ🧠
-
配列の各要素は「1引数」だよ!
- ✅
["node", "dist/server.js"] - ❌
["node dist/server.js"](これだと “1個の文字列” 扱いになって事故りがち)
- ✅
動作確認コマンド例👇
docker build -t todo-api:cmd .
docker run --rm -p 3000:3000 todo-api:cmd
パターンB:npm script で起動する(開発寄り)🛠️
package.json に "start" や "dev" があるなら、こういうのも定番!
CMD ["npm", "run", "start"]
または dev なら:
CMD ["npm", "run", "dev"]
※「停止がキレイに伝わる」観点では、最終的に node 直起動 が好まれやすいよ(特に本番)🙂 このへんの “開発用/本番用の分離” は次の章でちゃんとやる予定🎭
5) 「CMDを上書きして1回だけ別コマンド」やりたい!🎮✨
ここが CMD の気持ちよさポイント😆
docker run はこういう形👇で、イメージ名の後ろに書いたコマンドで上書きできるよ(Docker Documentation)
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
例:いつもの起動じゃなくて、1回だけテストを回す🧪
docker run --rm todo-api:cmd npm test
例:1回だけバージョン確認する🔎
docker run --rm todo-api:cmd node -v
例:コンテナの中身を確認する(シェルで入る)🕵️♂️
docker run --rm -it todo-api:cmd sh
6) いまこのイメージ、何が起動する設定なの?を確認👀🧾
「これ CMD 効いてる?」って迷ったら、inspect で確認できるよ🔍
docker image inspect todo-api:cmd --format "{{json .Config.Entrypoint}} {{json .Config.Cmd}}"
CmdがCMDEntrypointがENTRYPOINT
7) おまけ:停止・ゾンビ対策で “init” を入れる話(必要になったらでOK)👻🧯
プロセス周りが気になってきたら、--init で コンテナ内PID 1に init を置く手があるよ。
Docker公式に「ゾンビプロセス回収など init の責務を担う」って説明がある✅(Docker Documentation)
例:
docker run --init --rm -p 3000:3000 todo-api:cmd
この章では「そういう武器もある」くらいでOK!🧰
8) AI活用プロンプト例🤖✨(コピペOK)
- 「この
package.jsonの scripts を貼るので、コンテナ起動に最適なCMDを exec形式で提案して。dev/start の2案ほしい」 - 「このDockerfileの
CMDが原因で起動しない可能性ある?チェック観点を箇条書きで」 - 「
docker run IMAGE ...でCMDを上書きする例を、テスト/マイグレーション/シェルの3つで作って」
9) ミニ演習📝🎯
CMD ["node","dist/server.js"]にして起動できるか確認する🚀docker run ... node -vでCMDを上書きできるか試す🔁- わざと shell形式
CMD node dist/server.jsにして、違いを体験してみる(戻すの忘れずに!)⚠️
次の章で「開発用と本番用は別」🎭に入るから、ここで CMD の感覚がつかめると超ラクになるよ😆✨