教程的问题

2022 年 3 月 8 日,作者:Burke Holland,@burkeholland

编写出色的教程并不容易。我应该知道——我写了很多这样的文章,但并不是每一篇都取得了巨大的成功。

事实证明,制作一个优秀的教程并不在于你写了什么,而在于开发人员是否可以在无需阅读每个字的情况下取得成功。在本文中,我们将了解 Dev Containers 如何减少用户可能遇到的错误,以及Laravel PHP 项目如何在自己的教程中优雅地实现这一点并取得巨大效果。

没人读

我们自己的关于如何在 Visual Studio Code 中使用 Dev Containers 的教程长期以来完成率很低 - 大约 4 - 6%。

 Dev Containers 学习模块截图

为了找出人们放弃的地方,我们进行了用户研究并观察人们试图完成我们的教程。真是……痛苦。

人们无法完成本教程的原因立即显而易见:没有人阅读它。人们直接跳过说明,直接进入操作步骤。不可避免地,他们会陷入困境,因为他们犯了一个如果他们阅读了说明就不会犯的错误。

宾夕法尼亚州立大学教授约翰·卡罗尔(John M. Carroll)在他的开创性著作《纽伦堡漏斗 - 为实用计算机技能设计简约教学》中谈到了这一点。他写道:“[学习者]太忙于学习,无法充分利用教学内容。这就是意义建构的悖论。”

我能理解这一点,你可能也能理解。当我阅读教程时,我的眼睛会扫描代码块,因为我试图通过实践来学习。我真的太忙于学习而没有时间阅读说明。

人们不会阅读您的教程。或者至少没有你希望的那么多。你能做的最好的事情就是尽可能多地删除读者在学习过程中可能犯错的地方。一种方法是使用预配置的容器环境完全删除任何环境设置步骤。

容器化开发环境

任何教程的很大一部分通常都会专门介绍一系列先决条件和环境设置。我清楚地记得尝试学习 Ruby on Rails,并花费大部分时间尝试在 Windows 上正确安装 Ruby - 想知道世界上的“宝石”是什么以及为什么它们都以某种方式丢失。

容器化开发环境背后的想法是在Docker容器内进行开发。这使得拥有一个完全便携、配置齐全、可以随意站起来或拆下来的开发环境成为可能。然后,您可以将该环境作为一组配置文件提供给某人。

但是如何在容器内进行开发呢?这不像容器有一个 UI,您可以在其中启动 VS Code。

VS Code 的Dev Containers扩展正是这样做的。它包含将 Docker 容器配置为开发环境的机制,以及允许您从 VS Code 连接到该环境的机制。它通过在本地 VS Code 与之通信的容器内安装一个小型服务器组件来实现此目的。然后,您就可以像在本地一样进行开发,但 VS Code 附加到容器环境而不是本地环境。

来自扩展库的 Dev Containers 扩展屏幕截图

为了创建容器化开发环境,您通常需要对 Docker 了解一两件事。很多人这样做,但很多人不这样做(你看不到我,但我的手在空中),因此该扩展尝试尽可能抽象容器设置过程。我设置了一个新的 Python 容器。向导将引导您选择基础映像和 Python 版本。然后,您可以通过选择器列表向图像添加其他软件。在本例中,我添加了 Azure CLI、Dotnet CLI 和 PowerShell...

将 Dev Containers 配置添加到 Python 项目

此过程会.devcontainer向该项目添加一个文件夹,其中包含必要的内容Dockerfile。它还添加了一个devcontainer.json文件,这是定义 Dev Containers 各个方面的标准,例如应安装哪些扩展、容器构建后应运行哪些设置命令等。由于您可以完全控制环境及其设置,因此您可以几乎可以自动化所有事情——包括依赖项安装、库版本等。

通过这种方式,可以完全为某人提供一个完整的、随时可用的环境,不需要额外的设置步骤或触发 Ruby gems 的生存危机。

有些人已经在使用基于 Dev Containers 的方法来让用户在非常复杂的环境中快速启动和运行。PHP 的 Laravel 框架就是一个很好的例子。

Laravel 解决方案

Laravel是 PHP 的开源 MVC 框架。它是全面的,因为它还包括对象关系映射器 (ORM)、直接数据库访问、打包系统等。Laravel 可以做很多事情。为了体验它,在开始时您确实至少需要有一个数据库。通常,这不仅需要用户安装 PHP,还需要安装数据库 - 通常是 MySQL。当用户只是想尝试一下您的框架的大小时,这是一个重要的问题。

Laravel 通过容器化开发环境和名为Sail 的工具解决了这个问题。要从头开始使用 Laravel、MySQL 服务器和 Redis 缓存,您只需运行一个命令...

    curl -s "https://laravel.build/example-app?with=mysql,redis" | bash

这将创建一个带有文件的新项目docker-compose。该文件设置了三个容器——应用程序容器、MySQL 容器和 Redis 容器。您不必了解有关容器或这三种服务中任何一种的任何信息。Sail 为您抽象了所有这些。然后执行 Sail 命令来启动环境......

    ./vendor/bin/sail up

示例应用程序刚刚运行。无需安装 PHP。没有拉拉维尔。没有依赖性解析步骤。只是立即成功。

在本地主机上的浏览器中运行的示例 Laravel 应用程序

我指定我们的项目有一个 MySQL 服务器和一个 Redis 缓存,因此当项目启动时我们实际上得到了三个容器。我们可以看到使用VS Code 的Docker 扩展

VS Code 中的 Docker 扩展

这些容器联网在一起,以便我们可以从应用程序容器调用 MySQL 或 Redis 缓存容器。

如果将交互式终端连接到sail-8.1/app container,您将在该文件夹中看到您的项目/var/www/html。Docker 将项目从您的计算机“安装”到容器中,因此您在开发时所做的任何更改都会在您刷新时反映在应用程序中。

容器中 Laravel 项目的文件结构

添加 Dev Containers

还添加了对Dev Containers扩展的支持。要向该项目添加正确的 Dev Containers 配置,您可以构建同一项目并添加标志&devcontainer

    curl -s "https://laravel.build/example-app?with=mysql,redis&devcontainer" | bash

请注意,如果您想将 devcontainer 添加到现有的 Sail/Laravel 项目中,您可以通过运行php artisan sail:install --devcontainer.

这将创建相同的项目配置,但将包含一个.devcontainer文件夹。VS Code 将自动检测该文件夹并提示您在容器中重新打开项目,从而跳过所需的sail up步骤。

VS Code 中的通知显示“在容器中重新打开”

VS Code 附加到容器,因此您是容器环境中进行开发,而不是在本地环境中进行开发。您会知道这一点,因为 VS Code 左下角的远程指示器会告诉您......

VS Code 中的远程指示器显示与容器的连接

与在容器外进行开发相比,在容器中进行开发有一些明显的好处。

开发环境反映了应用程序环境

连接到容器后,您正在开发的上下文与应用程序运行的上下文相同。这样你的终端就变成了集装箱的终端......

连接到正在运行的容器实例的 VS Code 终端

Dev Containers 扩展还可以让您更全面地了解正在发生的情况,例如转发哪些端口 - 以防您忘记应用程序在哪里运行。

VS Code 中的端口转发视图显示端口 80 已转发

Laravel 应用程序自动启动,应用程序日志通过管道传输到容器日志。由于您可能想查看应用程序中发生的情况,因此 Dev Containers 扩展在 VS Code 中提供了一个新视图,您可以在其中查看所有正在运行的容器,以及连接到流容器日志。

Laravel 应用程序容器登录 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 Containers 使这成为可能。现在,如果我们能够弄清楚如何为我们自己的 Dev Containers 使用 Docker 容器作为 Visual Studio Code教程的开发环境...

快乐编码!

伯克·荷兰(@burkeholland