In our organization Laravel Homestead was adopted as a default way to create a local development environment and we were hesitant to do the change to Docker based local environment. The hesitation was not coming from some particular technical reasons but it was more about the convenience and don't try to fix something that is not broken philosophy. But one of our colleagues started to experience some performance issues in his environment and the first thought was that it must be the computer configuration because the computer that he was working on was not super new and was with some older generations of processors. After some deeper investigation the final conclusion was that actual bottleneck was Vite performance and how the files are mounted and read from the host machine to the Homestead guest machine. I believe that the issue was solvable if we spent time to optimize the configurations but we have decided that this is the time when we should probably take the step and go on with the container based local development environment.
And long story short, we migrated from Homestead to Sail and the same project on the same computer became very fast and our colleague could happily continue to work on his project on the same machine.
So, as I needed to practically pass the migration process it was not hard for me to document it and share it with you. In general it is not something complex and it is not something that you cannot figure it out by yourself by following the documentation but why not provide a straightforward streamlined process that everyone that is planning to do the same can follow.
There are a few things that you can do in order to prepare the migration.
you have the option to install Docker Engine only without Docker Desktop. For me this is the preferred way because installed in this way you reduce the probability for performance issues because Docker Engine can run natively on Linux. If you decide to use Docker Desktop on Linux that is fine too but you need to be aware that Docker Desktop installs a virtual machine on which it is running the Docker Engine. If you want to have only Docker Engine natively on Linux but still want to have some UI to manage the containers then you can spin up Portainer container as an alternative for Docker Desktop but that is out of the scope of this article.
The instructions provided below are tested on Linux but they should work on Mac also. If you are using Windows the process is the same but you might need to do some small additional search to find out how to do the particular things on Windows.
There is a clear explanation in the official documentation how to install it but here we will cover a way in which actually your existing Homestead can help you in the transition.
The first thing is to install Sail into the existing application. Let's install the composer dependency first:
composer require laravel/sail --dev
Please note that you can freely run this inside your Homestead virtual machine as you usually do with other composer dependencies.
After sail package is installed you need to run the artisan command in order to generate the compose.yml file that contains the configurations for building and running the containers. And guess what you can also run this command in your Homestead virtual machine.
php artisan sail:install
If you need to install some additional services you can do that even in this step by specifying which Sail-supported services you want to install
For example if you want to activate minio, redis and mailpit you can run:
php artisan sail:install --with=minio,redis,mailpit
This command will generate a compose.yml file that contains all the services.
By default, Sail commands are invoked using the vendor/bin/sail script that is included with all new Laravel applications, for example:
./vendor/bin/sail up
However, instead of repeatedly typing vendor/bin/sail to execute Sail commands, it is better to set an alias that allows you to execute Sail's commands more easily:
alias sail='sh $([ -f sail ] && echo sail || echo vendor/bin/sail)'
As a Mac or Linux user to make sure this is always available, you may add this to your shell configuration file in your home directory, such as ~/.zshrc or ~/.bashrc, and then restart your shell.
Once the shell alias has been configured, you may execute Sail commands by simply typing sail. The instructions in this post will assume you have configured this alias.
Some adjustments need to be done before you spin up the containers with sail in order to be sure that everything works. If you are using MySQL as a database change the value of the DB_HOST variable:
DB_HOST=mysql
If you are using Redis as a cache driver change the value of the CACHE_DRIVER variable:
CACHE_DRIVER=redis
If you are using Minio you might want to check the Port and adjust it in your values in your .env values related to the object storage connection. The Minio instance that Sail creates listens on Port 9000, so you need to add:
AWS_ENDPOINT=http://minio:9000
AWS_URL=http://localhost:9000/bucketname
It is also important to know that Sail is reading the variables from .env file and it is using them during the creation of the containers. If you are migrating an existing project you do not need to change anything but optionally if you want to make some changes to the database password, database name, database username etc. it is the right moment to do that.
Check your APP_URL variable in your .env file. It should be something like:
APP_URL=http://myapp.test
In your /etc/hosts file add the following:
127.0.0.1 myapp.test
So once your Sail containers are up you can access your application over myapp.test domain locally.
Now you are ready to start the Sail containers. Make sure that you are in the root directory of the project in your terminal and run:
sail up
or
sail up -d
if you want Sail to run in the background.
To stop your Sail containers you can run:
sail stop
To fully load the Laravel application you need to do the following steps.
Migrate the database and at the same time check if the database connection works.
sail artisan migrate
Run the database seeders if you have them.
sail artisan db:seed
If you are actively using a front-end framework install your npm packages.
sail npm install
Run your development server if you are using a front-end framework like VueJS or React.
sail npm run dev
Now if you type in myapp.test in your browser you should be able to reach your application.
We mentioned at the top that you should prepare a database backup and a backup of your files from your Homestead's Minio instance. Now it is time to import them.
For importing your database you can use any database client that you are using during development. Just make sure to check the official Laravel Sail documentation for instructions of how to connect.
However for importing the files in the newly created Minio instance things are not straightforward. As you know the recent Community version of the Minio UI app does not provide any interface for managing files and permissions. Because of that we must utilize "mc" the Minio's official command line tool to do the job.
We first need to install "mc" on the local machine. To do that you can run the following command:
curl --progress-bar -L https://dl.min.io/aistor/mc/release/linux-amd64/mc \
--create-dirs \
-o $HOME/aistor-binaries/mc
Once 'mc' is installed we need to create an alias so we can use that alias to connect to our Sail Minio instance.
mc alias set myapp_minio http://localhost:9000 sail password
Please note that in the command above "sail" is the default username and "password" is the default password that Sail creates during the creation of the Minio container.
Once we have the alias we can use it and start creating buckets as a first step. To create a private bucket run:
mc mb myapp_minio/bucketname
For the name of your bucket it is convenient to check what you have in your .env file settings and use the same.
To create a public bucket you can run:
mc mb myapp_minio/public-bucketname
Make it public after that:
mc anonymous set public myapp_minio/public-bucketname
Finally you can copy your files from the local machine to the appropriate bucket by using the following command:
mc cp --recursive /path/to/local/folder/ myapp_minio/bucketname/