チュートリアルに関する問題
2022年3月8日 Burke Holland 著、@burkeholland
素晴らしいチュートリアルを書くのは簡単ではありません。私が知っているのは、たくさん書きましたが、どれも大成功というわけではありませんでした。
結局のところ、素晴らしいチュートリアルを作ることは、何を書くかではなく、開発者がすべての単語を読むことなく成功できるかどうかです。この記事では、開発コンテナがユーザーが遭遇する可能性のあるエラーをどのように減らすことができるか、そしてLaravel PHPプロジェクトが、彼らのチュートリアルでこれをどのようにエレガントに実装し、大きな効果を上げているかを見ていきます。
誰も読まない
Visual Studio Code で Dev Containers を使用する方法に関する私たち自身のチュートリアルは、長い間完了率が低く、約4〜6%でした。

人々がどこで諦めているのかを把握するために、ユーザー調査を実施し、人々がチュートリアルを完了しようとする様子を観察しました。それは...苦痛でした。
人々がチュートリアルを完了できない理由はすぐに明らかでした。誰も読んでいなかったのです。人々は指示をスキップして、直接アクションステップに進んでいました。必然的に、指示を読んでいれば犯さなかったであろうエラーを犯して立ち往生しました。
ペンシルベニア州立大学のジョン・M・キャロル教授は、彼の画期的な著書『The Nurnberg Funnel - Designing Minimalist Instruction for Practical Computer Skill』の中でこれについて語っています。彼は「[学習者は]学習に忙しすぎて、指示をあまり利用しない。これが意味構築のパラドックスだ」と書いています。
私はこれに共感できますし、あなたもおそらくそうでしょう。チュートリアルを進めるとき、私は「実践による学習」を試みているので、コードブロックを探すように目を走らせています。文字通り、指示を読むには学習に忙しすぎるのです。
人々はあなたのチュートリアルを読みません。 あるいは、あなたが望むほどには読みません。できる限りの最善策は、学習プロセス中に読者がエラーを犯す可能性のある場所をできるだけ多く排除することです。その方法の1つは、事前構成されたコンテナ環境を使用して、環境設定ステップを完全に削除することです。
コンテナ化された開発環境
どのようなチュートリアルでも、かなりの部分は、必要条件と環境設定のリストに費やされます。Ruby on Rails を学ぼうとして、Windows に Ruby を正しくインストールするのにほとんどの時間を費やしたことを鮮明に覚えています。「gem」とは一体何なのか、なぜそれらがすべて何らかの形で不足していたのか、不思議に思っていました。
コンテナ化された開発環境の背後にある考え方は、Docker コンテナ内で開発することです。これにより、完全にポータブルで、完全に構成された開発環境を、自由に立ち上げたり、解体したりすることが可能になります。そして、その環境を単なる一連の設定ファイルとして誰かに提供することができます。
しかし、コンテナの中でどのように開発するのでしょうか?コンテナに VS Code を起動できるような UI があるわけではありません。
VS Code のDev Containers 拡張機能はまさにこれを行います。Docker コンテナを開発環境として構成するメカニズムと、VS Code からその環境に接続することを可能にするメカニズムの両方を含んでいます。これは、ローカルの VS Code と通信する小さなサーバーコンポーネントをコンテナ内にインストールすることで実現します。そうすることで、ローカルで開発しているのとまったく同じように開発できますが、VS Code はローカル環境ではなくコンテナ環境に接続されています。

コンテナ化された開発環境を作成するには、通常、Docker について多少の知識が必要になります。多くの人は知っていますが、多くの人は知りません(私には見えませんが、私の手は挙がっています)。そのため、この拡張機能はコンテナのセットアッププロセスを可能な限り抽象化しようとします。新しい Python コンテナをセットアップしました。ウィザードがベースイメージと Python バージョンの選択を案内します。その後、ピッカーリストからイメージに追加のソフトウェアを追加する機会が与えられます。この場合、Azure CLI、Dotnet CLI、PowerShell を追加します。

このプロセスにより、必要な Dockerfile を含む .devcontainer フォルダーがこのプロジェクトに追加されます。また、devcontainer.json ファイルも追加されます。これは、インストールすべき拡張機能、コンテナ構築後に実行すべきセットアップコマンドなど、開発コンテナの側面を定義するための標準です。環境とそのセットアップを完全に制御できるため、依存関係のインストール、ライブラリのバージョンなど、ほぼすべてを自動化できます。
このようにして、文字通り、追加のセットアップ手順や Ruby gems をめぐる実存的な危機を引き起こすことなく、完全で、すぐに使える環境を誰かに提供することが可能になります。
一部の人々はすでに、デブコンテナベースのアプローチを使用して、本来であれば非常に複雑な環境でユーザーを迅速に立ち上げて実行させています。この素晴らしい例が、PHP 用の Laravel フレームワークです。
Laravel ソリューション
Laravel は、PHP 用のオープンソース MVC フレームワークです。オブジェクトリレーショナルマッパー (ORM)、直接データベースアクセス、パッケージングシステムなども含まれている点で包括的です。Laravel は多くのことができます。そしてそれを体験するには、開始時に少なくともデータベースが必要になります。通常、これはユーザーが PHP だけでなく、データベース (通常は MySQL) もインストールする必要があることを意味します。ユーザーがフレームワークを試しているだけのときに、これはかなりの要求です。
Laravel は、コンテナ化された開発環境と Sail と呼ばれるツールでこれに対応します。Laravel、MySQL Server、および Redis Cache をゼロから始めるには、1つのコマンドを実行するだけです。
    curl -s "https://laravel.build/example-app?with=mysql,redis" | bash
これにより、docker-compose ファイルを持つ新しいプロジェクトが作成されます。このファイルは、アプリケーションコンテナ、MySQLコンテナ、Redisコンテナの3つのコンテナを設定します。コンテナやこれら3つのサービスについて何も知る必要はありません。Sail がこれらすべてを抽象化してくれます。その後、Sail コマンドを実行して環境を起動します。
    ./vendor/bin/sail up
サンプルアプリケーションはただ実行されます。PHP のインストールも、Laravel も、依存関係の解決ステップもありません。すぐに成功します。

プロジェクトに MySQL Server と Redis Cache があると指定したので、プロジェクトが起動すると実際に3つのコンテナが取得されます。これは、VS Code 用のDocker 拡張機能を使用して確認できます。

これらのコンテナはネットワークで接続されているため、アプリコンテナから MySQL または Redis キャッシュコンテナを呼び出すことができます。
sail-8.1/app container にインタラクティブターミナルを接続すると、/var/www/html フォルダにプロジェクトが表示されます。Docker はプロジェクトをあなたのマシンからコンテナに「マウント」するので、開発中に行った変更は、リフレッシュするとアプリケーションに反映されます。

開発コンテナの追加
Dev Containers 拡張機能のサポートも追加されました。このプロジェクトに適切な Dev Container 設定を追加するには、同じプロジェクトをスキャフォールドして &devcontainer フラグを追加します。
    curl -s "https://laravel.build/example-app?with=mysql,redis&devcontainer" | bash
既存の Sail/Laravel プロジェクトに devcontainer を追加したい場合は、
php artisan sail:install --devcontainerを実行してそれを行うことができます。
これにより、同じプロジェクト設定が作成されますが、.devcontainer フォルダーが含まれます。VS Code はそのフォルダーを自動的に検出し、プロジェクトをコンテナーで再度開くように促し、必要な sail up ステップをスキップします。

VS Code はコンテナにアタッチされるため、ローカル環境ではなくコンテナ環境の中で開発しています。これは、VS Code の左下隅にあるリモートインジケーターが教えてくれるのでわかります。

コンテナ内での開発は、コンテナ外での開発と比較していくつかの明確な利点があります。
開発コンテキストがアプリコンテキストをミラーリング
コンテナに接続されている場合、開発しているコンテキストはアプリケーションが実行されているコンテキストと同じになります。そのため、ターミナルはコンテナのターミナルになります。

Dev Containers 拡張機能は、アプリケーションがどこで実行されているかを忘れた場合でも、転送されているポートなど、何が起こっているかをより詳細に表示します。

Laravel アプリケーションは自動的に起動し、アプリケーションログはコンテナログにパイプされます。アプリケーションで何が起こっているかを確認したい場合がほとんどなので、Dev Containers 拡張機能は VS Code に新しいビューを提供し、実行中のすべてのコンテナを表示したり、コンテナログのストリームに接続したりできます。

開発環境のセットアップを自動化
最高の開発者エクスペリエンスには、エディタのカスタマイズが含まれます。これには、エディタ自体の設定や、デフォルトの環境に追加する必要がある拡張機能やその他のサポートが含まれます。
VS Code と Laravel の場合、拡張機能は devcontainer.json で推奨されていますが、自動的にインストールされないようにコメントアウトされています。これにより、ユーザーはすでに特定された拡張機能のセットから選択でき、エディターを構成する適切な方法を探す必要がなくなります。
    ...
    "extensions": [
        // "mikestead.dotenv",
        // "amiralizadeh9480.laravel-extra-intellisense",
        // "ryannaddy.laravel-artisan",
        // "onecentlin.laravel5-snippets",
        // "onecentlin.laravel-blade"
    ],
読む量を減らし、実行する量を増やす
人は読みません。それで構いません。Laravel のチュートリアルは他のものより短いとは限りませんが、重要なのは、コードにスキップしてコマンドを実行するだけで機能することです。Dev コンテナがそれを可能にします。さて、私たち自身のVisual Studio Code で Docker コンテナを開発環境として使用するチュートリアル用の Dev コンテナをどうやって作成するかを解明できればいいのですが。
ハッピーコーディング!
Burke Holland (@burkeholland)