❤️ AZDIGI chính thức cập nhật hệ thống blog mới hoàn chỉnh. Tuy nhiên có thể một số bài viết bị sai lệch hình ảnh, hãy ấn nút Báo cáo bài viết ở cuối bài để AZDIGI cập nhật trong thời gian nhanh nhất. Chân thành cám ơn.
Ở Bài 7, bạn đã deploy thành công WordPress + MySQL + phpMyAdmin bằng Docker Compose, một stack hoàn chỉnh với database, web app, và công cụ quản lý. Bạn đã thấy cách các container giao tiếp qua Docker network, cách dùng volumes để giữ dữ liệu, và cách environment variables giúp cấu hình mọi thứ mà không cần sửa file config bên trong container.

Nhưng WordPress stack dùng image có sẵn, mọi thứ đã được đóng gói. Trong thực tế, bạn sẽ thường cần build một stack tuỳ chỉnh hơn: chọn phiên bản PHP, cài thêm extension, viết config Nginx riêng, deploy code PHP của chính mình. Đó là lúc bạn cần LEMP Stack.
Trong bài này, mình sẽ hướng dẫn bạn dựng một LEMP Stack hoàn chỉnh bằng Docker Compose: Nginx + PHP-FPM + MariaDB: với custom Dockerfile, custom config, sẵn sàng để deploy bất kỳ project PHP nào.
LEMP Stack là gì?
LEMP là viết tắt của 4 thành phần:
- Linux: hệ điều hành (trong Docker, đó là Alpine Linux bên trong container)
- Engine-X (Nginx): web server, reverse proxy
- MariaDB (hoặc MySQL): hệ quản trị cơ sở dữ liệu
- PHP: ngôn ngữ lập trình server-side
Đây là stack phổ biến nhất để chạy các ứng dụng PHP: từ Laravel, CodeIgniter, đến các CMS như WordPress, Joomla, Drupal. Nếu bạn làm web với PHP, gần như chắc chắn bạn sẽ cần LEMP (hoặc LAMP).
LAMP vs LEMP – Khác nhau chỗ nào?
Bạn có thể đã nghe đến LAMP (Linux + Apache + MySQL + PHP). Sự khác biệt chính nằm ở web server:
┌────────────┬──────────────────────┬──────────────────────┐
│ │ LAMP │ LEMP │
├────────────┼──────────────────────┼──────────────────────┤
│ Web Server │ Apache │ Nginx │
│ PHP xử lý │ mod_php (module) │ PHP-FPM (FastCGI) │
│ Cấu hình │ .htaccess + httpd │ nginx.conf │
│ Hiệu năng │ Tốt, dùng nhiều RAM │ Nhẹ hơn, nhanh hơn │
│ Static file│ Chậm hơn │ Rất nhanh │
│ Phổ biến │ Hosting truyền thống│ VPS, cloud, Docker │
└────────────┴──────────────────────┴──────────────────────┘
Tại sao chọn LEMP? Nginx nhẹ hơn Apache đáng kể, xử lý static files cực nhanh, và kiến trúc event-driven giúp nó handle được nhiều concurrent connections hơn với ít tài nguyên hơn. Trong môi trường Docker và VPS, Nginx gần như là lựa chọn mặc định.
Sơ đồ hoạt động của LEMP Stack trong Docker:
┌──────────────────────────────────────────────────────┐
│ Docker Network │
│ (lemp-network) │
│ │
│ Browser Request │
│ ↓ │
│ ┌──────────┐ FastCGI ┌──────────┐ │
│ │ Nginx │───────────────→│ PHP-FPM │ │
│ │ :80 │ (.php files) │ :9000 │ │
│ │ │ │ │ │
│ │ (static │ │ ↓ SQL │ │
│ │ files) │ │ │ │
│ └──────────┘ └──────────┘ │
│ ↑ ↓ │
│ Shared Volume ┌──────────┐ │
│ (./src:/var/www/html) │ MariaDB │ │
│ ↑ │ :3306 │ │
│ └─────────────────────┘ │ │
│ PHP & Nginx cùng │ │
│ mount source code │ │
│ └──────────┘ │
└──────────────────────────────────────────────────────┘
Điểm quan trọng: Nginx và PHP-FPM là 2 container riêng biệt. Nginx nhận request, nếu là file .php thì chuyển sang PHP-FPM qua giao thức FastCGI (port 9000). Cả hai cùng mount chung thư mục source code để Nginx serve static files và PHP-FPM xử lý code PHP.
Tạo cấu trúc project
Tạo thư mục project và các file cần thiết:
mkdir -p ~/lemp-docker/{nginx,php,src}
cd ~/lemp-docker
Cấu trúc project khi hoàn thành sẽ như sau:
lemp-docker/
├── docker-compose.yml # File chính, định nghĩa 3 services
├── .env # Biến môi trường (secrets)
├── nginx/
│ └── default.conf # Config Nginx cho PHP-FPM
├── php/
│ ├── Dockerfile # Custom PHP image + extensions
│ └── php.ini # Tuỳ chỉnh PHP settings
└── src/
└── index.php # Source code PHP của bạn
Mỗi thư mục có vai trò riêng:
nginx/: chứa config Nginx, mount vào container Nginxphp/: chứa Dockerfile và php.ini để build custom PHP imagesrc/: chứa source code PHP, được mount vào cả Nginx và PHP-FPM
Viết file .env cho secrets
Trước khi viết docker-compose.yml, hãy tạo file .env để chứa các thông tin nhạy cảm. Tách secrets ra file riêng giúp bạn dễ quản lý và tránh commit password lên Git.
nano .env
Nội dung file .env:
# MariaDB
MYSQL_ROOT_PASSWORD=rootpass_secret_2024
MYSQL_DATABASE=lemp_db
MYSQL_USER=lemp_user
MYSQL_PASSWORD=lemp_pass_secret_2024
# Nginx
NGINX_PORT=8080
Lưu ý: Trong production, hãy đổi password thành giá trị mạnh hơn. Và luôn thêm .env vào .gitignore để không push secrets lên repository.
echo ".env" >> .gitignore
Custom PHP Dockerfile
Image php:8.3-fpm-alpine trên Docker Hub rất nhẹ nhưng thiếu nhiều extensions cần thiết. Bạn cần tự build image với các extensions phù hợp cho dự án.
nano php/Dockerfile
FROM php:8.3-fpm-alpine
# Cài các package hệ thống cần thiết cho PHP extensions
RUN apk add --no-cache \
freetype-dev \
libjpeg-turbo-dev \
libpng-dev \
libzip-dev \
icu-dev \
oniguruma-dev
# Cấu hình và cài PHP extensions
RUN docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install -j$(nproc) \
pdo_mysql \
mysqli \
gd \
zip \
intl \
mbstring \
opcache
# Copy file php.ini tuỳ chỉnh
COPY php.ini /usr/local/etc/php/conf.d/custom.ini
# Set working directory
WORKDIR /var/www/html
# Expose port 9000 (PHP-FPM default)
EXPOSE 9000
Giải thích từng phần:
- FROM php:8.3-fpm-alpine: base image PHP 8.3 với FPM (FastCGI Process Manager), dựa trên Alpine Linux (siêu nhẹ, chỉ ~50MB)
- apk add: cài các thư viện C cần thiết để compile PHP extensions (freetype cho font trong GD, libjpeg/libpng cho xử lý ảnh, libzip cho ZIP, icu cho internationalization)
- docker-php-ext-configure gd: cấu hình extension GD với hỗ trợ FreeType và JPEG trước khi cài
- docker-php-ext-install: script có sẵn trong PHP Docker image, giúp cài extensions dễ dàng. Flag
-j$(nproc)dùng tất cả CPU cores để compile nhanh hơn - COPY php.ini: copy file cấu hình PHP tuỳ chỉnh vào container
Các extensions đã cài:
┌──────────────┬──────────────────────────────────────────┐
│ Extension │ Dùng để làm gì │
├──────────────┼──────────────────────────────────────────┤
│ pdo_mysql │ Kết nối MySQL/MariaDB qua PDO (chuẩn) │
│ mysqli │ Kết nối MySQL/MariaDB (legacy, WP cần) │
│ gd │ Xử lý ảnh (resize, crop, watermark) │
│ zip │ Đọc/tạo file ZIP │
│ intl │ Internationalization (đa ngôn ngữ) │
│ mbstring │ Xử lý chuỗi multibyte (UTF-8) │
│ opcache │ Cache PHP bytecode, tăng tốc đáng kể │
└──────────────┴──────────────────────────────────────────┘
Custom php.ini
Tạo file php.ini để tuỳ chỉnh các settings PHP mặc định:
nano php/php.ini
; === Upload & POST ===
upload_max_filesize = 64M
post_max_size = 64M
; === Memory ===
memory_limit = 256M
; === Execution ===
max_execution_time = 300
max_input_time = 300
max_input_vars = 3000
; === Error Handling ===
display_errors = Off
log_errors = On
error_log = /var/log/php/error.log
; === OPcache ===
opcache.enable = 1
opcache.memory_consumption = 128
opcache.max_accelerated_files = 10000
opcache.revalidate_freq = 60
; === Timezone ===
date.timezone = Asia/Ho_Chi_Minh
Một số settings quan trọng:
- upload_max_filesize & post_max_size: mặc định PHP chỉ cho upload 2MB, tăng lên 64MB cho thoải mái
- memory_limit: RAM tối đa cho mỗi PHP process, 256M đủ cho hầu hết ứng dụng
- opcache: cache bytecode giúp PHP không cần compile lại code mỗi request, tăng tốc 2-3 lần
- display_errors = Off: tắt hiển thị lỗi trên web (bảo mật), chỉ ghi vào log
Custom Nginx config
Nginx cần được cấu hình để chuyển request .php sang PHP-FPM. Tạo file config:
nano nginx/default.conf
server {
listen 80;
server_name localhost;
root /var/www/html;
index index.php index.html index.htm;
# Logging
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
# Xử lý request chính
location / {
try_files $uri $uri/ /index.php?$query_string;
}
# Chuyển file .php sang PHP-FPM
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
# "php" là tên service trong docker-compose.yml
fastcgi_pass php:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
# Timeout cho các script chạy lâu
fastcgi_read_timeout 300;
}
# Cache static files
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
expires 30d;
add_header Cache-Control "public, immutable";
access_log off;
}
# Chặn truy cập file ẩn (.env, .git, .htaccess)
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
}
Giải thích các phần quan trọng:
try_files – Xử lý URL
try_files $uri $uri/ /index.php?$query_string;
Dòng này nói với Nginx: “Thử tìm file theo URL → nếu không có, thử thư mục → nếu vẫn không có, chuyển tất cả về index.php“. Đây là cách hoạt động của hầu hết PHP framework (Laravel, WordPress, CodeIgniter), mọi request đều đi qua một file entry point duy nhất.
fastcgi_pass – Kết nối PHP-FPM
fastcgi_pass php:9000;
Đây là dòng quan trọng nhất, nó chuyển request PHP sang container PHP-FPM. php ở đây chính là tên service trong docker-compose.yml, Docker network tự động resolve tên này thành IP của container. Port 9000 là port mặc định của PHP-FPM.
Static file caching
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
expires 30d;
add_header Cache-Control "public, immutable";
access_log off;
}
Block này cấu hình cache cho static files (ảnh, CSS, JS, fonts). Browser sẽ cache các file này trong 30 ngày, giảm request đến server đáng kể. access_log off tắt log cho static files để giảm I/O.
Chặn file ẩn
location ~ /\. {
deny all;
}
Block bảo mật, chặn truy cập vào tất cả file bắt đầu bằng dấu chấm: .env, .git, .htaccess. Nếu không có dòng này, ai cũng có thể đọc file .env chứa password database của bạn qua trình duyệt.
Viết docker-compose.yml
Bây giờ đến phần chính, file docker-compose.yml kết nối tất cả lại với nhau:
nano docker-compose.yml
services:
# === Nginx Web Server ===
nginx:
image: nginx:alpine
container_name: lemp-nginx
ports:
- "${NGINX_PORT:-8080}:80"
volumes:
- ./src:/var/www/html # Source code
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf # Nginx config
depends_on:
- php
restart: unless-stopped
networks:
- lemp-network
# === PHP-FPM ===
php:
build:
context: ./php
dockerfile: Dockerfile
container_name: lemp-php
volumes:
- ./src:/var/www/html # Cùng source code với Nginx
depends_on:
- mariadb
restart: unless-stopped
networks:
- lemp-network
# === MariaDB Database ===
mariadb:
image: mariadb:11
container_name: lemp-mariadb
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
volumes:
- mariadb_data:/var/lib/mysql # Persistent data
restart: unless-stopped
networks:
- lemp-network
# === Volumes ===
volumes:
mariadb_data:
# === Network ===
networks:
lemp-network:
driver: bridge
Phân tích từng service:
Service nginx
- image: nginx:alpine: dùng image Nginx nhẹ nhất (~40MB)
- ports: map port 8080 trên host vào port 80 trong container. Giá trị lấy từ file
.env, mặc định 8080 nếu không set - volumes: mount 2 thứ: source code (shared với PHP) và config Nginx
- depends_on: php: đảm bảo PHP-FPM khởi động trước Nginx
Service php
- build: build image từ Dockerfile trong thư mục
php/, không dùng image có sẵn - volumes: mount cùng thư mục
src/với Nginx. Đây là điểm mấu chốt: Nginx serve static files, PHP-FPM xử lý file.php, cả hai cùng đọc từ một thư mục - depends_on: mariadb: đảm bảo database sẵn sàng trước khi PHP chạy
- Không expose port: PHP-FPM chỉ giao tiếp nội bộ qua port 9000 trong Docker network, không cần expose ra ngoài
Service mariadb
- image: mariadb:11: MariaDB phiên bản 11, tương thích hoàn toàn với MySQL
- environment: tất cả giá trị lấy từ file
.envqua cú pháp${VARIABLE} - volumes: mariadb_data: named volume, giữ dữ liệu database khi container restart hoặc recreate
- Không expose port: tương tự PHP, database chỉ truy cập nội bộ. Nếu cần kết nối từ host (dùng MySQL Workbench chẳng hạn), thêm
ports: - "3306:3306"
Deploy và test
Mọi thứ đã sẵn sàng. Bắt đầu deploy!
Bước 1: Tạo file test
Tạo file index.php đơn giản trong thư mục src/:
cat > src/index.php << 'EOF'
<!DOCTYPE html>
<html>
<head>
<title>LEMP Stack Docker</title>
<style>
body { font-family: Arial, sans-serif; max-width: 800px; margin: 50px auto; }
.success { color: #27ae60; }
.error { color: #e74c3c; }
code { background: #f4f4f4; padding: 2px 8px; border-radius: 4px; }
</style>
</head>
<body>
<h1>🚀 LEMP Stack đang chạy!</h1>
<p>PHP Version: <strong><?php echo PHP_VERSION; ?></strong></p>
<p>Server: <strong><?php echo $_SERVER['SERVER_SOFTWARE'] ?? 'Nginx + PHP-FPM'; ?></strong></p>
<h2>Test kết nối MariaDB</h2>
<?php
$host = 'mariadb'; // Tên service trong docker-compose
$db = getenv('MYSQL_DATABASE') ?: 'lemp_db';
$user = getenv('MYSQL_USER') ?: 'lemp_user';
$pass = getenv('MYSQL_PASSWORD') ?: 'lemp_pass_secret_2024';
try {
$pdo = new PDO("mysql:host=$host;dbname=$db", $user, $pass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$version = $pdo->query('SELECT VERSION()')->fetchColumn();
echo "<p class='success'>✅ Kết nối thành công! MariaDB version: <strong>$version</strong></p>";
} catch (PDOException $e) {
echo "<p class='error'>❌ Lỗi kết nối: " . $e->getMessage() . "</p>";
}
?>
<h2>PHP Extensions đã cài</h2>
<ul>
<?php
$check = ['pdo_mysql', 'mysqli', 'gd', 'zip', 'intl', 'mbstring', 'Zend OPcache'];
foreach ($check as $ext) {
$loaded = extension_loaded($ext) ? '✅' : '❌';
echo "<li>$loaded $ext</li>";
}
?>
</ul>
</body>
</html>
EOF
Bước 2: Build và khởi động
# Build PHP image và khởi động tất cả services
docker compose up -d --build
Lần đầu chạy sẽ mất vài phút vì Docker cần build PHP image (compile extensions). Output sẽ trông như thế này:
[+] Building 45.2s (8/8) FINISHED
=> [php internal] load build definition from Dockerfile
=> [php 2/4] RUN apk add --no-cache freetype-dev libjpeg-turbo-dev ...
=> [php 3/4] RUN docker-php-ext-configure gd --with-freetype --with-jpeg ...
=> [php 4/4] COPY php.ini /usr/local/etc/php/conf.d/custom.ini
=> exporting to image
[+] Running 4/4
✔ Network lemp-docker_lemp-network Created
✔ Container lemp-mariadb Started
✔ Container lemp-php Started
✔ Container lemp-nginx Started
Bước 3: Kiểm tra trạng thái
docker compose ps
Kết quả mong đợi, cả 3 container đều Up:
NAME IMAGE STATUS PORTS
lemp-mariadb mariadb:11 Up 30 seconds 3306/tcp
lemp-nginx nginx:alpine Up 29 seconds 0.0.0.0:8080->80/tcp
lemp-php lemp-docker-php Up 30 seconds 9000/tcp
Bước 4: Test trên trình duyệt
Mở trình duyệt và truy cập:
http://your-server-ip:8080
Bạn sẽ thấy trang test hiển thị:
- PHP version: 8.3.x
- Kết nối MariaDB thành công với version number
- Tất cả extensions đều có dấu ✅
Nếu muốn xem đầy đủ thông tin PHP, tạo thêm file phpinfo():
echo "<?php phpinfo();" > src/info.php
Truy cập http://your-server-ip:8080/info.php để xem toàn bộ cấu hình PHP. Nhớ xoá file này sau khi test xong: phpinfo tiết lộ rất nhiều thông tin nhạy cảm về server.
# Xoá sau khi test xong
rm src/info.php
Bước 5: Test kết nối database từ CLI
Ngoài test qua web, bạn có thể exec vào container MariaDB để kiểm tra trực tiếp:
# Exec vào container MariaDB
docker exec -it lemp-mariadb mariadb -u lemp_user -p
# Nhập password: lemp_pass_secret_2024
# Sau khi vào MySQL prompt:
SHOW DATABASES;
USE lemp_db;
SHOW TABLES;
Nếu thấy database lemp_db trong danh sách, mọi thứ đã hoạt động đúng.
Quản lý và tuỳ chỉnh LEMP Stack
LEMP Stack bằng Docker Compose linh hoạt hơn cài trực tiếp trên server rất nhiều. Dưới đây là các tuỳ chỉnh phổ biến:
Thêm PHP extension
Cần thêm extension Redis chẳng hạn? Sửa file php/Dockerfile:
# Thêm PECL extension (Redis, Xdebug, etc.)
RUN apk add --no-cache $PHPIZE_DEPS \
&& pecl install redis \
&& docker-php-ext-enable redis
Sau đó rebuild image:
docker compose up -d --build php
Docker sẽ rebuild chỉ service PHP, các service khác giữ nguyên. Cực kỳ tiện so với việc phải cài extension trên server thật rồi restart PHP-FPM.
Đổi phiên bản PHP
Muốn chuyển từ PHP 8.3 sang 8.2 (hoặc 8.1)? Chỉ cần sửa dòng đầu tiên trong php/Dockerfile:
# Đổi từ PHP 8.3 sang 8.2
FROM php:8.2-fpm-alpine
Rồi rebuild:
docker compose up -d --build php
Chỉ mất 1 phút, không cần uninstall PHP cũ, không sợ conflict version. Đây là một trong những lợi thế lớn nhất của Docker, chuyển đổi version cực kỳ dễ dàng.
Thêm virtual host cho nhiều domain
Muốn chạy nhiều website trên cùng một LEMP Stack? Tạo thêm file config Nginx cho từng domain:
mkdir -p nginx/conf.d
Tạo file nginx/conf.d/site1.conf:
server {
listen 80;
server_name site1.example.com;
root /var/www/site1;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass php:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
Cập nhật docker-compose.yml để mount thêm thư mục config và source code:
nginx:
volumes:
- ./src:/var/www/html
- ./sites/site1:/var/www/site1 # Source code site 1
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
- ./nginx/conf.d:/etc/nginx/conf.d/extra # Thêm config files
php:
volumes:
- ./src:/var/www/html
- ./sites/site1:/var/www/site1 # PHP cũng cần mount
Nhớ mount source code vào cả Nginx và PHP-FPM. Nếu thiếu một bên, bạn sẽ gặp lỗi “File not found” hoặc Nginx trả về 404.
Các lệnh quản lý thường dùng
# Xem logs của từng service
docker compose logs nginx
docker compose logs php
docker compose logs mariadb
# Xem logs realtime
docker compose logs -f
# Restart một service (sau khi sửa config)
docker compose restart nginx
# Vào shell container PHP (để debug, test)
docker exec -it lemp-php sh
# Kiểm tra PHP extensions đã cài
docker exec lemp-php php -m
# Backup database
docker exec lemp-mariadb mariadb-dump -u root -p lemp_db > backup.sql
# Restore database
docker exec -i lemp-mariadb mariadb -u root -p lemp_db < backup.sql
# Dừng toàn bộ stack
docker compose down
# Dừng và xoá cả database volume (CẨN THẬN!)
docker compose down -v
📚 Serie Docker từ A đến Z
- Bài 1: Docker là gì? Tại sao nên dùng Docker trên VPS
- Bài 2: Cài đặt Docker và Docker Compose trên VPS Ubuntu
- Bài 3: Làm quen với Docker – Các lệnh cơ bản cần biết
- Bài 4: Docker Image & Dockerfile – Tự tạo Image riêng
- Bài 5: Docker Volume & Network – Quản lý dữ liệu và mạng
- Bài 6: Docker Compose là gì? Cài đặt và cú pháp cơ bản
- Bài 7: Deploy WordPress + MySQL + phpMyAdmin bằng Docker Compose
- Bài 8: Deploy LEMP Stack (Nginx + PHP-FPM + MariaDB) bằng Docker Compose (đang đọc)
- Bài 9: Biến môi trường & file .env trong Docker Compose
- Bài 10: Reverse Proxy với Nginx Proxy Manager + SSL tự động
- Bài 11: Deploy ứng dụng Node.js / Python với Docker Compose
- Bài 12: Backup & Restore dữ liệu Docker Volume
- Bài 13: Monitoring Docker với Portainer, Uptime Kuma và cAdvisor
- Bài 14: Docker Logging – Quản lý log hiệu quả
- Bài 15: Bảo mật Docker trên VPS
- Bài 16: CI/CD đơn giản – Auto deploy với Webhook + Docker Compose
- Bài 17: Docker Compose trong thực tế – Tổng hợp project mẫu
Tổng kết
Trong bài này, bạn đã:
- Hiểu LEMP Stack là gì và tại sao nó phổ biến hơn LAMP trong môi trường Docker/VPS
- Viết custom Dockerfile cho PHP-FPM với các extensions cần thiết (pdo_mysql, gd, zip, opcache...)
- Cấu hình Nginx để proxy request PHP qua FastCGI, cache static files, và bảo vệ file nhạy cảm
- Dùng file .env để quản lý secrets tách biệt khỏi docker-compose.yml
- Deploy và test thành công: PHP hoạt động, database kết nối OK, extensions đầy đủ
- Biết cách tuỳ chỉnh: thêm extension, đổi PHP version, thêm virtual host cho nhiều domain
So với Bài 7 (WordPress stack dùng image có sẵn), bài này đã nâng cấp đáng kể: bạn tự build image, tự viết config, kiểm soát hoàn toàn từng thành phần. Đây mới là cách dùng Docker trong production thực tế.
Bạn có thể nhận ra rằng trong suốt bài này, mình đã hardcode nhiều giá trị trong file .env và truyền vào container qua environment. Nhưng khi project phức tạp hơn : nhiều environment (dev/staging/production), nhiều service, nhiều secrets , cách quản lý environment variables sẽ cần bài bản hơn.
Trong Bài 9, mình sẽ đi sâu vào Environment Variables & .env trong Docker: các cách truyền biến môi trường, thứ tự ưu tiên, quản lý secrets an toàn, và pattern cho multi-environment deployment. Hẹn gặp bạn ở bài tiếp theo! 🚀
👈 Bài trước: Deploy WordPress + MySQL + phpMyAdmin bằng Docker Compose
👉 Bài tiếp: Biến môi trường & file .env trong Docker Compose
Có thể bạn cần xem thêm
- Docker Compose là gì? Cài đặt và cú pháp cơ bản
- Deploy WordPress + MySQL + phpMyAdmin bằng Docker Compose
- Deploy ứng dụng Node.js / Python với Docker Compose
- Biến môi trường & file .env trong Docker Compose
- CI/CD đơn giản – Auto deploy với Webhook + Docker Compose
- Docker Compose trong thực tế – Tổng hợp project mẫu
Về tác giả
Thạch Phạm
Đồng sáng lập và Giám đốc điều hành của AZDIGI. Có hơn 15 năm kinh nghiệm trong phổ biến kiến thức liên quan đến WordPress tại thachpham.com, phát triển website và phát triển hệ thống.