自分の機械では動いたのに
ソフトウェアで最も古い文の一つがある。自分の機械では動いたのに。
昔のデプロイは単純だった。自分のコンピュータで作ったファイルをサーバーにそのまま上げれば、人々はそれを見た。だがこの方式には黙った前提があった。自分の機械とサーバーの環境が同じだという前提である。
実際には違う。OS が違うか、同じ OS でもバージョンが違うか、入っている道具のバージョンが違う。最初に上げるとき合わせておいても、時間がたてばずれる。コードは同じで土台が違うので、ここでは動きあちらでは動かないことが起きる。
直すのも難しい。いくらコードをにらんでも、問題がコードにないからだ。
だから土台ごと移す
発想は単純だ。環境が違うことが問題なら、環境ごと一緒に移せばよい。
プログラムだけを移すのではなく、それが動いていた土台を一緒に取って一つの包みにする。どの OS の上でどの道具のどのバージョンと一緒に動いていたかが、その包みの中に全部入る。
その包みをイメージといい、イメージを立ち上げて実際に動く状態をコンテナという。この方式全体が Docker である。
こうするとデプロイが変わる。ファイルを一つずつ上げて上書きする代わりに、コンテナを丸ごと入れ替える。新しい包みを立ち上げ、古い包みを降ろす。まずければ古い包みをまた立てればよい。
以前 自分のコード ──────────────────▶ サーバー
(サーバーの環境はサーバーの事情)
今 自分のコード + それが動いていた環境 ──▶ イメージ ──▶ コンテナとして実行
(土台が同じなので、ここで動けばあちらでも動く)移すときだけのものではない
バイブコーディングをしているうちに、ある日コンピュータにクジラのアイコンが入っていたのを見た人がいるだろう。たいていこの用途である。
他人が作ったイメージを受け取り、自分の機械でそのまま立ち上げられるからだ。データベースを例に取れば、前回見た PostgreSQL を自分の機械に直接入れるのではなく、イメージで受け取ってコンテナとして立てる。導入の途中で起きうる問題を丸ごと飛ばせる。
使い終わればコンテナを降ろせばよい。自分の機械にはほとんど跡が残らない。複数のプロジェクトが違うバージョンを求めても互いにぶつからない。
つまり Docker はデプロイの道具であると同時に開発環境の道具でもある。以前、自分の機械もサーバーになれると述べたが、そのサーバーを何台も並べて立てる方法でもある。
Kubernetes、そして Dockerfile を一度開く
包みが一つなら管理することは少ない。複数になると事情が変わる。どれを何個立てるか、一つ落ちたらいつ立て直すか、要求が集まったら何個まで増やすかを決めなければならない。
その仕事をするのが Kubernetes だ。字数が多いので K と s の間の八文字を略して K8s と書く。規模が大きくなったサービスで使う道具であって、最初から要るものではない。
デプロイを自動で回す話もここに付く。コードをリポジトリへ上げれば、勝手にビルドし検査し新しいコンテナに入れ替えるようにしておける。この自動の流れを CI/CD と呼ぶ。
今すぐ試せることが一つある。プロジェクトの最上部に Dockerfile というファイルがあるか見て、あれば開いてみることだ。入れて、ビルドして、束ねる順序が十行ほど書かれている。デプロイのボタンを押して数分待つあいだに何が起きているかが、そこに全部ある。
FROM node:22 ← どの土台の上から始めるか
WORKDIR /app ← どのフォルダで作業するか
COPY package.json . ← 何を包みに入れるか
RUN npm install ← 何を入れるか
COPY . .
RUN npm run build ← 何をビルドするか
CMD ["npm", "start"] ← 立ち上がったら何を動かすか
デプロイにかかる数分は、これらの行が順に実行される時間だ九回を一本の線に
ブラウザがサーバーへ要求を送り、ファイルを受け取り、画面を描くという一本の線から出発した。
ブラウザが読むファイルは三つ。要求は IP とポートで行き先を決め、ドメインがそれを名前に書き換える。届いた要求に何を返すかを決めるのがウェブサーバーで、返ってきたものを描くのがフロントエンド、返すものを作るのがバックエンドだ。値はデータベースに、ファイルはストレージと CDN に積まれる。そしてこの全体を別のコンピュータへ移すときにコンテナを使う。
この順番を知っていれば、次に出会う見慣れない名前も、どこに付くのかから問える。それがこの九回の目的だった。
