Laravel Deployments

I’d like to talk about Laravel deployments for both development and production environments. The default way to install a Laravel application for development now uses Docker technology, so I want to mention a thing or two about Docker, Laravel Sail, Spin, and the uses for each technology.

laravel deployments

Docker Containers vs. Virtual Machines

In older, more traditional virtual machines (VMs), configuration would look like that of a bare-bones server, with a fully featured operating system and all the necessary software for the tech stack installed on top of that.

Docker containers are typically more lightweight. Each Docker container uses the kernel of the host’s operating system instead of having its own. Furthermore, each container is typically broken down into the smallest possible component.

Despite the fact that Docker containers make use of the host machine’s kernel, they have no knowledge of the host machine, and thus operate in isolation. This can be a huge benefit for security.

Knowing that Docker containers are typically broken down into small, bite-sized pieces, it follows that with larger or complicated applications, we might need multiple. In those cases, will need to be able to orchestrate them together harmoniously; that’s where Docker Compose comes in. Docker Compose offers a clever configuration file structure that the engineer can use to define all the parts and how they will work together.

For example, I could define a Docker Compose configuration file that would specify that both a database server and a web server are needed, and that the web server depends upon the database server being available.

Once configuration for Docker Compose has been defined, setting up your environment is typically just a single command away. Teardown is just as simple.

We’ve been using Docker technology to standardize our development environment for some time now; this has made a tremendous difference in several ways.

Each of our developers’ own local environments are now exactly the same, which eliminates the “It works on my machine” problem. This is true even with developers using all the main Operating Systems (Windows/Mac/Linux). Developer machine deployments are now swift and efficient, as they’re all standardized, and deployed in a standardized fashion, typically with a single command.

Another great thing about working with Docker containers is that all the software needed for a project is typically contained within the containers, making it very easy to switch between projects without worrying about conflicting software configurations. Also, Docker Compose is self-documenting in a way; by keeping its configuration within our repositories, it’s quite simple for us to determine which version of PHP a system was designed around (as an example).

Laravel + Docker = Sail

Here at Direct Impact Solutions, we’ve used the Laravel PHP Framework for a significant number of systems. The good folks who created the Laravel framework have even adopted usage of Docker as their default installation method using their own Docker Compose system, Laravel Sail. Laravel Sail is customizable and easy to use, so we’ve made use of it within some of our projects. I like how easy it is to add new service containers into a project. For instance, once you get to a spot in your development where your application needs to send emails, you can quickly add a container for mailpit using baked-in commands.

One unfortunate thing about Laravel Sail, however, is the fact that it does not make use of a traditional web server, but rather an artisan command (artisan serve) that acts as a wrapper around PHP’s built-in web server. This is unfortunate because PHP’s built-in web server runs only one single-threaded process. As such, it’s not designed to handle multiple requests and should not be used for production environments.

Since Laravel Sail is built using Docker compose technology, it should (in theory) be possible to make it work using a traditional web server so that we would not have the limitations that prevent us from using this tech in production. Unfortunately, I suspect that this won’t be happening any time soon. This may have something to do with the fact that the developers of Laravel and Laravel Sail also have a production deployment and management product known as Laravel Forge.

Due to our appreciation for standardization, simplicity, and Docker/Sail, we are looking into other technologies in hopes of finding something that offers the continuity we want between dev and production environments.

Spin

ServerSideUP has recently published an open-source development tool, Spin, that’s very similar to Laravel Sail. Spin aims to do exactly what we originally wanted from Laravel Sail, and then some! Not only does it allow us to reuse the same dev environment within production, but also it does more.

In order to begin using Laravel Sail, the engineer would often run sail up -d from the command line.
Similarly, when using Spin instead of Sail, one can execute spin up -d to create an environment. Similar commands are provided for running commands inside of the Docker containers as well (it’s common to run PHP artisan commands from the PHP container, and npm run commands from the node container).

Spin checks for updates when you run the spin up command. That’s refreshing to see, and not something I’ve seen in Laravel Sail.

In theory, using Spin for both dev and production deployments should always yield identical environments for end users. Separate Docker-compose.yml files are provided for both, however, so for those instances where some things need to change between environments (example mailpit in dev, proper mail server in production), Spin has you covered. There are Docker-compose.yml files provided for dev, production, and even continuous integration (CI).

A project that has Spin integrated will come with other configuration files beyond the simple Docker Compose configuration files. These additional configuration files let the engineer define details about SSH connections and the user accounts that will be responsible for deploying the solution. When being deployed to a production environment, Docker Swarm technology is used. There’s even a .spin-inventory.ini file in Ansible inventory format where you can define the servers to be used.

Since Spin utilizes a number of configuration files that could potentially hold sensitive information, it’s important to note that Spin highly encourages encryption of these files. Once encrypted, you can confidently commit and store these files within your repository. Spin comes equipped with its own vault which contains commands for encrypting, decrypting, editing, etc.

Spin helps engineers by providing GitHub action templates and supporting documentation. New Laravel projects can be started with Spin. Alternatively, you can add Spin to an existing Laravel project.

Regardless of the approach you take, you’ll be given access to templated GitHub actions. The de facto action is to deploy to production whenever a new release is added to GitHub. Getting this up and running requires a few other pieces, but Spin guides you through this process.

Spin is similar to Laravel Sail, utilizes tried-and-true technologies like Docker and Ansible, has you covered on security and flexibility, and even eliminates the issue of having different production and development environments (which is why most of us started using Docker in the first place). Spin also helps with zero-downtime deployments, making this a very promising tool in our tool belts.