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 .
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:
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:
This setup ensures a modular, scalable, and secure Laravel deployment.
Thank you !!!
Student at Rajasthan Technical University
3 天前Interesting