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.
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.
What is Docker Compose?
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.
Benefits
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.
Laravel Sail Wishlist
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.
Where To From Here?
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.
Spin Usage
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 Update Checks
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.
Spin Environment Discrepancies
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).
Spin Configuration
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.
Spin Encryption
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.
Zero-Downtime Deployments
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.
Conclusion
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.