DEV Community

Flemming
Flemming

Posted on

Laravel with NGINX Unit

In this brief tutorial, I'll provide a quick overview of how I hosted a small Laravel application using the new lightweight Nginx Unit Server.

Why?

My goal was to host a Laravel application in Docker without the overhead of managing nginx and PHP-FPM. While I could use the built-in command php artisan serve, it's not as performant as PHP-FPM. Therefore, I decided to utilize the new Unit Server from Nginx.

How?

The configuration file

Unit is configured via a handy JSON file. This file allows me to define the type of application to be executed and the location of static files.

{
    "listeners": {
        "*:80": {
            "pass": "routes"
        }
    },
    "routes": [
        {
            "match": {
                "uri": "!/index.php"
            },
            "action": {
                "share": "/var/www/html/public$uri",
                "response_headers": {
                    "Cache-Control": "max-age=60, s-maxage=120"
                },
                "fallback": {
                    "pass": "applications/laravel"
                }
            }
        }
    ],
    "applications": {
        "laravel": {
            "type": "php",
            "root": "/var/www/html/public/",
            "script": "index.php"
        }
    }
}

Enter fullscreen mode Exit fullscreen mode
  1. Initially, I defined a listener on a specific port.
  2. This listener directs all requests, checking if the requested asset is static; otherwise, it falls back to the application block.
  3. In the application config, I defined the language to be used and the script's location for execution.

Dockerfile

Fortunately, Unit provides prebuilt Docker images that I utilized in the following steps.

FROM unit:php8.2

# Prepare workfir
RUN mkdir -p /var/www/html
RUN mkdir -p /var/www/html/databasestore
WORKDIR /var/www/html

# Pullin build artifacts from build stage
COPY --from=build --chown=unit:unit /var/www/html /var/www/html

# Set timezone
ENV TZ=Europe/Berlin

# Update package lists and install required dependencies
RUN apt-get update && apt-get install -y \
    libicu-dev \
    libjpeg-dev \
    libpng-dev \
    libfreetype6-dev \
    sudo \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

# Install and enable the intl and gd extensions
RUN docker-php-ext-install intl gd

COPY docker/config.json /docker-entrypoint.d/config.json

COPY docker/entrypoint.sh /docker-entrypoint.d/entrypoint.sh

RUN chmod +x /docker-entrypoint.d/entrypoint.sh

EXPOSE 80
Enter fullscreen mode Exit fullscreen mode
  1. 1. Initially, I set up everything, including creating the workspace, setting the timezone, and installing required extensions.
  2. The most crucial tasks are the last two COPY commands, placing config.json and entrypoint.sh in /docker-entrypoint.d. Unit will reconfigure itself using config.json and then execute entrypoint.sh, which migrates the database, flushes the config, etc.

Now, I have a relatively compact image that serves my Laravel application much more efficiently than the built-in serve command. It's easier to configure and has less overhead.

You can find an example repository here: https://github.com/chaostreff-flensburg/simple-borrow

Top comments (0)