# Run Laravel 11 with Docker, Supervisor, and PostgreSQL for a Scalable Development Setup

By Dinesh Uprety
Published: 2024-12-21
Updated: 2024-12-21
Canonical: https://laranepal.com/blog/run-laravel-11-with-docker-supervisor-and-postgresql-for-a-scalable-development-setup

# Running a Laravel 11 Project in Docker with Supervisor and PostgreSQL

## Introduction

Docker simplifies running Laravel projects by offering isolated, reproducible environments. This guide walks you through
setting up a Laravel 11 project in Docker using Supervisor for managing background processes and PostgreSQL as the
database.

## Prerequisites

Before starting, ensure you have the following:

1. **Docker and Docker Compose** installed on your system.
2. **Laravel 11** installed in your project directory.

## Folder Structure

Your project directory should include a .docker folder containing Docker configuration files:

```
project-root/
├── .docker/
│   ├── php/
│   │   ├── Dockerfile
│   │   └── supervisord.conf
│   ├── nginx/
│   │   └── default.conf
│   └── php-supervisor/
│       ├── log/
│       └── Dockerfile
├── app/
├── bootstrap/
├── config/
├── database/
├── public/
├── resources/
├── routes/
├── storage/
├── tests/
├── vendor/
├── .env
├── docker-compose.yml
```

## Step 1: Setting Up Docker Compose

Create a `docker-compose.yml` file in your project root with the following content:

```yaml
version: '3.8'

services:
  app:
    build:
      context: .docker
      dockerfile: php/Dockerfile
    container_name: laravel_11_app # Change this to your project name
    ports:
      - "9001:9000"
    volumes:
      - .:/var/www/html
    networks: # Connect to the laravel_network
      - laravel_network
    restart: unless-stopped
    depends_on: # Wait for the database to start
      - db

  nginx:
    image: nginx:alpine
    container_name: laravel_11_nginx
    ports:
      - "8080:80"
    volumes:
      - .:/var/www/html
      - ./.docker/nginx/default.conf:/etc/nginx/conf.d/default.conf # Nginx configuration
    networks:
      - laravel_network
    depends_on:
      - app

  db:
    image: postgres:15
    ports:
      - "5433:5432"
    restart: always
    environment:
      POSTGRES_DB: laravel # Change this to your database name
      POSTGRES_USER: root # Change this to your database user
      POSTGRES_PASSWORD: root # Change this to your database password
    networks:
      - laravel_network

  supervisor:
    build:
      context: .docker
      dockerfile: php-supervisor/Dockerfile
    container_name: laravel_11_supervisor
    volumes:
      - .:/var/www/html
    networks:
      - laravel_network
    depends_on:
      - app

volumes: # Persist the database data
  db_data:

networks: # Create a network for the services to communicate
  laravel_network:
    driver: bridge
```

## Step 2: Setting Up the PHP Container

Create a `Dockerfile` in the `.docker/php` directory with the following content:

```dockerfile
FROM php:8.3.11-fpm

#Oppitional label
LABEL author="Dinesh Uprety"

# Install dependencies
RUN apt-get update && apt-get install -y \
    build-essential libpng-dev libjpeg-dev libwebp-dev libxpm-dev libfreetype6-dev \
    libzip-dev zip unzip git bash fcgiwrap libmcrypt-dev libonig-dev libpq-dev \
    && rm -rf /var/lib/apt/lists/*

# Install PHP extensions
RUN docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp \
    && docker-php-ext-install gd pdo pdo_pgsql mbstring zip exif pcntl bcmath opcache

# Install Composer
COPY --from=composer/composer:latest-bin /composer /usr/bin/composer

# Copy application code
COPY . /var/www/html/

# Configure permissions and timezone
RUN groupadd -g 1000 www && useradd -u 1000 -ms /bin/bash -g www www \
    && ln -snf /usr/share/zoneinfo/Asia/Kathmandu /etc/localtime \
    && echo "Asia/Kathmandu" > /etc/timezone \
    && printf '[PHP]\ndate.timezone = "Asia/Kathmandu"\n' > /usr/local/etc/php/conf.d/tzone.ini

USER www

EXPOSE 9000

CMD ["php-fpm"]
``` 

For more information about the
Dockerfile, [click here](https://medium.com/@iamsujanshakya/core-concepts-for-web-application-development-using-docker-containerization-part-1-1338b4996000)
to read an explanation by **[Sujan Shakya](https://medium.com/@iamsujanshakya)**.

## Step 3: Configuring Supervisor

Supervisor manages Laravel’s queue workers. The configuration is in `.docker/php/supervisord.conf`:

```ini
[program:laravel_worker]
process_name = %(program_name)s_%(process_num)02d
command = php /var/www/html/artisan queue:work --sleep=3 --tries=3 --max-time=3600
autostart = true
autorestart = true
stopasgroup = true
killasgroup = true
user = www
numprocs = 8
redirect_stderr = true
# Change this to your log file path
stdout_logfile = /var/www/html/.docker/php-supervisor/log/stdout_logfile.log
stopwaitsecs = 3600

[supervisord]
# Change this to your log file path
logfile = /var/www/html/.docker/php-supervisor/log/logfile.log
nodaemon = true
# Change this to your log file path
pidfile = /var/www/html/.docker/php-supervisor/log/pidfile.log
```

The Supervisor container uses its own `Dockerfile` located in `.docker/php-supervisor/`:

```dockerfile
FROM php:8.3.11-fpm

# Update package list and install required libraries
RUN apt-get update && apt-get install -y \
    supervisor \
    libpq-dev \
    && docker-php-ext-install pdo_pgsql \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

# Create the www user and group
RUN groupadd -g 1000 www && useradd -u 1000 -ms /bin/bash -g www www

# Create directories for Supervisor configuration and logs
RUN mkdir -p /var/log/supervisor && chown -R www:www /var/log/supervisor

# Set working directory
WORKDIR /var/www/html

# Copy application code
COPY --chown=www:www . /var/www/html

# Optionally copy specific process configuration files
COPY ./php/supervisord.conf /etc/supervisor/conf.d/supervisord.conf

# Default command to run Supervisor
CMD ["/usr/bin/supervisord", "-n", "-c", "/etc/supervisor/supervisord.conf"]
```

## Step 4: Configuring Nginx

Create a `default.conf` file in the `.docker/nginx` directory with the following content:

```nginx
server {
    listen 80;
    listen [::]:80;
    server_name _;
    root /var/www/html/public;

    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Content-Type-Options "nosniff";

    index index.php index.html index.htm;

    charset utf-8;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    error_page 404 /index.php;

    location ~ ^/index\.php(/|$) {
		# Change this to your app container name <laravel_11_app>
        fastcgi_pass laravel_11_app:9000;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
        fastcgi_hide_header X-Powered-By;
    }

    location ~ /\.(?!well-known).* {
        deny all;
    }
}
```

## Step 5: Running the Containers

Run the following command in your project root to start the containers:

#### 1. Start the containers:

```bash
docker-compose up --build -d
```

#### 2. Access web application container

```bash
docker exec -it laravel_11_app bash
```

#### 3. Run the following command to run the application

```bash
cp .env.example .env

composer install && php artisan key:generate && php artisan migrate && php artisan db:seed
```

#### 4. Access the Application

Once the containers are up and running, open your web browser and navigate to: http://localhost:8080
This URL will provide access to the application.

## Step 6: Managing the PostgreSQL Database

The PostgreSQL container is pre-configured with:

* **Database**: laravel
* **User**: root
* **Password**: root

You can access the database using a PostgreSQL client or by running the following command:

```bash
docker exec -it laravel_11_db psql -U root laravel
```

You can connect using a database client like **DBeaver** or directly in Laravel by updating the `.env` file:

```dotenv
DB_CONNECTION=pgsql
DB_HOST=db
DB_PORT=5432
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=root
```

## Conclusion

You have successfully set up a Laravel 11 project in Docker with Supervisor for managing background processes and
PostgreSQL as the database. This setup provides a robust and scalable environment for developing and deploying Laravel
applications.

## References

- [Docker Documentation](https://docs.docker.com/)
- [Laravel Documentation](https://laravel.com/docs)
- [Supervisor Documentation](http://supervisord.org/)
- [PostgreSQL Documentation](https://www.postgresql.org/docs/)
- [Nginx Documentation](https://nginx.org/en/docs/)
