「ローカル開発環境」というその幻想に惑わされないための道しるべ

# この記事は誰向けのものか

- 各作業者のPCで仮想サーバーを動かす「ローカル開発環境」と呼ばれる手法に興味がある、やってみたい。快適な開発が行えると聞いた
- 既にローカル開発環境に相当するものを導入済みだが、使いこなせない。もっとうまくなりたい
- ローカル開発環境にあたるものを運用しているつもりだが、どうにもスムーズに進まない。理想が実現できているのか疑わしい
- 絶賛トラブル発生中。なんとかしたい

# この記事は誰向けのものではないか

- 「仮想マシンとか環境構築とか、難しいからよくわかんない他の人にやってほしい」という方
- 「この春入社したばかりの新人です。たくさん情報を渡されても善悪の判断はまだつきません」という方
- 「我社は既に完璧な開発スキームを完成させており、業務に何ら支障は起きていない、大丈夫だ」という強い自負のある方

# この記事を書くに至った経緯

弊社でUnityのゲームアプリと連携するWebサービスを構築する際に、「Dockerでローカル開発環境を構築して開発の画一化や効率化を図りたい」という申し出があった。それに対する問題点については事前によく熟知していたのではあるが、開発チームに経験者が少なく、**まずは体験してみて痛い目を見なければわからない**というのを察したので了承。その顛末を教訓・教養として書き記そうと筆を執った次第。

はじめに、「プロビジョニング」という言葉が日本のIT企業に浸透し始めた頃より、VagrantやDocker(compose)を利用して「手元のPC1台でWebアプリケーションをサクサク開発できるらしい」「別途サーバー建てないでいいなんて最高じゃん、ケンカも起きないし」という評判が独り歩きしはじめた。巷には「やってみた」という導入の簡単さを称賛する記事やそれによって成功した事例のストーリーテリングが溢れているが、失敗談や実地検証といった類の情報はあまり表には出てこない。

この記事はいち現場監督者での視点から、「ローカル開発環境」という風化した幻想に一石を投じるものである。仮想マシンを利用した開発に好意的な印象を持つ方は本記事を読んでこれからの未来に注意されたし。
なお、件は各々の作業者が開発に着手することが困難になり、インフラ担当者が社内スタッフのための保守対応に追われ、進捗の遅れから炎上している。

# それぞれの障害ケース

## 💀障害ケース１：「起動させたらエラーが出て進みません」という問い合わせが同じ原因で全社員から殺到する
:::note warn
- 発生要因：`.gitignore` に指定されているディレクトリやファイルに起因する、サーバー設定の不備
- 解決方法：`.gitignore` に指定されがちなものを特定し、以下のいずれかの対応を取る。
    - `node_modules`がignoreされている場合、`npm install`
    - `vendor`がignoreされている場合、`composer install` または `composer update`
    - `.env`ファイルの再作成
    - `[L]ogs`ディレクトリがignoreされている場合、それを解除して代わりに`*.log`を登録し、ディレクトリがちゃんと共有されるようにする
    - ignoreされているファイルやディレクトリのignore解除を検討
:::
### 解説
Docker-composeによるプロビジョニングを実施した直後にインフラ担当者が直面するのがこの「社内カスタマーサポート」の憂き目である。プロジェクト開始とほぼ同時期に納品日さながらの質問と設置業務に追われ、用意したドキュメントも目を通されずに「困ったら〇〇君を呼ぼう、コミュニケーションにもなるし」という短絡的な理由で一日中カスタマーサポートをする作業コストが発生し、激務にもかかわらず給与には反映されない。

対処法を丁寧に教えることでそれぞれの開発者の知識レベルは上がっていくが、それでも毎年新人が入ってくるような活発な現場では毎年の恒例行事のようになり疲弊は免れない。「30人体制でやるからそれぞれのPCに環境構築してくれ」なんていう指示が飛ぼうものなら、問い合わせに一日中対応するコールセンターのスタッフのような業務をこなさなければならない。

この問題が起きる背景には、Node.jsの文化の存在がある。本番環境と実験環境とで変えなければならない環境変数ファイル（`.env`）や、ファイルの総数が4桁～5桁に及ぶためにgithubで管理しない決定が下されがちなnode.js向け拡張機能フォルダ（`node_modules`）がほとんどの場合にとっての原因になっている。同じ経緯でlaravelやRuby on Railsの拡張機能フォルダ（`vendor`）もgithubで管理しないものとして挙げられやすく、原因になりがちである。

Webアプリケーションの動作に必須な拡張機能、プラグイン、モジュールの類がgithubで共有されないことにより、「モジュールの参照エラーを解決するために `npm install` が必要」といった情報共有、通達、作業フローの構築が必須になってしまう。これが改善されない限り、社内カスタマーとなってしまっている他のプログラマーやプランナー、デザイナー達のためにサーバーサイド担当やインフラ担当は社内業務がストップしないよう保守作業をやらされる羽目になる。

これを減らして開発スピードを速めるためには、ローカル開発環境に関わる職種や人員を絞ることが望ましい。

## 💀障害ケース２：コンソールとかターミナルとかシェルとかCLIとか言われてもわからない
:::note warn
- 発生要因：ローカル開発環境を活用するメンバーにクライアントサイド一辺倒のエンジニア、プランナー、デザイナーなどが含まれている
- 解決方法：CLIに頼らなくても操作を行える代替案やツールを検討する。またはCLIに関する勉強会を行う
:::
### 解説
そもそも「コンソール」とか「ターミナル」とか「シェル」とかいった単語でウキウキできる人間はどちらかというと技術屋よりかはマニアである。「バーニア」「ファンネル」「サイコフレーム」と聞いて頷く人々がロボット工学博士でないのと同じだ。CLIの世界はそのワードや文化、歴史にロマンやカッコよさ、強さ賢さを感じるマニアの情熱によって支えられている。

とはいえ、サーバー担当ではないスタッフに「これこそがサーバーだ！覚えるんだ楽しいぞ！」と布教しても仕方がない。代替案を練ったりCLIを使いこなすための勉強会を開いたりして、互いの作業ストレスを無くすのが幸せへの第一歩である。可能ならこういった、抵抗が強いがために熱量が高くなる学習コストは減らしていき、溝を吸収するクッション役の人員を据えて、腫れ物に触らない人を作っていくほうがよい。最終的にはシェルを極力触らなくても作業ができるようにインフラ担当者が尽力したほうがよい。

## 💀障害ケース３：コンソールを開いたら「#」だけ表示されてどこで何をしているのかわからない
:::note warn
- 発生要因：Linuxディストリビューションに関する知識が不足している
- 解決方法：下記のコマンドをお守りだと思って日常的に使って体に覚え込ませる
    - `bash` 比較的広まっていて機能性もあるシェル「bash」の起動を試みる（※Debian系）
    - `pwd` 現在のディレクトリを表示
    - `ls -la` 現在のディレクトリの隠しファイルを含むファイル一覧を表示
:::
### 解説
Dockerコンテナを起動して、何かしら操作を行ってみたという節目に立った時に新米エンジニア達を絶望の淵に叩き落す、UI/UXの欠片もない画面が次のものである。

```
# 
```
これでいったい何をすればいいというのか？そもそもこの画面は何なのか？謎だらけの暗闇に放り出された人々に私が示せる道は、たいまつと地図とコンパスにあたるお守りのコマンド達だ。

まず、この画面は「シェル」という分類のアプリケーションがファイルとフォルダのナビゲーションのために表示している画面だ。その中でもbash（バッシュ）はいくつものLinuxディストリビューションで採用されている、標準的でわりと親切なほうのシェルだ。Debian系のOSを採用しているDockerコンテナは`bash`と入力してEnterを押すと、`/bin`フォルダなどからbashの実行プログラムを探し出して起動してくれる。これにより、絶望の暗闇は次のように変化する。

```bash
root@3dd18ff1e230:/var/www/html# 
```
bashは先ほどの不愛想なシェルと比べて、`<ユーザー名>@<接続PC名>:<ディレクトリ>`というルールで現在の状態を示してくれる。上記の場合、ユーザーがroot、PC名が3dd18ff1e230、指しているディレクトリは/var/www/htmlということになる。これさえ理解できれば「誰がどのディレクトリを操作しているのか」がわかって一安心だ。明かりは灯された。

だが、Linuxディストリビューションによってはbashを採用していないものもある。そういったときには`pwd`コマンドを使用すると、現在の階層を表示してくれるため現在位置の把握に役立つ。
```
# pwd
/var/www/html
```
現在のディレクトリに何があるのかは`ls -la`コマンドで確認できる。こまめに確認してフォルダやファイルの操作を間違えないようにしよう。

```
# ls -la
total 172
drwxr-xr-x   1 root root   4096 Apr 13 12:42 .
drwxr-xr-x   1 root root   4096 Apr 13 12:42 ..
-rwxr-xr-x   1 root root      0 Apr 13 12:42 .dockerenv
lrwxrwxrwx   1 root root      7 Mar  8 02:05 bin -> usr/bin
drwxr-xr-x   2 root root   4096 Apr 18  2022 boot
drwxr-xr-x   4 root root   4096 Mar 16 03:52 data
drwxr-xr-x   5 root root    340 Apr 13 12:42 dev
drwxr-xr-x   1 root root   4096 Apr 11 22:11 docker-entrypoint-initdb.d
drwxr-xr-x   1 root root   4096 Apr 13 12:42 etc
drwxr-xr-x   2 root root   4096 Apr 18  2022 home
...
```


## 💀障害ケース４：ファイルを編集しようとしたらテキストエディタがない
:::note warn
- 発生要因：Linuxの文化的にLinux向けの新しいテキストエディタが生まれないため、`vi` 以外のテキストエディタが採用されていない
- 解決方法：採用されている `vi` の使い方を覚える。または `vim` や `nano` のインストールを試みる
:::
### 解説
Linuxは長らくコマンドライン・インターフェースでのみの運用が行われてきた歴史があるため、古くに開発されたシェル「sh」やテキストエディタ「vi」を今でも現役運用している。そしてLinux愛好者はそれをより使いやすいアプリにアップデートすることをあまり好まない。

近年になってようやく、MicrosoftとCanonicalが手を組んだことにより、「UbuntuはWindows感覚で使えるLinux」という刷り込みが徐々に浸透している。かつてはグラフィック性能など求められなかったサーバーマシンにRyzen7を積み、GnomeのデスクトップGUIやSteamでのゲーミングなどが楽しめるような時代がついに到来した。Ubuntu Desktopを普段使いする身であればテキストエディタは専ら「gedit」だ。UbuntuならVS Codeもインストールできる。わざわざCLIを使ってviやnanoなんていうのは、もはや趣味の範疇だ。

だがDockerコンテナを使う場合には、それらのテキストエディタを扱う必要が出てくる。せっかくなら「vi」や「vim」「gvim」の使い方を覚えたいという気持ちもわからんでもないが、筆者はUbuntuに標準搭載されており比較的理解しやすいnanoをおすすめしておく。例えばDebian系のコンテナであれば`apt install nano`で導入できる。

Emacs？その話はまた今度にしよう。

## 💀障害ケース５：アプリのインストール方法がわからない
:::note warn
- 発生要因：Linuxディストリビューション毎の差分に関する知識が足りていない
- 解決方法：下記のコマンドを試しに入力し、パッケージマネージャーが何なのかの特定を行う
    - `apt update`
    - `apk update`
    - `yum update`
    - `pacman -Syy`
:::
### 解説
次項の障害ケース６とも関連するが、Linuxはディストリビューションごとにパッケージマネージャーのアプリが異なる名前で用意されている。ユーザーにとっては「いつものaptコマンドが使えない？？」と混乱のタネを生みやすい話題だ。

解決方法として挙げている4つのコマンドは、比較的有名なディストリビューションのパッケージマネージャーのリスト更新を促すコマンドである。Windowsで言えば「Windows Update」、Gitで言えば`git fetch`だと思ってもらえばよい。

補足程度に記載しておくと、`apt`および`apt-get`はDebianやUbuntu、`apk`はAlpine、`yum`はCentOSやRedhat、`pacman`はArchの標準パッケージマネージャーである。いずれかで動作したら、そのコマンドでインストールを試みればよい。

## 💀障害ケース６：DockerコンテナのOSの詳細を確認できない
:::note warn
- 発生要因：DockerfileやDockerHubのドキュメントを読む文化がない、読む必要性が出てこない
- 解決方法：`cat /etc/os-release` でOSの情報をターミナル上に表示するのが手っ取り早い
:::
### 解説
Dockerコンテナは便利便利と言われるが、Linuxに詳しくないメンバーが触るにはかなりハードルが高い。その大きな理由はOSがわからず、情報を得られないからである。

Dockerfileや[DockerHubのImage Layer Details](https://hub.docker.com/layers/docker/getting-started/latest/images/sha256-d819f321a1850678676fc16cdf8d80f3041a3407285856ba59cf6235bbdbb9dd?context=explore)などを見れば一応解決するが、手っ取り早いのは`cat`コマンドで`/etc/os-release`を閲覧することである。
```sh
/ # cat /etc/os-release
NAME="Alpine Linux"
ID=alpine
VERSION_ID=3.8.1
PRETTY_NAME="Alpine Linux v3.8"
HOME_URL="http://alpinelinux.org"
BUG_REPORT_URL="http://bugs.alpinelinux.org"
```

## 💀障害ケース７：どれサーバーエンジニアの俺に貸してみろフフン、と思ったら`sudo`ができない
:::note warn
- 発生要因：採用したコンテナのOSがAlpine Linux
- 解決方法：以下のいずれかの対応を取る
    - `sudo`が必要ない設計でやり直す
    - OSが異なる同じ機能のコンテナを探す
    - `apk add sudo`のあとでユーザー権限を操作し、sudoコマンドを使えるようにする
:::
### 解説
Dockerコンテナに採用されているOSはある程度絞られるが、その中でも採用率が高いのは [Alpine Linux](https://www.alpinelinux.org/) と [Debian bullseye](https://www.debian.org/releases/bullseye/) のようだ。Alpineの場合、sudoを実現するアプリケーションが入っていないため、sudoコマンドが使えない。

こちらについてはAlpineでググってもらえれば有識者の情報がいくつも手に入るので、Dockerfileに記述するなどして対策するとよい。

https://www.alpinelinux.org/

https://www.debian.org/releases/bullseye/

## 💀障害ケース８：「安全な接続ではありません」という旨のエラーが解決できない
:::note warn
- 発生要因：Google ChromeをはじめとするWebブラウザが非SSLの通信を遮断している
- 解決方法：社内向け開発環境であったとしてもLet's Encrypt等を利用してSSL通信を可能にする。Localhostについてはhttpでの通信のみでやり取りできるように独自の設定ファイルを組む
:::

### 解説
本件のメインテーマ。主要ブラウザであったGoogle Chromeが2021年頃に「http通信は安全ではないからブラウザ側で遮断するよ」と発表したことにより、Webアプリの開発現場には激震が走った。これまでhttpsなんて本当にセキュリティを守らなければならない本番環境やステージング環境でしっかり守れていればよかったものが、クローズな開発環境だろうがSSL通信でやれと通告されたのである。

https://www.chromium.org/Home/chromium-security/marking-http-as-non-secure/

これにより社内向けの開発環境ですらhttpsの対応が必須となり、余波として「localhostへのSSL通信がブロックされるので、localhostへhttps通信を行う方法を教えてください」という、驚愕の質問やノウハウが急速に広まった。ある種のバッドノウハウであるのだが、これにより危機を脱し事なきを得たWebサービス開発者はこの事態を悪くは言えない。

この問題に関しては、httpで通信できるようにlocalhost向けに独自の設定や環境変数を作るべきである。それが難しいのであれば、共同でアクセスする自社サーバー、またはロリポップ、さくらのVPSなどのレンタルサーバーを使ってローカル開発環境を捨てた開発フローを構築したほうがまだ生産的だ。

スキルやプロジェクトの傾向によって最適な開発手法には諸説ある。だが、GoogleやMozillaがhttpを締め出した2年後である2023年の今、Webサービスのローカル開発はどれもが正解とはいえない状況が続いている。

## 💀障害ケース９：ChocolateyやXAMPPといったWindows環境を簡単に汚すツール群の撤去、無効化に苛まれる
:::note warn
- 発生要因：Windowsで開発しており、LocalhostでHTTPS通信が必要になった際に上長が「ggrks」と言って放置している
- 解決方法：Windowsで開発しているメンバーに対して、インフラ担当者が目を光らせておく。前項の「Localhostではhttp用の設定ファイルを組む」をチーム内で徹底する
:::
上記の「Localhostでhttps接続」に関わる内容だが、「XAMPPを導入して解決しましょう」というナレッジが世間に広く流布されている。かつてはそのような方法で開発を行うことは選択肢の一つではあったが、DockerやVagrantを使って開発環境の統一を図ろうと試みる開発チームにおいてXAMPPの存在はレガシーの魔物かつ異物である。
ノウハウを学習して自己証明書などの取り方を身に着けるには良いかもしれない。しかし例えばhostsファイルを書き換える手法はWindowsの環境を著しく汚すし、XAMPPでインストールしたmysqlのサービスがホストOSの3306ポートを占有し、Dockerのmysqlの立ち上げを失敗させる問題も発生しやすい。そしてこれは、監督者が「ググったら解決策が見つかるはずだからそれでやってくれ」と放置することによって被害が拡大していく。

そして、「Chocolatey」はWindowsのアプリ管理マネージャーとしてMac OSのHomebrewと共に愛用されているが、その流れを断ち切ろうとMicrosoft公式が「Winget」を広めようとしており、従来の「msiでインストール」も重なってWindowsのアプリ管理は混沌を極めている。できるだけOSの設定が汚れるような選択肢は控え、トラブルを未然に防ぎたい。

https://learn.microsoft.com/ja-jp/windows/package-manager/winget/

## 💀障害ケース１０：ホストOSのユーザーがDockerコンテナで使用するファイルやフォルダを操作できない
:::note warn
- 発生要因：Windowsで開発しており、Docker-volumesを利用して共有ディレクトリを作っているため互いの権限設定に引っかかる
- 解決方法：コンテナの内部で動作するシェルスクリプトを組んでファイルやフォルダの権限を一括修正できるようにする
:::
### 解説
DockerHubで提供されているDockerコンテナは基本的にroot権限で動作する。Webサーバは一般的にwww-data権限で動作し、Windowsはログインユーザーの権限で動作し、Linuxのユーザーとは無関係。この3者（場合によりWSL2を含めた4者）がそれぞれファイルやフォルダの権限を取り合っている場合に問題が発生する。
例えばWindowsの「Owner」ユーザーが作成した「Logs」フォルダはwww-dataがアクセスできず、Laravelがエラーを起こす場合がある。dockerコンテナにアタッチして`php artisan make:migration`で作成したマイグレーションファイルはもれなくroot権限のファイルになり、Windows側で`git push`を試みてもエラーになってしまう。
この問題はファイルやフォルダを操作するだけで継続的に発生するので、Dockerコンテナ内で利用できるシェルスクリプトを組むなどしてスピーディに解決できるようにしておこう。

## 💀障害ケース１１：通信ポートとは何かを理解しはじめて、これで接続できるぞ！と思ったら接続できない
:::note warn
- 発生要因：マイクロサービスでのオーケストレーションとポートフォワーディングの知識が足りていない
- 解決方法：インフラ／サーバー担当で集まって設計を確認する、全員で各疎通確認ができるまで取り組む
:::
### 解説
単純にチームワークの問題であるが、インフラ担当者、Webアプリケーション担当者はそれぞれ通信ポートを予約しあわなければならない。

例えば「試しにアプリケーションを起動してみましょう。`http://localhost:3000`で接続できましたね！おめでとう！」といった技術記事が溢れている昨今、Ruby on RailsとNode.jsとの担当者がそれぞれポートフォワーディングの設定を「`3000:3000`」にしてしまい、ホストOS側ポートが競合する問題は発生しやすい。
その時に誰も監督せず行き当たりばったりで設計を行ったりすると、nginxのポートフォワーディングが「`80:80` / `8080:80` / `8088:80`」の3種類などカオスになっていったり、Dockerfileで`EXPOSE 9000`が指定されているphp-fpmのコンテナに「`9001:9001`」のフォワーディングが指定されてコンテナ側の9000と9001が両方空いたりする。隣の担当者を無関係と思わず、互いに情報を持ち寄るべきである。

## 💀障害ケース１２：複数のWebアプリが自分勝手なルーティングで開発される
:::note warn
- 発生要因：Docker-compose、nginx、node.jsなどサーバーを起動するアプリケーションの担当者同士でのすり合わせが不十分
- 解決方法：インフラ／サーバー担当で集まって設計を確認する、全員で設計書を書く
:::

### 解説
上記に同じチームワークの問題。`http://localhost/app1/login/`など、複数アプリケーションを想定したURIを各担当者がすり合わせもなしに設定すると、nginxの設定ファイルと折り合いがつかなかったりして面倒ごとになりやすい。

## 💀障害ケース１３：気がついたらお気に入りの作業ツールを起動できない、とにかくOSの動作が重い

:::note warn
- 発生要因：Dockerコンテナの使いすぎによるメモリ枯渇
- 解決方法：ホストOSのメモリを解放する、Windowsの場合はPowershellで `wsl --shutdown` を入力してWSL2の終了と再起動を行う
:::

### 解説
「Dockerは軽くて速い」などと評判になったが、Virtualboxなどに比べて比較的軽いだけでホストOSへの負荷が軽いわけではない。複数のコンテナを運用するとそれだけで数百MB、あるいは数GBのメモリをあっという間に消費する。

LinuxでDockerを活用すると、複数のコンテナを起動してもせいぜい1GB～2GBで消費はおさまるが、WindowsではWSL2を土台に使うため、輪をかけてメモリ消費が大きくなる。WSL2が不調なときは `wsl --shutdown` のコマンドで終了～再起動を行うと解消されることが多いので、覚えておこう。
WSL2は「vmmemWSL」という名前でリソースモニターに表示される。動作が重い時は要チェック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391505/f6448fc4-6f5a-52e5-33e7-0d377e0d267b.png)


Docker Desktopをお使いの方は、拡張機能の「[Resouce Usage](https://hub.docker.com/extensions/docker/resource-usage-extension)」を導入すると幸せになれる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391505/04bea2e0-0d15-8bff-7a5f-a364ed9f0bf1.png)


## 💀障害ケース１４：他のスタッフは問題が起きてないのに、自分の環境だけ動作がおかしい
:::note warn
- 発生要因：一度構築したDockerイメージが古いままのソースコードで動作している、あるいはDockerを動作させる土台のOSがバグっている
- 解決方法：以下のいずれかの方法でやり直す
    - `docker-compose build --no-cache`でキャッシュを使わずにDockerイメージを再ビルドする
    - `docker-compose down --rmi all --volumes --remove-orphans` でDockerイメージとボリュームを完全破棄してやり直す
    - Dockerボリュームで共有しているデータベースのディレクトリ（`mysql/db/`など）を削除してデータベースを作り直す
    - Windowsの場合はPowershellで `wsl --shutdown` を入力してWSL2の終了と再起動を行う。ダメならホストOSごと再起動を行う
:::

### 解説
Dockerは以前に作ったDockerイメージを使いまわすキャッシュ機能がある。そのキャッシュの関係で、コンテナ内部のソースコードは新しいのにコンテナが参照する通信ポートやURLが異なる…などの現象が起きた人はエラーになってしまう。
また、Dockerボリュームを使ってmysqlコンテナの中身をホストOSに共有するナレッジなどもあるが、その場合はデータベースの内容に変更があるたびにテーブルをDROPして再度マイグレーションをかけるなどの手間が必要である。どのような条件でキャッシュが利用されるのかなどの学習は別途行うとして、とりあえず異変が起こったら諸々を作り直すのが安心。

Dockerイメージのキャッシュを使わずに再ビルドしてコンテナを再起動するには、次のコマンドでDocker-composeを起動するとよい。
```powershell
docker-compose build --no-cache
```

## 💀障害ケース１５：そもそもDockerのメリットを感じられない。VirtualBoxと何が違うのかわからなくなってきた
:::note warn
- 発生要因：プロジェクトのシステム構成や採用アプリケーション、フレームワークのそもそもの肥大化
- 解決方法：プロジェクトの設計を見直す、マイクロサービスが本当に有効なのかを検証する、Dockerでの開発、運用をやめる
:::

### 解説
一時期は「仮想マシンとコンテナ技術は違う」といった見出しで原理やスペックの違いを声高に布教する記事などが広まったが、現実的には運用はそれほど変わらず、扱いの難しさや取り回しの悪さ、必要なアプリを揃えていくとVirtualboxで仮想マシンをチューニングするのと大して開発スピードが変わらない点などアラが目立ってくる。
酷くなってくると、Nuxt.jsだけで完結するはずのものにnginxコンテナとphpのコンテナをかませるような無駄の多い構成から抜け出せなくなったり、最終的にはnginx + php-fpm(laravel & nodejs)を合体させたコンテナなどを独自に作って「Dockerで使うことだけが目的の巨大なコンテナ１つ」をDocker-composeするような歪な開発環境が生まれたりなんかもする。

Dockerを使った環境構築は手軽で便利であるが、監督がいないとGitHubで無数にブランチが生まれるのと同じような収拾不可能な事態が発生しがちである。適切に運用できないのであれば、nginx + php + mysqlが揃ったオールインワンの仮想マシンをVirtualboxやMultipass、VM WareやWSL2などで作ってそれを配布したほうがあなたのチームに合っているかもしれない。

## 💀障害ケース１６：Amazon ECS（Elastic Container Service）にそのまま流用できるようでできない
:::note warn
- 発生要因：ECS担当者とDocker-compose担当者のすり合わせミス
- 解決方法：Docker-compose.ymlにあれこれ設定を追加せず、可能な限りDockerfileで定義する 
:::
### 解説
ECSではDocker-composeの代わりに「タスク定義」というものを設定して、ECRに登録されているコンテナを起動させる手順を踏むわけだが、GitHub Actionsなどを利用して自動デプロイを試みると、AWSの仕様に合わせたymlファイルを運用することになり、ローカル環境向けのDocker-compose.ymlは関係がなくなる。Dockerfileにできるだけ書き込むことでECRに設定を持ち越すことはできるが、「あちらを立てればこちらが立たず」にならないように対策を入念に取るべき。

可能であれば、本番環境を想定した構築はまず初めに検証を行っていつでも起動できるようにしておけば以後の心理的安全性が保たれる。

https://matsuand.github.io/docs.docker.jp.onthefly/cloud/ecs-compose-examples/

https://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/tutorial-ecs-deployment.html

# 総評

仮想マシンを使ったローカル開発環境の歴史は比較的浅いものであるが、2023年の現在においても、Webサービスを取り巻く環境は年単位で大きく変化を遂げている。日本において「聞いたことのあるアレ」は、すでに欧米や海外では問題が見つかっていたり対策が必要だったりするものである可能性は高く、広く知見が共有され流行していると感じられるものはすでに枯れて進歩のない技術、徒花となっている場合もある。そしてそれは以後の開発、保守において癌となりうる。例えば、かつてはjQueryがそうであった。

いくつかのライブラリやフレームワークの名を枯れた技術の代表として挙げたとして、「私はそれを間違っているとは思わない」と頑なな姿勢を取りたくなる方もいることだろう。しかしその隣で「まだCOBOLを使っているなんて…」「そろそろExcelから脱却したいのだが…」という呻き声が上がっているのも真実だ。信じるものを掲げ、それを押し通す頑なな姿勢はある種の「惰性」であって正解ではあるかもしれないが、他者に振りかざし権利を勝ち取る「正義」とは異なる。

かつて複数のPCを用意してネットワークとWebサービスを構築する開発環境はコストの高いものであった。それを解決した仮想マシンと、それによって培われた「ローカル開発環境」の考え方はたしかにWebサービス開発者たちに光明をもたらしたが、オーケストレーションの本質と保守の難しさは変わっていない。知識を身に着けて正しい運用を考えなければ、プランナーがmigrateのコマンドを叩き、デザイナーがDocker-composeやgit pushを行わなければならない暗黒時代は脈々と続いていくだろう。

どのような体制でも、チーム全体で正しく知識を身に着けて運用していければよい。究極的には、チーム全員がその体制で楽しければいい。しかし、チームメンバーのそれぞれがフルスタックエンジニアの教養を身に着ける必要はないはずだ。仮想マシンを導入したことで逆に苦労が増えていると感じる場合、別の体制を検討すべきだし進言すべきだろう。大切なのは道具や型式ではなく、使い方だ。