Kubernetes Development Blog
  • Docs
  • GitHub
  • Blog
  • Install

›Recent Posts

Recent Posts

  • DevOps and the Cloud: Tools and Technologies for Forward Looking DevOps Teams
  • The Missing Kubernetes Platform for Developers
  • How to Give Developers Access to Kubernetes During Development
  • How to deal with computing resource cost for Kubernetes-based development
  • Why Cloud Development Could (Finally) Become the New Standard

Deploying Laravel Projects to Kubernetes

October 16, 2019

Lukas Gentele

Lukas Gentele

Future-proof Laravel deployments with Kubernetes and DevSpace.

Prerequisites

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

DevSpace works with any Kubernetes cluster (minikube, GKE, AKS, EKS etc.) or virtual Clusters, so you can use any of these solutions for this tutorial.

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  # for git-bash on windows
PROJECT_DIR=/home/[username]/my-laravel-project     # for unix-based systems (mac, linux)

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 setup 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.

Copy .env.example

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

cp .env.example .env

Create Encryption Key

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.

Optimize

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:

# Change Apache root directory
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 works with any cluster.

If you do not have a cluster yet, you can create one locally with tools such as minikube or kind. There are also many managed Kubernetes services in public clouds, such as EKS, AKS, or GKE. If your team has connected a cluster to loft, you are able to create virtual clusters and namespaces in a shared cluster. (There even is the loft-devspace-plugin, so you can also control loft via DevSpace.)

After you made sure that you have access to a cluster and that you are in the right kube-context that is pointing to your cluster, we need to tell DevSpace create a namespace in this cluster. For this, we run the following command:

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?

Subscribe for more tips about Kubernetes!
Subscriptions

Tip: Define PHP Shortcut Command

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

Extra: Add MySQL Database

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
      version: "1.4.0"
    values:
      mysqlDatabase: "homestead"
      mysqlUser: "homestead"
      mysqlRootPassword: ${DB_ROOT_PASSWORD}
      mysqlPassword: ${DB_PASSWORD}

As shown in the config snippet, 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.

To view a list of all available config options (i.e. values) for this mysql deployment, take a look at the documentation of this Helm chart on GitHub.

Before deploying the database, we 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
      version: "1.4.0"
    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:
      - image: dscr.io/${DEVSPACE_USERNAME}/mylaravelproject  # this line may be different for you
        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.

In addition to deploying our Laravel application to Kubernetes, the devspace dev command also starts a powerful development UI which runs on localhost and is available as long as the devspace dev command is running.

You should see a log statement similar to this one in the output of devspace dev:

#########################################################
[info]   DevSpace UI available at: http://localhost:8090
#########################################################

So go ahead and check out the DevSpace UI in your browser! You can use it to see the container and pod status of your deployments as well as to stream logs and open interactive terminal sessions for every container. It should look like in this screencast:

DevSpace: Kubernetes Development UI - Screencast

Before we continue, make sure your MySQL database is up and running. You can do that by checking the logs in the development UI or by opening another terminal and running the following command:

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

Extra: Add Auth

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 namespace [namespace] to switch between namespaces. After running this 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.

Subscribe below to receive an email when my next article about development with Kubernetes is 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!

Tweet
Recent Posts
  • Prerequisites
  • 1. Create a Laravel Project
    • Copy .env.example
    • Create Encryption Key
    • Optimize
  • 2. Containerize Project
  • 3. Choose Kubernetes Cluster
  • 4. Start Development
    • Tip: Define PHP Shortcut Command
    • Extra: Add MySQL Database
    • Extra: Add Auth
  • 5. Deploy Project
  • Next: Optimize for Production
Star
Don't miss new blog posts and subscribe here:
Subscriptions