Series Dockerize Laravel Thực chiến #2: Lắp ráp động cơ LEMP & Giao thức FastCGI
1. Rèn đúc lõi xử lý PHP-FPM (Dockerfile)
Image php:8.2-fpm nguyên bản trên Docker Hub rất nhẹ, nhưng nó thiếu gần như toàn bộ các "đồ chơi" (extensions) mà Laravel cần để chạy. Nếu để nguyên mà chạy, Laravel sẽ văng lỗi ngay lập tức vì không kết nối được MySQL hay không xử lý được file ZIP.
Bạn hãy mở file docker/php/Dockerfile đã tạo ở Bài 1 và dán đoạn mã sau vào:
# Sử dụng phiên bản PHP 8.2 FPM
FROM php:8.2-fpm
# Cài đặt các thư viện hệ thống cần thiết cho các extension của PHP
RUN apt-get update && apt-get install -y \
git \
curl \
libpng-dev \
libonig-dev \
libxml2-dev \
libzip-dev \
zip \
unzip
# Xóa cache apt để image nhẹ hơn
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
# Cài đặt các PHP extensions bắt buộc cho Laravel
RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd zip
# Copy Composer từ image chính thức vào container này để tiện dùng lệnh
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# Thiết lập thư mục làm việc mặc định
WORKDIR /var/www/html
2. Dạy Nginx cách "Bắt tay" với PHP
Như đã nói, Nginx là một gã bảo vệ đứng ở cửa, chỉ biết trả về các file tĩnh (HTML, CSS). Khi người dùng truy cập một route yêu cầu logic Laravel (ví dụ: /api/campaigns), Nginx sẽ "đứng hình".
Nhiệm vụ của chúng ta là viết cấu hình để bảo Nginx: "Ê, nếu thấy đuôi .php hoặc route không tìm thấy file tĩnh, hãy ném nó qua cái cổng số 9000 của container PHP bằng giao thức FastCGI".
Mở file docker/nginx/default.conf và điền cấu hình sau:
server {
listen 80;
index index.php index.html;
server_name localhost;
# TRỌNG TÂM: Phải trỏ root vào thư mục public của Laravel
root /var/www/html/public;
# Xử lý các request thông thường, nếu không có file tĩnh thì đẩy vào index.php
location / {
try_files $uri $uri/ /index.php?$query_string;
}
# Bắt các request có đuôi .php và ném sang container app (PHP-FPM)
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
# 'app' là tên service của container PHP trong file docker-compose
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;
}
}
3. Nhạc trưởng Docker Compose kết nối hệ thống
Bây giờ chúng ta đã có bản vẽ cho Nginx và PHP. Để mang Database MySQL vào và kết nối cả 3 thành phần này lại, hãy mở file docker-compose.yml ở thư mục ngoài cùng:
version: '3.8'
services:
# 1. Container Nginx (Web Server)
webserver:
image: nginx:alpine
container_name: laravel_web
restart: unless-stopped
ports:
- "8000:80" # Mở port 8000 ra máy thật để bạn truy cập
volumes:
- ./:/var/www/html # Map toàn bộ code vào trong container
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf # Map cấu hình
depends_on:
- app
networks:
- laravel_network
# 2. Container PHP-FPM (Bộ não xử lý)
app:
build:
context: .
dockerfile: docker/php/Dockerfile
container_name: laravel_app
restart: unless-stopped
volumes:
- ./:/var/www/html
networks:
- laravel_network
# 3. Container Database (MySQL)
db:
image: mysql:8.0
container_name: laravel_db
restart: unless-stopped
environment:
MYSQL_DATABASE: ${DB_DATABASE:-laravel_app}
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD:-secret}
MYSQL_PASSWORD: ${DB_PASSWORD:-secret}
MYSQL_USER: ${DB_USERNAME:-laravel_user}
ports:
- "3306:3306"
volumes:
- db_data:/var/lib/mysql # Giữ lại dữ liệu database khi tắt container
networks:
- laravel_network
# Định nghĩa mạng ảo để 3 container nhìn thấy nhau
networks:
laravel_network:
driver: bridge
# Định nghĩa ổ cứng ảo cho MySQL
volumes:
db_data:
4. Kích hoạt toàn bộ hệ thống
Mọi thứ đã chuẩn bị xong. Giờ là lúc bạn thi triển ma thuật. Cấp quyền cho file .env nếu cần thiết (copy từ .env.example sang .env), và mở Terminal gõ lệnh:
docker-compose up -d --build
Docker sẽ bắt đầu tải Ubuntu, tải Nginx, biên dịch PHP và cài đặt các extension. Khi quá trình hoàn tất, bạn mở trình duyệt và truy cập vào địa chỉ: http://localhost:8000
Nếu bạn nhìn thấy màn hình chào mừng đỏ rực của Laravel, xin chúc mừng! Cụm LEMP Stack chuẩn Enterprise của bạn đã hoạt động trơn tru.
Hệ thống đã chạy, nhưng hiện tại nếu bạn muốn gõ các lệnh quen thuộc như php artisan migrate hay composer require thì làm thế nào khi máy tính của bạn vẫn không hề cài PHP? Ở Bài 3, bạn muốn chúng ta đi sâu vào Cách chạy Artisan/Composer trực tiếp qua Docker exec, hay muốn học cách Cấu hình tối ưu quyền sở hữu file (File Permissions) để tránh lỗi không upload được ảnh trên môi trường Linux?
All rights reserved