The Workshop: Local Dev with Lando - php[architect] Magazine November 2022

Joe • July 5, 2023

learning phparch writing

Warning:

This post content may not be current, please double check the official documentation as needed.

This post may also be in an unedited form with grammatical or spelling mistakes, purchase the November 2022 issue from http://phparch.com for the professionally edited version.

The Workshop: Lando Local Dev

This month we’re going to visit a topic that is near and dear to my heart: local development environments. I’ve been maintaining Laravel Homestead since late 2016 and have been a longtime tinkerer of just about every local development tool you’ve ever heard of and they all have their strengths and weaknesses. Lando is just about the only tool I haven’t had a chance to dive into so join me in this dive into the world of local development with Lando.dev.

One Lando feature which initially drew my curiosity was the claim that “Lando can isolate all your dev needs on a per app basis”. This sounds great but I can show you long commit histories of tools and services with similar claims that have come and gone over the years from my projects. Lando is going to wrap our development environment services in Docker and use a proxy service to serve our application to a local development URL. Lando comes bundled with Docker Desktop on macOS and Windows so you’re ready to go out of the box on a fresh installation. Lando differs from Valet where the services will be running in Docker containers instead of directly on your system. What sets Lando apart from Homestead is you’re only virtualizing the necessities required to operate the application instead of the entire computer and operating system. Lando is going to eat a lot of resources so beware the more power your machine has will ensure a smoother runtime experience.

We’ll configure a project with Lando; a member management system that utilizes Apache, PHP 8.0, MySQL, and Redis in production. Before we get too far ahead of ourselves we should start with downloading and installing Lando. We’ll download Lando from their official GitHub releases and select our package preference. I’m running Lando on a first-generation M1 Apple Silicon mac mini with 16GB of RAM. Lando supports Linux, Windows, and macOS which is a welcome feature of any local development tool. We all know developers rarely agree on operating system choices and when tools can support all of the options it greatly reduces the friction teams may have when adopting new tools. Isn’t this cross-platform compatibility the future we were all promised?

Install Lando

You will be prompted for your password

You will be prompted for your password

Lando installation successful

Lando installation successful

We now have access to the lando command

We now have access to the lando command

Running lando init to create our configuration will begin a series of questions we answer about our project so Lando can create the appropriate services we need. We’ll select the current working directory for our project, Laravel, specify our public folder, and then name our application.

Running lando init to create our configuration

Running lando init to create our configuration

The result of our init command outputs a .lando.yml configuration file. We need to override the defaults which we can do by passing them in the config top-level item. We’ll set our PHP version to 8.0, enable Xdebug, and specify MySQL as our database. We’ll also leverage Lando’s built-in service to add our Redis service to our configuration.

name: rfid
recipe: laravel
config:
  webroot: public
  php: '8.0'
  database: mysql
  xdebug: true
  cache: redis

The recipe we’re using is laravel but we want to understand that Lando’s Recipes are high-level abstractions containing routing, services, and tooling for the particular project to be applied when starting Lando.

Lando Start!

With our configuration complete we’re ready to lando start which unleashes a lot of things. Lando takes over and downloads all the required Docker container images it needs to configure our application and the supporting services.

lando start kicking off

lando start kicking off

Depending on your connection speed and how many Docker images you may not already have on your system you should arrive at the “Booomshakalaka!!!” screen indicating success on my M1 system this took just over 3 minutes.

Success

Success!

If you’re curious about what’s happening behind the scenes we can run docker ps to see the services running: rfid_rfid-redis_1, bitnami/mysql:5.7.29-debian-10-r51 our database, devwithlando/php:8.0-apache-4 Apache/PHP, and traefik:2.2.0 which is used to make all of the URL proxy magic happen without us having to understand reverse proxies and a lot of other logic that our time would be better spent on building our awesome application, not fighting our development environment.

What if we forgot a service or want to change something? We can use this as an example of how to add a new service to our application: Mailhog for local mail processing. We’ll update our .lando.yml configuration file:

services:
  mailhog:
    type: mailhog:v1.0.0
    portforward: true
    hogfrom:
      - appserver

Next we’ll use lando rebuild -y to apply our changes and reload our application. the rebuild operation took about 2 minutes and resulted in adding our Mailhog URLs.

Your app has started up correctly.
Here are some vitals:

 NAME            rfid
 LOCATION        /Users/halo/Code/rfid
 SERVICES        appserver, database, cache, mailhog
 APPSERVER URLS  https://localhost:64387
                 http://localhost:64388
                 http://rfid.lndo.site:8080/
                 https://rfid.lndo.site/
 MAILHOG URLS    http://localhost:64386

We’ll also need to update our application’s .env to point it at Lando’s services:

...
APP_URL=https://rfid.lndo.site
APP_SERVICE=rfid.lndo.site

DB_CONNECTION=mysql
DB_HOST=database
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=laravel
DB_PASSWORD=laravel
...

We can use Lando’s built in lando mysql command to jump directly into a MySQL shell which can be helpful for debugging our database.

lando mysql command usage

lando mysql command usage

If you would prefer to use a graphical SQL client you can retrieve the port information from lando info; which returns information about the services of the project.

{ service: 'database',
    urls: [],
    type: 'mysql',
    healthy: true,
    internal_connection: { host: 'database', port: '3306' },
    external_connection: { host: '127.0.0.1', port: '64802' },
    healthcheck: 'bash -c "[ -f /bitnami/mysql/.mysql_initialized ]"',
    creds: { database: 'laravel', password: 'laravel', user: 'laravel' },
    config: {},
    version: '5.7',
    meUser: 'www-data',
    hasCerts: false,
    hostnames: [ 'database.rfid.internal' ] },

We can see our database service is listening for external_connections on IP 127.0.0.1 and port 64802. We can plug these values into PhpStorm for example:

example

We can see our database from PhpStorm by connecting it to Lando’s MySQL service

We can see our database from PhpStorm by connecting it to Lando’s MySQL service.

Using and Abusing Lando

Since we’re starting fresh in a new database we need to run our migrations and database seeds. Traditionally we’d do this with php artisan commands but to run them in the correct container we can use lando artisan migrate and lando db:seed to set up our application. If something goes wrong we can trash everything we’ve done so far via lando destroy which will delete the database and anything in the application’s storage folder. If you want something less destructive lando stop will stop all running services. If you’ve reached this far and you’re done, you can also uninstall Lando easily and return to your preferred local development environment.

Just as we added lando to our artisan and db commands we can use lando composer install or other Composer commands on our project just as we typically would to install dependencies or adjust other options.

Another common task is exporting and importing databases for our project. We can use lando db-export filename to export our DB to a local file. To import a SQL export into our database we would use db-import filename. Neither of these commands requires us to rebuild the environment, you should see the changes immediately after the import.

What about NPM and Node, how do we run npm run dev to build our front-end assets? We can add a NodeJS service to our .lando.yml and provide a command to run such as npm run dev. In my use cases I still typically run NPM commands directly on my files instead of connecting to the running container such as lando artisan and lando php commands would. This is a personal preference and you should use what makes the most sense to you. Our updated .lando.yml adding Node might look like this:

services:
  mailhog:
    type: mailhog:v1.0.0
    portforward: true
    hogfrom:
      - appserver
  node:
    type: node:16
    command: npm run dev

Since we’ve changed our configuration file we need to run lando rebuild -y to apply the changes and we’ll see another port added for our Node URLs:

NAME            rfid
LOCATION        /Users/halo/Code/rfid
SERVICES        appserver, database, cache, mailhog, node
APPSERVER URLS  https://localhost:50803
                http://localhost:50804
                http://rfid.lndo.site:8080/
                https://rfid.lndo.site/
MAILHOG URLS    http://localhost:50799
NODE URLS       http://localhost:50800

You’ll want to add this Node service to your configuration if you want to run these commands inside Lando. There are some things to consider with this as your node_modules PATH variable may not be what you’d expect since they’ll be paths for the container services and not what you might be used to. Experiment and see what come up with, there’s certainly the ability to override and change behaviors around Lando so I would expect just about any project would be able to get up and running quickly.

But I need MSSQL! Lando’s got you covered with a MSSQL plugin. But we use a highly specialized Varnish caching layer! Lando has you covered with a Varnish plugin. What makes me excited about Lando is it makes adding these services trivial, and when you remove the complexity of configuring and installing services you enable developers to use those tools and experiment with other solutions. Lando isn’t just for Laravel, whether it’s supported via Services or Recipes you can easily use WordPress, Joomla, Drupal, Symfony, and just about any other PHP framework you might be interested in. We’ve only configured one application with Lando, you can keep adding sites or start removing them as much as you’d like to and as much as you have the system resources to run all of the services.

What’s the result of our Lando test drive? One added file to our project which is our .lando.yml file and our entire development environment is created from there. This is an incredibly powerful tool as even something such as Sail requires adding supplemental files and configuration templates to your project folder. We’re also using many defaults so we’re not near Lando’s limits and our modest M1 2020 system is not showing any signs of stress such as other applications lagging and becoming unresponsive. Granted you may need to add custom configuration files to override PHP configurations like you would with Laravel Sail. Lando has been a breath of fresh air for someone who has a lot of opinions on how local development environments work.

Lando is a pretty fantastic local development environment tool. It allows you to leverage the complexity of Docker without having to be an expert. The tools integrate well with typical PHP development workflows, and the documentation is concise while descriptive. The most important part of a local development environment is that Lando got out of my way. I felt immediately productive and didn’t have to struggle. If you run into trouble the docs also contain a troubleshooting guide as well as a list of known issues you might run into while using Lando. Lando is a great solution to a very difficult problem: keeping developers happy while building applications, I would certainly recommend it as a tool in your toolbox.

Warning:

This post content may not be current, please double check the official documentation as needed.

This post may also be in an unedited form with grammatical or spelling mistakes, purchase the November 2022 issue from http://phparch.com for the professionally edited version.