現代のフロントエンドエンジニアリングは、10年前とは全く異なります。単にHTMLやCSSを書くだけではありません。現在の典型的なプロジェクトには、特定のNode.jsランタイム、固定されたパッケージマネージャーのバージョン、複雑に絡み合ったビルドツール、そしてすべてが完璧に整っていることを前提としたデプロイパイプラインが含まれています。最初の npm install から最終的なプロダクションビルドまでのどこかで、小さな差異が入り込みます。チームメイトはNode 20を使用しています。あなたはNode 18を使用しています。あなたのマシンにあるグローバルなCLIツールが、他の人のマシンでの依存関係の欠如を隠してしまいます。そして、誰も聞きたくないあの言葉が飛び出します。「自分のマシンでは動くんだ。」
Dockerがフロントエンドのツールキットにおいて確固たる地位を築いている理由は、その不確実性を取り除いてくれるからです。Dockerは、アプリケーションを、実行に必要な正確なランタイム、システムライブラリ、および依存関係とともにパッケージ化します。Windowsでコーディングしていても、macOSからリリースしていても、Linuxのクラウドインスタンスにデプロイしていても、動作は同一に保たれます。
なぜフロントエンド開発者が注目すべきなのか
Dockerが解決する問題点は抽象的なものではありません。それらは毎スプリントのように発生します。
バージョン競合は時間を浪費させます。あるレガシーなクライアントプロジェクトではNode 18が必要で、個人のサイドプロジェクトではNode 20が必要、そして新しいスタートアップの業務ではNode 22が必要、といった状況です。コンテナがなければ、これらをバージョンマネージャーで管理することになります。それは、うまくいっている間はいいのですが、そうでない時もあります。npmのマイナーバージョンの不一致がピア依存関係(peer dependencies)の解決方法を変えてしまい、他の人の環境では問題なく動くのに、自分の環境ではビルドが壊れるといったことが起こり得ます。フレームワークが新しいリリースを発表したとき、フィードバックループが「2時間の再インストール作業」であってはなりません。それは「1つのファイルの変更とコンテナの再起動」であるべきです。
グローバルパッケージも、目に見えない摩擦を生む原因となります。半年前にインストールしたAngular CLI、Expo、またはPrismaがグローバルに残っているかもしれません。新しい開発者が同じツールを新規にインストールすると、異なるバージョンが入ります。すると突然、ビルドスクリプトが他の場所では表示されない警告を出し始めます。Dockerは、すべてをプロジェクトローカルに保つことでこれを解決します。DockerfileでNodeのバージョンを定義します。依存関係はホストのオペレーティングシステムから隔離された状態で、コンテナ内でインストールされます。あなたのラップトップがmacOS、Windows、あるいはUbuntuであっても、アプリケーションは常に全く同じ環境を参照します。
オンボーディングのメリットも無視できません。新しく入ったメンバーは、Homebrewのインストール、nvmのエイリアス、グローバルな権限修正などを網羅した3ページにわたるREADMEを読む必要はありません。Dockerをインストールし、リポジトリをクローンして、コマンドを1つ実行するだけです。かつては午後いっぱいかかっていたセットアップが、数分に短縮されます。そしてプロジェクトを切り替えても、何も残りません。孤立したグローバルツールも、PATHの優先順位を争うバージョンマネージャーもありません。彼らのローカルマシンはクリーンなまま保たれます。
イメージとコンテナ:基本概念
Dockerが初めての方でも、用語は聞いた目よりもシンプルです。Dockerイメージは設計図です。これにはソースコード、Node.jsランタイム、ロックファイル、およびアプリの実行に必要なすべての依存関係が含まれています。コンテナは、そのイメージから作成された実行中のインスタンスです。イメージをレシピ、コンテナを実際の料理と考えてみてください。1つのレシピから同じケーキを100回焼くことができます。ホストコンピュータに何がインストールされているかを気にすることなく、1つのイメージから同一のコンテナをいくつでも立ち上げることができます。
実践的なDockerfile
具体的な出発点を見てみましょう。もしあなたが
