Deploying Laravel Projects to Kubernetes

Lukas Gentele
Oct 22, 2019 · 9 min read

Future-proof Laravel deployments with Kubernetes and DevSpace.

No Kubernetes Cluster? No Problem.

This tutorial works with any Kubernetes cluster (minikube, GKE, AKS, EKS etc.) but if you are new to Kubernetes and want to explore how to deploy your Laravel application before setting up a cluster, you can simply use the free tier of DevSpace Cloud — we are providing free Kubernetes namespaces in fully managed clusters to get you started as quickly as possible. If you are more familiar with Kubernetes, you can, of course, use your own cluster or switch to it whenever you like.

Portability is one of the biggest strengths of Kubernetes.

Prerequisites

Before we get started, make sure you have Docker installed and you marked the hard drive containing your working directory as Shared Drive.

1. Create a Laravel Project

If you already have a Laravel project, you can skip this step.

Before creating a Laravel project, let’s define a variable with the directory that we want our Laravel project to be located in:

PROJECT_DIR=/c/Users/[username]/my-laravel-project # win (git-bash)
PROJECT_DIR=/home/[username]/my-laravel-project # mac, linux (bash)

Make sure you have sufficient (write) permissions for the directory and that you are using the correct syntax.

If you are using Docker Toolbox, you must use a directory inside your home directory (e.g. C:/Users/[username]/my-laravel-project).

To create a Laravel project, we can simply run the following Docker command:

mkdir $PROJECT_DIR docker run --rm -v /$PROJECT_DIR:/app composer/composer create-project --prefer-dist laravel/laravel . cd $PROJECT_DIR

Running this command can take quite a while. Sometimes it looks like it’s hanging but it just takes some time to set up a powerful framework such as Laravel. So, be patient and make sure you wait until the command successfully terminates.

If you are on Windows, you can run this command using git-bash.

If you see the error “Drive has not been shared”, make sure you mark the hard drive containing your working directory as Shared Drive.

Now, you should be inside the root directory of your new Laravel project. Three simple commands left and our Laravel project is ready to be deployed to Kubernetes.

Inside the Laravel project, we can find a file called .env.example. You need to copy this file to .env:

cp .env.example .env

Laravel needs a secure application key to encrypt data, so we need to create this key before deploying the project:

docker run --rm -v /$PROJECT_DIR:/app --entrypoint="//usr/local/bin/php" composer/composer artisan key:generate

As you can see, we also run this command via Docker, so we don’t need PHP or anything else on our local development machine.

The last step to get our new Laravel project ready is to run the artisan optimize command:

docker run --rm -v /$PROJECT_DIR:/app --entrypoint="//usr/local/bin/php" composer/composer artisan optimize

2. Containerize Project

Alright. Now, we are ready to containerize our Laravel project. We are using DevSpace, an open-source development tool for Kubernetes, for containerizing and deploying our Laravel project, so let’s install DevSpace. The easiest option to install DevSpace is to run the following npm command:

npm install -g devspace

For other install options, take a look at the DevSpace GitHub page.

After installing DevSpace, run the following command inside your Laravel project directory:

devspace init

DevSpace will ask a couple of questions that are pretty easy to answer. If you are not sure about a question, just use the answer that is selected by default and press Enter.

Make sure you select php as language. Because Laravel has a package.json and quite a few Javascript files, DevSpace detects the language as javascript. Make sure, you change that and select php using the UP/DOWN arrow keys on your keyboard before hitting Enter.

When DevSpace shows you a warning that the application is listening on port 80 which is a privileged port, just hit Enter, so DevSpace will use 8080 to show your Laravel project on localhost.

After DevSpace containerized our project, we will find a Dockerfile inside the project directory. To make this Dockerfile working for Laravel, we need to add the following lines at the end of the Dockerfile:

ENV APACHE_DOCUMENT_ROOT=/var/www/html/public RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf

That’s it! Our project is now fully containerized and ready to be deployed to Kubernetes.

3. Choose Kubernetes Cluster

Now, we need to decide to which Kubernetes cluster we want to deploy our Laravel project. As mentioned in the beginning, DevSpace sponsors free Kubernetes namespaces. So, if you don’t have a Kubernetes cluster, you can run the following command to create a hosted Kubernetes namespace directly from the command-line:

devspace create space tutorial-laravel

After running this command, DevSpace sets up a so-called kube-context that allows you to access this namespace with any Kubernetes tool such as kubectl or helm.

If you already have a Kubernetes cluster, you can skip the above command and instead make sure that you are in the right kube-context that is pointing to your cluster. To tell DevSpace to use your own cluster, you can run the following command to let DevSpace know which namespace to use:

devspace use namespace [YOUR_NAMESPACE]

DevSpace will automatically create the namespace before deploying the project if it does not exist yet.

4. Start Development

Before deploying in “production-like” mode, I want to show you how you can iteratively test your application inside a Kubernetes cluster. To do that, simply run:

devspace dev

This command will build a Docker image based on our Dockerfile, push this Docker image to a Docker registry (e.g. Docker Hub) and then deploy our Laravel project to the Kubernetes cluster. But instead of stopping there, this development command will also stream the logs of our application and then open the application on localhost (via so-called port-forwarding). That means that the Laravel project is running inside a container which runs in a Kubernetes cluster but we can still access the application via localhost in the browser as long as devspace dev is still running.

If everything starts as it should be, DevSpace will show the Apache logs and shortly after, the browser will open with your Laravel site on localhost:8080 showing this getting started page:

Laravel Welcome Page Running Inside Kubernetes — Congrats!

Additionally, when we run devspace dev, DevSpace will also watch for file changes on the local filesystem within our project directory. That means that whenever you change a file, DevSpace will update our Laravel deployment directly inside Kubernetes.

Try it out:

  1. Change the following file: resources/views/welcome.blade.php
  2. Reload the browser and see your changes directly taking effect.

Pretty fast, right?

Because we are running commands such as php artisan ... very often when working with Laravel, it makes sense to create a little shortcut to make it easier to execute these commands directly inside our Kubernetes containers. Add the following lines to the end of of devspace.yaml:

commands: 
- name: php
command: devspace enter php

devspace.yaml is the configuration file for DevSpace and let's you define how your application should be deployed and developed using Kubernetes. It is pretty powerful and allows a lot of customization.

After adding the above lines and saving the devspace.yaml, you can now run php artisan ... commands within Kubernetes like this:
devspace run php artisan ...
Instead of artisan, you could also run any other PHP command, as long as it starts with devspace run php.

Try it yourself and run:

devspace run php artisan optimize

Before continuing with this step, make sure you end the devspace dev command using CTRL+C.

Most Laravel projects need a database, so I will show you how to add a Kubernetes-based mysql database to your project. Everything that DevSpace deploys to Kubernetes is defined within the devspace.yaml, so let's change this file to add a MySQL database. Right under the line containing deployments:, add the following:

- name: database
helm:
chart:
name: stable/mysql
values:
mysqlDatabase: "homestead"
mysqlUser: "homestead"
mysqlRootPassword: ${DB_ROOT_PASSWORD}
mysqlPassword: ${DB_PASSWORD}

We are defining homestead as username and database name because that is the default for Laravel projects. The password for the users root and homestead are defined as a DevSpace variables. The next time, we will deploy the project with DevSpace, DevSpace will ask us to provide a value for each one of these variables.

After adding this MySQL deployment to our configuration, we also need to tell the Laravel deployment how to access the database. To do this, we need to add the following lines:

        env:
- name: DB_HOST
value: database-mysql
- name: DB_PASSWORD
value: ${DB_PASSWORD}

So our final deployments section in devspace.yaml will look like this:

deployments:
- name: database
helm:
chart:
name: stable/mysql
values:
mysqlDatabase: "homestead"
mysqlUser: "homestead"
mysqlRootPassword: ${DB_ROOT_PASSWORD}
mysqlPassword: ${DB_PASSWORD}
- name: my-laravel-project # this line may be different for you
helm:
componentChart: true
values:
containers:
# this line may be different for you
- image: dscr.io/${DEVSPACE_USERNAME}/mylaravelproject
env:
- name: DB_HOST
value: database-mysql
- name: DB_PASSWORD
value: ${DB_PASSWORD}
service:
ports:
- port: 80

Now, we can deploy this project again and DevSpace will add the MySQL to our Laravel app. So, let’s run:

devspace dev

The first time you run devspace dev after this change, DevSpace will ask you to define a database password that is used for the variable DB_PASSWORD.

DevSpace will only show the logs of our Laravel project but not of the MySQL because the database is using a standard Docker image which is not built by DevSpace during the deployment process.

Before we continue, make sure your MySQL database is up and running. You can do that by checking the logs. So, either close devspace dev after you see the Apache logs or open another terminal and run the following command to stream the logs of the MySQL database:

devspace logs -f

When you see one of the following log lines, then the MySQL server is ready:

# Option 1: 
2019-10-16T03:46:32.089655Z 0 [Note] mysqld: ready for connections.
# Option 2:
MySQL init process done. Ready for start up.

It might take a while when starting the MySQL server for the very first time.

After the database is ready, run the following command to initialize the data for our Laravel application inside the MySQL database:

devspace run php artisan migrate

You should see an output like this one:

Migration table created successfully. Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table Migrating: 2014_10_12_100000_create_password_resets_table Migrated: 2014_10_12_100000_create_password_resets_table

To add authentication for our Laravel project, you can simply run the following command:

devspace run php artisan make:auth

Before you run this command, make sure you added the MySQL database and initialized the data for it.

After running the artisan make:auth command, you should see an output like this one:

Authentication scaffolding generated successfully.

For more info on how to configure your Laravel authentication, take a look at the official documentation: https://laravel.com/docs/5.8/authentication#introduction

Laravel Signup Page — Adding Authentication

5. Deploy Project

Now, you know how to run devspace dev and develop a Laravel project using Kubernetes. When you're ready to deploy your project in a more production-like fashion and make it available on a public domain, you can run the following command:

devspace deploy

In contrast to devspace dev, devspace deploy terminates after deploying the project.

If you want to access the deployed project, you can run the following command:

devspace open

DevSpace will ask you if you want to access the Laravel application using port-forwarding (e.g. via localhost just like when running devspace dev) or if it should make the project accessible on a public URL.

Congrats, now your application is running inside a Kubernetes cluster!

Tip: Use a separate namespace for development and production. You can run the command devspace use space [name] for DevSpace Cloud or devspace use namespace [namespace] for your own clusters to switch between namespaces. After running one of these command, just run devspace dev to develop the project or devspace deploy to deploy the project just as you have done it during the tutorial.


Next: Optimize for Production

Of course, our “production-like” deployment still needs some fine-tuning. At the moment, there is no optimization for automatic scaling, caching etc. — but this tutorial is already pretty long and I want to make sure you are familiar with the basics first. In my next article, I will show you how to add a high available Redis cluster for caching and how to optimize your MySQL database and your Dockerfile for automated scaling using Kubernetes.

Subscribe below to receive an email when this article will be online.

If this is helpful to you or you have any questions or ideas what might be interesting to blog about next, reach out via twitter @LukasGentele or email: lg AT devspace.cloud

Looking forward to hearing from you!


Originally published at https://devspace.cloud.

The Startup

Medium's largest active publication, followed by +587K people. Follow to join our community.

Lukas Gentele

Written by

The Startup

Medium's largest active publication, followed by +587K people. Follow to join our community.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade