Laravel Sail is a Docker development environment included by default in Laravel since version 8. It allows you to quickly get a PHP development environment up and running, tailored for running Laravel applications with built-in support for NPM / Node.
In this guide, you’ll bootstrap a new Laravel application with Laravel Sail and create a styled “about me” landing page using Tailwind CSS, a utility-first CSS framework designed for rapidly building custom user interfaces. At the end, you’ll have a base that you can use to further develop a Laravel application using Tailwind CSS for the front end and Sail for the development environment.
If you’d prefer to follow along from an existing codebase rather than creating the project from scratch, you can access the finished demo application code at do-community/laravel-tailwind-starter on GitHub.
Although the code shared in this guide should work seamlessly across multiple environments and systems, the instructions explained here were tested within an Ubuntu 20.04 local system running Docker and Docker Compose. Regardless of your base operating system, here’s what you’ll need to set up in order to get started:
To get started, you’ll download and execute the official Laravel builder script, which will pull in the necessary Docker container images to build your development environment and then bootstrap a new application in your current folder. This installation method doesn’t require you to have PHP installed on your system, requiring only that you download and execute the builder script that will set up the Docker environment where you can run the actual Laravel installer.
At the end, the script asks for your sudo
password to make sure the application folder has correct permissions for your system user. You can access the script URL from your browser to verify its contents before running the next command. In this example, we’re using the name myapp, but you are free to replace this with a different name:
curl -s https://laravel.build/myapp | bash
OutputUnable to find image 'laravelsail/php80-composer:latest' locally
latest: Pulling from laravelsail/php80-composer
852e50cd189d: Pull complete
0266fc315b01: Pull complete
…
Application ready! Build something amazing.
Sail scaffolding installed successfully.
Please provide your password so we can make some final adjustments to your application's permissions.
[sudo] password for sammy:
Thank you! We hope you build something incredible. Dive in with: cd myapp && ./vendor/bin/sail up
When the installation is finished, access the new application directory and get the Sail environment up with:
- cd myapp
- ./vendor/bin/sail up
This will bring the environment up in foreground mode, so you can follow up with the logs from all running containers. You’ll see a few different services getting started, using different ports to communicate between each other:
Output...
mailhog_1 | [HTTP] Binding to address: 0.0.0.0:8025
...
laravel.test_1 | Starting Laravel development server: http://0.0.0.0:80
...
meilisearch_1 | Server listening on: "http://0.0.0.0:7700"
...
mysql_1 | 2021-06-23T01:15:24.327234Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.25' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server - GPL.
...
selenium_1 | 01:14:57.417 INFO [SeleniumServer.boot] - Selenium Server is up and running on port 4444
...
redis_1 | 1:M 23 Jun 2021 01:14:54.243 * Running mode=standalone, port=6379.
…
These are services configured by default within Sail environments. For more information about each of them, refer to the official Sail documentation.
Next, access the application from your browser at:
http://localhost
If all steps were successful, you’ll see a page like this:
The application is now bootstrapped.
You can now stop the Sail environment that is running on your terminal by typing CTRL+C
.
Laravel Sail offers several shortcuts to manage your development environment. Most commands and arguments are based on the default Docker Compose API.
To bring the environment up in background mode, you can run:
- ./vendor/bin/sail up -d
To stop a Sail environment that was previously initiated in background mode, run:
- ./vendor/bin/sail stop
This won’t delete attached networks or volumes.
To bring back an environment that was previously stopped with a sail stop
command, you can use:
- ./vendor/bin/sail start
To stop an environment and also delete all associated resources such as volumes and networks, you can use the sail down
command. Please notice that this command will delete any data that was previously created and is only available inside containers, such as records stored in a database.
- ./vendor/bin/sail down
OutputStopping laravel-tailwind-starter_laravel.test_1 ... done
Stopping laravel-tailwind-starter_redis_1 ... done
Stopping laravel-tailwind-starter_selenium_1 ... done
Stopping laravel-tailwind-starter_mysql_1 ... done
Stopping laravel-tailwind-starter_mailhog_1 ... done
Stopping laravel-tailwind-starter_meilisearch_1 ... done
Removing laravel-tailwind-starter_laravel.test_1 ... done
Removing laravel-tailwind-starter_redis_1 ... done
Removing laravel-tailwind-starter_selenium_1 ... done
Removing laravel-tailwind-starter_mysql_1 ... done
Removing laravel-tailwind-starter_mailhog_1 ... done
Removing laravel-tailwind-starter_meilisearch_1 ... done
Removing network laravel-tailwind-starter_sail
If your environment is down, bring it back up with:
- ./vendor/bin/sail up -d
When your environment is up and running, you can check the status of all active containers with:
- ./vendor/bin/sail ps
Output Name Command State Ports
---------------------------------------------------------------------------------------------------------------------------------
myapp_laravel.test_1 start-container Up 0.0.0.0:80->80/tcp,:::80->80/tcp, 8000/tcp
myapp_mailhog_1 MailHog Up 0.0.0.0:1025->1025/tcp,:::1025->1025/tcp,
0.0.0.0:8025->8025/tcp,:::8025->8025/tcp
myapp_meilisearch_1 tini -- /bin/sh -c ./meili ... Up (healthy) 0.0.0.0:7700->7700/tcp,:::7700->7700/tcp
myapp_mysql_1 docker-entrypoint.sh mysqld Up (healthy) 0.0.0.0:3306->3306/tcp,:::3306->3306/tcp, 33060/tcp
myapp_redis_1 docker-entrypoint.sh redis ... Up (healthy) 0.0.0.0:6379->6379/tcp,:::6379->6379/tcp
myapp_selenium_1 /opt/bin/entry_point.sh Up 4444/tcp
The output from the sail ps
command will tell you which containers related to that specific environment are currently active, which ports are being redirected, and more importantly, in which state each container is. In the previous example output, all services are up.
To check the containers logs when you’re running your environment in background mode, you can use:
- ./vendor/bin/sail logs
This will show you the latest logs from all services.
Attaching to laravel-tailwind-starter_laravel.test_1, laravel-tailwind-starter_mailhog_1, laravel-tailwind-starter_mysql_1, laravel-tailwind-starter_redis_1, laravel-tailwind-starter_selenium_1, laravel-tailwind-starter_meilisearch_1
...
mysql_1 | 2021-06-24T15:08:06.435530Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.25' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server - GPL.
...
meilisearch_1 | [2021-06-24T15:16:38Z INFO actix_web::middleware::logger] 127.0.0.1:60874 "GET /health HTTP/1.1" 200 22 "-" "Wget" 0.000056
...
laravel.test_1 | [Thu Jun 24 15:08:07 2021] PHP 8.0.7 Development Server (http://0.0.0.0:80) started
...
selenium_1 | 15:08:06.864 INFO [SeleniumServer.boot] - Selenium Server is up and running on port 4444
...
redis_1 | 1:M 24 Jun 2021 15:08:05.280 * Ready to accept connections
...
mailhog_1 | 2021/06/24 15:08:05 Serving under http://0.0.0.0:8025/
You can also see logs per service by providing an additional argument to the command call:
- ./vendor/bin/sail logs redis
OutputAttaching to laravel-tailwind-starter_redis_1
redis_1 | 1:C 24 Jun 2021 15:08:05.278 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis_1 | 1:C 24 Jun 2021 15:08:05.278 # Redis version=6.2.4, bits=64, commit=00000000, modified=0, pid=1, just started
...
redis_1 | 1:M 24 Jun 2021 15:08:05.280 * RDB memory usage when created 0.77 Mb
redis_1 | 1:M 24 Jun 2021 15:08:05.280 * DB loaded from disk: 0.000 seconds
redis_1 | 1:M 24 Jun 2021 15:08:05.280 * Ready to accept connections
While working on your Laravel application, you’ll often be required to run artisan
commands to build, test, and manage your application. You’ll also need to run composer
commands to manage your PHP dependencies. In addition to the default Docker Compose API, Sail offers helpful shortcuts to execute these commands in your application container (myapp_laravel.test_1
in the example output). With a regular Docker Compose setup, running Artisan would look like this:
docker-compose exec app php artisan
With Sail, the equivalent call is shortened to:
- ./vendor/bin/sail artisan
You can run Composer in a similar way:
- ./vendor/bin/sail composer
For more information about all features and commands available, please visit the official Laravel Sail Documentation.
You’re now familiar with how to manage your Sail development environment and how to run commands on the application container. In the next step, you’ll set up Tailwind CSS to design and style your landing page.
Next, you’ll install and set up Tailwind CSS to build a landing page.
Make sure your Sail environment is up and running, then install Laravel’s front end dependencies with the npm
command, which is used to download and manage JavaScript packages :
- ./vendor/bin/sail npm install
Output...
added 1327 packages, and audited 1328 packages in 20s
99 packages are looking for funding
run `npm fund` for details
...
Then, install Tailwind and its dependencies with:
- ./vendor/bin/sail npm install -D tailwindcss@latest postcss@latest autoprefixer@latest
Output...
added 9 packages, removed 22 packages, changed 7 packages, and audited 1315 packages in 5s
99 packages are looking for funding
run `npm fund` for details
...
Next, you’ll need to create a configuration file for Tailwind. To do that, you’ll use npx
, which stands for Node package executer and allows you to execute a Node package. The following npx
command will generate a new default Tailwind configuration for your application:
- ./vendor/bin/sail npx tailwindcss init
This will create a new configuration file named tailwind.config.js
in your project’s root directory with the following content:
module.exports = {
purge: [],
darkMode: false, // or 'media' or 'class'
theme: {
extend: {},
},
variants: {
extend: {},
},
plugins: [],
}
Although there are different ways to set up Tailwind within a project, in this guide we’ll configure Tailwind with Laravel Mix and webpack. Both libraries are used to compile and output front end resources.
Open the file webpack.mix.js
using your code editor. It will look like this:
mix.js('resources/js/app.js', 'public/js')
.postCss('resources/css/app.css', 'public/css', [
//
]);
Laravel Mix uses PostCSS to compile CSS resources. Remove the //
characters and include the following highlighted line, which will add Tailwind CSS in the list of CSS resources to process:
Remove the //
characters and include the following highlighted line, which requires Tailwind as a PostCSS plugin:
mix.js("resources/js/app.js", "public/js")
.postCss("resources/css/app.css", "public/css", [
require("tailwindcss"),
]);
Save the file after making this change.
Next, include Tailwind within the application’s main CSS file. Open resources/css/app.css
in your code editor and add the following 3 lines to this file:
@tailwind base;
@tailwind components;
@tailwind utilities;
Save when finished.
Next, you’ll need to build the front end assets with NPM:
- ./vendor/bin/sail npm run dev
You will receive output that is similar to the following, with a line like the the highlighted Compiled Successfully
portion that indicates you have integrated all of the components into your Sail environment:
Output
Laravel Mix v6.0.24
✔ Compiled Successfully in 5515ms
┌───────────────────────────────────────────────────────────────────┬──────────┐
│ File │ Size │
├───────────────────────────────────────────────────────────────────┼──────────┤
│ /js/app.js │ 597 KiB │
│ css/app.css │ 3.81 MiB │
└───────────────────────────────────────────────────────────────────┴──────────┘
webpack compiled successfully
Tailwind is now configured and you have built the front end assets for your site… In the next step, you’ll create a new landing page for your application.
With Tailwind’s configuration in place, you can now start building your application’s front end views. In Laravel, templates are typically stored in the resources/views
directory. The page you saw before when opening the application from a browser (http://localhost
) is defined in a single template called welcome.blade.php
, in that directory.
In your code editor, open a new file called index.blade.php
in the resources/views
directory.
The following example template defines an “about me” HTML page with a few unstyled elements. It uses an example avatar image but you may replace it with an image of your own.
Create a new img
directory in the public application folder:
- mkdir public/img
Save your preferred image to this new directory, under the name profile_image.png
.
In the following example, notice the use of the highlighted {{ asset… }}
helper lines to define paths for both the CSS and the image files. This function outputs the correct public path for application resources located in the public
directory.
Copy this content to your own index.blade.php
:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Sammy the Shark - About Page</title>
<meta name="description" content="My Application Description">
<meta name="author" content="Sammy">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body>
<div>
<img src="{{ asset('img/profile_image.png') }}" width="200" alt="avatar"/>
<h1>Sammy the Shark</h1>
<p>Content Creator</p>
<p>Hello, I'm Sammy. I am a friendly shark interested in Linux, coding, and community.
You can find out more about me in the following links:</p>
<div>
<div><a href="https://twitter.com/digitalocean">Twitter</a></div>
<div><a href="https://www.linkedin.com/company/digitalocean">LinkedIn</a></div>
<div><a href="https://instagram.com/thedigitalocean">Instagram</a></div>
</div>
</div>
</body>
</html>
Save the file when you’re finished editing its contents.
Now edit the routes/web.php
file to modify the main route so that it uses the newly created template. Open that file using your code editor, and replace welcome
with index
to change the view used by the main application endpoint. This is how the updated route declaration will look like once you’re finished:
Route::get('/', function () {
return view('index');
});
Save the file. You can now reload the application page in your browser to see the new index page. You’ll see a page like this:
By default, Tailwind removes all styling from elements, which gives you freedom to build up your views by combining and mixing Tailwind CSS utility classes. In the next section, you’ll learn how to combine some of these utility classes in order to create a responsive “about me” page.
Building responsive pages is an important front end development requirement, since users may access your website or application from many different devices, each with different screen sizes.
Tailwind offers selectors that are able to apply styles per screen size. This way, you can create responsive containers by setting up the smallest width as default, and appending the additional responsive sizes for bigger screens. For instance, an element set with class="w-3/4 lg:w-1/2"
will set a default width of 3 quarters the width of the parent element, which will be valid for smaller screens, but for larger screens (lg:
selector), it will use half the width of the parent element.
Notice that you can combine the responsive selectors with any utility class, not only those associated with an element’s size. You can, for instance, hide an element at a certain breakpoint, change its colors, or even turn it into a grid with a variable number of columns.
You can find all available responsive selectors and their equivalent breaking points at the official Tailwind documentation.
The following template sets up a responsive content area at the center of the page, using background gradients and an example avatar image. For the buttons, it uses a grid flow system that will break the container into three columns starting at medium screens, but will make the buttons occupy the full container size when the page is accessed from smaller screens.
Open the resources/views/index.blade.php
file that you created in the previous step in your code editor and replace the contents with the following template:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Sammy the Shark - About Page</title>
<meta name="description" content="My Application Description">
<meta name="author" content="Sammy">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body class="bg-gradient-to-r from-blue-400 via-purple-600 to-blue-700">
<div class="w-3/4 lg:w-1/2 mx-auto rounded-md bg-gray-200 shadow-lg m-20 p-10 text-center">
<img src="{{ asset('img/profile_image.png') }}" class="w-32 lg:w-1/6 bg-blue-600 mx-auto rounded-lg mb-4" alt="avatar"/>
<h1 class="text-3xl">Sammy the Shark</h1>
<p class="text-gray-500 pb-4">Content Creator</p>
<p class="text-gray-700 mb-6">Hello, I'm Sammy. I am a friendly shark interested in Linux, coding, and community.
You can find out more about me in the following links:</p>
<div class="grid grid-cols-1 md:grid-cols-3 grid-flow-row gap-6">
<div class="px-4 py-2 bg-blue-600 text-gray-100 rounded-md mr-4 hover:bg-blue-700"><a href="https://twitter.com/digitalocean">Twitter</a></div>
<div class="px-4 py-2 bg-blue-600 text-gray-100 rounded-md mr-4 hover:bg-blue-700"><a href="https://www.linkedin.com/company/digitalocean">LinkedIn</a></div>
<div class="px-4 py-2 bg-blue-600 text-gray-100 rounded-md mr-4 hover:bg-blue-700"><a href="https://instagram.com/thedigitalocean">Instagram</a></div>
</div>
</div>
</body>
</html>
This template will produce the following page:
And this is how the page adapts to different screen sizes:
In the updated template, each HTML element has a number of Tailwind classes and selectors applied to them. Tailwind uses specific nomenclature for its utility classes to create responsive layouts. Each of the following is used in the example template to create the final result:
bg-gradient-to-r
: creates a gradient from left to right, using the specified colors.w-1/3
: sets the width of the element to one third (1/3) of the parent’s element width. There are many different ways to set up an element’s width within Tailwind.mx-auto
: centers the element.rounded-md
: creates rounded corners, “medium” (md) in size.shadow-lg
: creates a shadow effect, “large” (lg) in size.mr-*
and other m
variants: used to set up an element’s margins.pb-*
and other p
variants: used to set up an element’s padding.hover:bg-blue-700
: changes the background color of the selected element on mouse hover.Check Tailwind’s official documentation for a complete reference of all available utility classes.
In this tutorial, you’ve bootstrapped a new Laravel application using Laravel Sail and Tailwind CSS. You also created a responsive “about me” landing page using Tailwind’s powerful utility classes.
If you’d like to build a more complex landing page and learn more about Tailwind in the process, you can follow our guide on How To Build a Styled Landing Page with Tailwind CSS for detailed instructions on how to create a complete website page with this framework.
If you’d like to learn more about Laravel in a project-based guide, you can refer to our How To Build a Links Landing Page in PHP with Laravel series. For more PHP content, check our PHP tag.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
I was struggling with this example for ages and I found out that v3 only adds CSS for your content files. So if this does not work try updating your tailwind config.
Then run
./vendor/bin/sail npm run dev
Isso foi muito útil, obrigada!