Deploying PHP Laravel with Docker Containers and Nginx on Host Machine: Security with Trivy Image Scanning

Deploying PHP Laravel with Docker Containers and Nginx on Host Machine: Security with Trivy Image Scanning

Introduction

In modern web application deployment, Docker simplifies containerizing applications, Laravel provides a powerful PHP framework, and Nginx serves as a high-performance web server. This guide demonstrates setting up Laravel inside a Docker container, connecting it with a MySQL container, running Nginx on the host machine, and scanning Docker images using Trivy for security.


Prerequisites

Before starting, ensure you have:


Step 1: Setting Up Laravel in a Docker Container

Create a Dockerfile for Laravel:

# Use official PHP 8.3 FPM image
FROM php:8.3-fpm
# Set working directory
WORKDIR /var/www
# Install system dependencies and required PHP extensions in a single RUN
RUN apt-get update && apt-get install -y \
    zip unzip git curl build-essential \
    libpng-dev libjpeg-dev libfreetype6-dev \
    libonig-dev libxml2-dev zip libzip-dev \
    && docker-php-ext-configure gd --with-freetype --with-jpeg \
    && docker-php-ext-install gd mbstring pdo pdo_mysql zip bcmath exif pcntl fileinfo opcache \
    && apt-get clean && rm -rf /var/lib/apt/lists/*
# Install Composer globally
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# Copy Laravel project files
COPY . .
# Create necessary directories with correct permissions
RUN mkdir -p /var/www/storage/framework/{sessions,views,cache} \
    && chown -R www-data:www-data /var/www \
    && chmod -R 775 /var/www/storage /var/www/bootstrap/cache
# Switch to non-root user
USER www-data
# Install Laravel dependencies
RUN composer install --no-interaction --prefer-dist --optimize-autoloader
# Pre-cache configurations for performance
RUN php artisan config:cache && php artisan route:cache && php artisan view:cache
# Expose PHP-FPM port
EXPOSE 9000
# Start PHP-FPM
CMD ["php-fpm"]
        

Step 2: Build the Docker Image

docker build -t   simple-registration_app .        

  • -t → Assigns a name (simple-registration_app) to the built image.
  • . → Refers to the current directory where the Dockerfile is located.

2.1 Verify the Image Build

docker images

akhil@akhilpatel:~/Public/simple-registration$ docker images
REPOSITORY                TAG       IMAGE ID       CREATED          SIZE
simple-registration_app   latest    59a9f6de790d   59 minutes ago   709MB        

Step 3: Setting Up MySQL in a Docker Container

Create a docker-compose.yml file to define the MySQL container.

version: '3.8'

services:
  app:
    build: 
      context: .
      dockerfile: Dockerfile
    container_name: php_container
    restart: always
    working_dir: /var/www
    ports:
      - "9000:9000"
    networks:
      - my_bridge_network

  mysql:
    image: mysql:8
    container_name: mysql_container
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: laravel_db
      MYSQL_USER: laravel_user
      MYSQL_PASSWORD: secret
    ports:
      - "3306:3306"
    networks:
      - my_bridge_network
    volumes:
      -  mysql_data:/var/lib/mysql  # Persistent volume for MySQL
      - . /db_backup:/db_backup  # Host to container volume

networks:
  my_bridge_network:
    driver: bridge
volumes:
   mysql_data:        

Step 4: Configuring Nginx on the Host Machine

server {
    listen 80;
    server_name laravel.com;
    root /var/www/public; # Laravel's public directory

    index index.php index.html index.htm;

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

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_pass 127.0.0.1:9000; # Connects to PHP-FPM in Docker
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param DOCUMENT_ROOT $document_root;
    }

    location ~ /\.ht {
        deny all;
    }
}
        
#Restart Nginx service
sudo systemctl restart nginx        

Step 5: Running Containers

Start the Laravel and MySQL containers:

docker-compose up --build  -d        

Verify that the containers are running:

docker ps        


php_container and mysql_ container is up

akhil@akhilpatel:~/Public/simple-registration$ docker ps
CONTAINER ID   IMAGE                     COMMAND                  CREATED         STATUS          PORTS                                                    NAMES
948ddc9dd446   simple-registration_app   "docker-php-entrypoi…"   4 minutes ago   Up 4 minutes    0.0.0.0:9000->9000/tcp, [::]:9000->9000/tcp              php_container
99a7599d38c7   mysql:8                   "docker-entrypoint.s…"   4 minutes ago   Up 4 minutes    0.0.0.0:3306->3306/tcp, [::]:3306->3306/tcp, 33060/tcp   mysql_container        


Step 6: Scanning Docker Images with Trivy

trivy image simple-registration_ap        
trivy config Dockerfile        

Docker images (trivy image)

File systems (trivy fs)

Git repositories (trivy repo)

Running containers (trivy --input)

Kubernetes clusters (trivy k8s)

Docker configurations (trivy config)Trivy is a powerful tool to ensure security before deploying applications. You can use it to scan:

  1. Docker images (trivy image)
  2. File systems (trivy fs)
  3. Git repositories (trivy repo)
  4. Running containers (trivy --input)
  5. Kubernetes clusters (trivy k8s)
  6. Docker configurations (trivy config)

Step 7: Open in the Browser

If Nginx is configured correctly, your Laravel application should be accessible at:

https://localhost
        

If you configured a domain, use:

https://yourdomain.com
        

Import an SQL File (If You Have an Existing Database)

Access the MySQL container and get the username and password from docker-compose file.


akhil@akhilpatel:~/Public/simple-registration$ docker exec -it mysql_container /bin/bash
bash-5.1# mysql -u root -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 11
Server version: 8.4.4 MySQL Community Server - GPL

Copyright (c) 2000, 2025, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>         

The SQL file is located inside the db_backup directory in the MySQL container and needs to be imported.


Enter the details, and after completing the registration, you can log in.

Conclusion

This article covered:

  1. Setting up Laravel inside a Docker container.
  2. Running MySQL in a separate container.
  3. Configuring Nginx on the host machine to serve Laravel.
  4. Using Trivy to scan Docker images for security vulnerabilities.

This setup ensures a modular, scalable, and secure Laravel deployment.

Thank you !!!

ASHISH SHARMA

Student at Rajasthan Technical University

3 天前

Interesting

要查看或添加评论,请登录

Akhilesh Patel的更多文章