- How to install and set up Laravel with Docker Compose on Ubuntu 22.04?
- Initial checklist
- Installing Docker and Docker Compose on Ubuntu 22.04
- Proposed project structure
- Recommended Dockerfile for PHP-FPM (PHP 8.1)
- docker-compose.yml example
- Nginx configuration file (docker/nginx/default.conf)
- Preparing the code and installing dependencies
- Setting up the .env file for Docker
- SSL and Let's Encrypt — Two Easy Ways
- Launch at boot and maintain service
- Practical security tips
- Performance optimization for production environments
- Queue workers and Horizon
- Tips related to location and data center selection
- Backups, monitoring, and logs
- Common debugging
- Conclusion and final recommendation
- Related services
- Frequently Asked Questions
How to install and set up Laravel with Docker Compose on Ubuntu 22.04?
In this practical and technical guide, we will walk you through the step-by-step process of installing and configuring an application. Laravel Using Docker Compose On the server Ubuntu 22.04 The goal of this article is to provide repeatable guidelines for developers, DevOps teams, and technical managers to create a secure, scalable, and maintainable production environment.
Initial checklist
Before you begin, prepare the following:
- A server Ubuntu 22.04 With root access or a user with sudo
- Docker (stable version) and Docker Compose (or use docker compose plugin)
- Open ports: 80/443 For the web; if needed 3306 Or 5432 For database (preferably limited to IPs)
- Adequate disk space (SSD recommended) and access to one of more than 85 locations Global if using cloud services
- Domain name and DNS record pointing to the server IP
Installing Docker and Docker Compose on Ubuntu 22.04
Run the following commands on the server to install Docker and the docker compose plugin:
sudo apt update && sudo apt upgrade -y
sudo apt install -y ca-certificates curl gnupg lsb-release
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmour -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
sudo usermod -aG docker $USERThen log out and log back in or newgrp docker Use.
To check the installation:
docker --version
docker compose versionProposed project structure
It is recommended that the project folder be organized as follows to make maintenance and development easier:
project-root/docker/nginx/default.confphp/Dockerfile
src/— Laravel code (or mount)docker-compose.yml.env
Recommended Dockerfile for PHP-FPM (PHP 8.1)
A file with a path docker/php/Dockerfile Create something like the following example:
FROM php:8.1-fpm
# Install required tools and extensions
RUN apt-get update && apt-get install -y \
git zip unzip libpng-dev libjpeg-dev libfreetype6-dev libonig-dev libxml2-dev \
libzip-dev libpq-dev cron curl supervisor \
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install -j$(nproc) gd pdo pdo_mysql pdo_pgsql mbstring xml bcmath zip opcache \
&& pecl install redis && docker-php-ext-enable redis \
&& pecl install xdebug || true \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
# Composer
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
# Create non-root user
RUN useradd -G www-data,root -u 1000 -d /home/appuser appuser
WORKDIR /var/www/html
USER appuserdocker-compose.yml example
Suggested version docker-compose.yml To run the application, web server, database, and Redis:
version: "3.8"
services:
app:
build:
context: .
dockerfile: docker/php/Dockerfile
image: laravel_app:latest
container_name: laravel_app
restart: unless-stopped
volumes:
- ./src:/var/www/html
- ./docker/php/supervisord.conf:/etc/supervisor/conf.d/supervisord.conf
environment:
- APP_ENV=production
- APP_DEBUG=false
networks:
- laravel-net
web:
image: nginx:alpine
container_name: laravel_web
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./src:/var/www/html:ro
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
- ./certs:/etc/letsencrypt
depends_on:
- app
networks:
- laravel-net
db:
image: mysql:8.0
container_name: laravel_db
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_DATABASE: laravel
MYSQL_USER: laravel
MYSQL_PASSWORD: secret
volumes:
- db_data:/var/lib/mysql
networks:
- laravel-net
redis:
image: redis:6-alpine
container_name: laravel_redis
restart: unless-stopped
volumes:
- redis_data:/data
networks:
- laravel-net
volumes:
db_data:
redis_data:
networks:
laravel-net:
driver: bridgeNginx configuration file (docker/nginx/default.conf)
Example Nginx configuration to route requests to PHP-FPM (app):
server {
listen 80;
server_name example.com;
root /var/www/html/public;
index index.php index.html;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass app:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
location ~ /\.ht {
deny all;
}
}Note: In architectures with reverse proxy or multiple services, you can put Nginx at the load balancer or CDN layer.
Preparing the code and installing dependencies
If you don't have a Laravel project, you can create a new one with Composer:
composer create-project --prefer-dist laravel/laravel srcThen to build and run containers:
docker compose build
docker compose up -dTo run Composer and Artisan commands inside a PHP container:
docker exec -it laravel_app bash
composer install --no-dev --optimize-autoloader
php artisan key:generate
php artisan migrate --force
php artisan config:cache
php artisan route:cache
exitSetting up the .env file for Docker
Example .env configuration compatible with docker-compose:
DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=laravel
DB_PASSWORD=secret
CACHE_DRIVER=redis
REDIS_HOST=redis
APP_URL=https://example.comSSL and Let's Encrypt — Two Easy Ways
There are two simple ways to enable HTTPS:
- Using Certbot on the host: Stop Nginx temporarily, place the issued certificate in the folder
./certsand mount it to the container. - Using the automated solution: Tools like docker-letsencrypt-nginx-proxy-companion Or Traffic They are suitable for automated certificate management.
Quick example with Certbot:
sudo apt install -y certbot
sudo docker compose down
sudo certbot certonly --standalone -d example.com --non-interactive --agree-tos -m [email protected]
# Copy certificates from /etc/letsencrypt/live/... to ./certs and then:
sudo docker compose up -dLaunch at boot and maintain service
To ensure services run after reboot:
sudo systemctl enable dockerAdditionally, in docker-compose from restart: unless-stopped It has been used. If needed, a systemd unit can be created for docker-compose.
Practical security tips
- Using a non-root user in a PHP container (
appuserin the Dockerfile above) - Restricting access to the database port with firewall (UFW):
sudo ufw allow OpenSSH
sudo ufw allow 80,443/tcp
sudo ufw enableOther recommendations:
- Regular backup of the database volume (
db_data) and storing it outside the server - Enabling HTTPS and HSTS
- Using secrets or key management services to store passwords (Docker secrets or key management services)
- Use security tools such as fail2ban And if needed WAF like ModSecurity
- Using a CDN or Anti-DDoS service to protect traffic
Performance optimization for production environments
- Enabling OPcache in
php.ini:opcache.memory_consumption=256 opcache.validate_timestamps=0 - Setting up php-fpm (pm = dynamic or ondemand) and increasing
max_childrenAccording to server memory - Using Redis for cache and sessions
- Using a CDN for static files
- Horizontal scaling: running multiple instances of the app service with a load balancer (NGINX or HAProxy)
- Use separate workers and supervisors or services for real-time and queues.
Queue workers and Horizon
Add a separate service in docker-compose to run queue workers. Example:
worker:
build: ...
command: php /var/www/html/artisan queue:work --sleep=3 --tries=3
depends_on: [app, redis]
restart: unless-stoppedFor Laravel Horizon it is best to use a dedicated container with PHP and Horizon installed and place it behind Nginx/authentication.
Tips related to location and data center selection
Practical tips for choosing a location:
- For the lowest latency, choose a server in a location close to your end users or destination. The service provider is more than 85 global locations It has.
- For gamers or traders, choose a location with low ping and an optimized BGP network.
- Use GPU-equipped servers for AI processing and rendering.
- Use servers and CDN with Anti-DDoS protection to resist DDoS.
Backups, monitoring, and logs
- Container logs with
docker logsAre accessible; use ELK or Prometheus+Grafana for central aggregation. - Daily database backup and periodic restore test
- Monitoring CPU/RAM resources, application and error tracking in CI/CD
Common debugging
- 502 Bad Gateway Error: Check that php-fpm is running in the app container and that fastcgi_pass is set to the correct address (
app:9000) to point out. - Database connection problem: Check .env variables, docker network, and MySQL logs.
- File permissions: In case of permission errors, set ownership of the storage and bootstrap/cache folders:
sudo chown -R 1000:1000 src/storage src/bootstrap/cacheConclusion and final recommendation
Using Docker Compose to run Laravel on Ubuntu 22.04 makes development and deployment simple, repeatable, and scalable. By following this guide, you can set up a secure, fast, and maintainable production environment: PHP-FPM with Nginx, MySQL/MariaDB or PostgreSQL, Redis for cache and queue, and SSL settings and monitoring.
Related services
To professionally implement this architecture, you can use the following services:
- More than 85 global locations To reduce latency and bring the server closer to the user or destination
- Graphics server (GPU) for AI computing and rendering
- VPS for trading with low ping and optimized BGP network
- Gaming VPS with low ping and Anti-DDoS
- Hosting and domain registration services, CDN, network and BGP solutions
- High-performance cloud server and managed backup









