1. Sport Site
Sport
  • Sport Site
    • Tài liệu triển khai dự án Sport Site
    • Tài liệu triển khai dự án Landing Page
    • Tài liệu triển khai dự án Newslooks
  • Sport API
    • Tài liệu triển khai dự án KSport API
    • Tài liệu triển khai dự án WSport API
    • Tài liệu triển khai dự án WSport API Game
  • Sport DB
    • Tài liệu triển khai dự án Sport DB
  • Sport Admin
    • Tài liệu triển khai dự án Sport Admin
  1. Sport Site

Tài liệu triển khai dự án Sport Site

Tài Liệu Triển Khai Dự Án Sport — Laravel trên Docker#

    
Triển Khai Laravel Production với Docker trên AWS
    

🔥 Tổng Quan#

Tài liệu này mô tả quy trình build và triển khai cho các dự án Sport (dựa trên Laravel) chạy trên Docker trong môi trường production trên AWS. Mỗi dự án Sport đều tuân theo cùng một kiến trúc:
PHP-FPM Service (fpm): Xử lý các request PHP, chứa vendor dependencies và source code Laravel.
Nginx Web Service (web): Phục vụ nội dung tĩnh từ thư mục public của Laravel và chuyển tiếp (proxy) các request PHP đến service FPM.

Hạ Tầng Chính#

Thành phầnDịch vụ AWSMục đích
Container ImagesAWS ECRRegistry Docker image riêng tư
Cơ sở dữ liệuAWS RDSMySQL được quản lý cho Laravel
CacheElastiCacheRedis cache cho session, queue, và cache driver
Lưu trữ chia sẻAWS EFSLưu trữ NFS cho uploads WordPress news

Các Dự Án Sport Sử Dụng Kiến Trúc Này#

Dự ánECR RepositoryNhánh sourceĐường dẫn WP News
thscoresports/thscore-live-prodthscore-v2.0prediction
bongdakosports/bongdako-live-prodbongdako-live-developnhan-dinh-bong-da
bongdalusports/bongdalu-live-prodbongdalu-nowgoaltin-tuc
bongdapisports/bongdapi-live-prodbongdapi-livetin-moi

📖 Tài Liệu Tham Khảo#

Bạn có thể xem tài liệu tại docs.docker.com và các câu hỏi thường gặp tại đây.

🚧 Cấu Trúc Dự Án#

Dự Án Sport (ví dụ: thscore)
├─ .gitignore
├─ .gitmodules                              # Tham chiếu submodule đến source Laravel
├─ README.md                                # Tài liệu triển khai
├─ build/
│  ├─ Dockerfile-base-live.production       # Base image: Cài đặt FPM + Nginx (user, supervisor, php config)
│  ├─ Dockerfile-live.production            # Production image: composer install, npm build, multi-stage
│  ├─ Dockerfile-live.development           # Development image: build đầy đủ
│  ├─ conf/
│  │  ├─ nginx/
│  │  │  ├─ common/
│  │  │  │  └─ nginx.conf                   # Cấu hình nginx global
│  │  │  └─ template/
│  │  │     └─ default-live.conf.template.example  # Template server block (sử dụng $FPM_HOST)
│  │  ├─ robots.txt.example                 # Template robots.txt mặc định
│  │  └─ supervisor/
│  │     ├─ common/
│  │     │  ├─ entry_point.sh               # Script khởi chạy Supervisor
│  │     │  └─ supervisord.conf             # Cấu hình Supervisor global
│  │     └─ php-fpm.conf                    # Supervisor program: php-fpm
│  ├─ data/
│  │  └─ php/
│  │     ├─ php.ini                         # Cấu hình PHP tùy chỉnh
│  │     └─ php-fpm.conf.example            # Template cấu hình PHP-FPM pool
│  └─ source/                               # ⚡ Git submodule — Source code Laravel
│     ├─ .env                               # Biến môi trường ứng dụng (load khi runtime)
│     ├─ composer.json
│     ├─ package.json
│     └─ ...
├─ docs/
│  ├─ swap-memory/README.md
│  └─ vi-VN/README.md                      # Tài liệu tiếng Việt (file này)
├─ media/                                   # Media assets cho tài liệu
├─ .env-live.production                     # Biến Docker Compose cho production
├─ .env-live.development                    # Biến Docker Compose cho development
├─ docker-compose-live.yml.production       # File Compose cho triển khai production
└─ docker-compose-live.yml.development      # File Compose cho triển khai development

🏗️ Tổng Quan Kiến Trúc#

Pipeline Build Docker Multi-Stage#

Quá trình build production sử dụng Dockerfile multi-stage để tạo image tối ưu:
┌──────────────────────────────────────────────────────────────────────────┐
│                   PIPELINE BUILD MULTI-STAGE                             │
│                                                                          │
│  ┌─────────────┐    ┌─────────────┐    ┌─────────────┐                   │
│  │ GIAI ĐOẠN 1 │    │ GIAI ĐOẠN 2 │    │ GIAI ĐOẠN 3 │                   │
│  │   vendor    │───▶│  node_base  │───▶│    build    │                   │
│  │             │    │             │    │             │                   │
│  │ • composer  │    │ • Copy từ   │    │ • npm run   │                   │
│  │   install   │    │   vendor    │    │   build     │                   │
│  │ • PHP deps  │    │ • npm       │    │ • Assets    │                   │
│  │             │    │   install   │    │   đã build  │                   │
│  └─────────────┘    └─────────────┘    └──────┬──────┘                   │
│                                               │                          │
│                          ┌────────────────────┼────────────────────┐     │
│                          │                    │                    │     │
│                          ▼                    ▼                    │     │
│                   ┌─────────────┐      ┌─────────────┐             │     │
│                   │ GIAI ĐOẠN 4 │      │ GIAI ĐOẠN 5 │             │     │
│                   │ fpm_server  │      │ web_server  │             │     │
│                   │             │      │             │             │     │
│                   │ • Toàn bộ   │      │ • Nginx     │             │     │
│                   │   Laravel   │      │ • Chỉ thư   │             │     │
│                   │ • PHP-FPM   │      │   mục       │             │     │
│                   │ • Vendor    │      │   public/   │             │     │
│                   │ • Supervisor│      │ • Static    │             │     │
│                   │             │      │   assets    │             │     │
│                   └─────────────┘      └─────────────┘             │     │
│                          │                    │                    │     │
│                          ▼                    ▼                    │     │
│                   ┌─────────────┐      ┌─────────────┐             │     │
│                   │  ECR Push   │      │  ECR Push   │             │     │
│                   │  :fpm-latest│      │  :web-latest│             │     │
│                   └─────────────┘      └─────────────┘             │     │
└──────────────────────────────────────────────────────────────────────────┘

Kiến Trúc Runtime Production#

┌─────────────────────────────────────────────────────────────────────────────────────┐
│                          MÔI TRƯỜNG PRODUCTION AWS                                  │
│                                                                                     │
│  ┌──────────────────────────────────────┐  ┌──────────────────────────────────────┐ │
│  │          Docker Host                 │  │            DỊCH VỤ AWS               │ │
│  │                                      │  │                                      │ │
│  │  ┌────────────────────────────────┐  │  │  ┌──────────────────────────────┐    │ │
│  │  │     web (Nginx Container)      │  │  │  │       AWS RDS (MySQL)        │    │ │
│  │  │                                │  │  │  │  • CSDL Production           │    │ │
│  │  │  • Phục vụ static assets       │  │  │  │  • Được AWS quản lý          │    │ │
│  │  │  • Proxy PHP → FPM:9000        │  │  │  └──────────────────────────────┘    │ │
│  │  │  • Port 80 expose              │  │  │                                      │ │
│  │  │  • Nginx templates             │  │  │  ┌──────────────────────────────┐    │ │
│  │  │  • News uploads (RO) ◄─────────┼──┼──┼──│  AWS ElastiCache (Redis)     │    │ │
│  │  │                                │  │  │  │  • Lưu trữ Session           │    │ │
│  │  └───────────┬────────────────────┘  │  │  │  • Cache Driver              │    │ │
│  │              │ fastcgi_pass          │  │  │  • Queue Connection          │    │ │
│  │              ▼                       │  │  └──────────────────────────────┘    │ │
│  │  ┌────────────────────────────────┐  │  │                                      │ │
│  │  │    fpm (PHP-FPM Container)     │  │  │  ┌──────────────────────────────┐    │ │
│  │  │                                │──┼──┼──▶       AWS ECR                │    │ │
│  │  │  • Laravel source + vendor     │  │  │  │  • :fpm-latest               │    │ │
│  │  │  • PHP-FPM port 9000           │  │  │  │  • :web-latest               │    │ │
│  │  │  • Supervisor quản lý          │  │  │  │  • :fpm-base-latest          │    │ │
│  │  │  • Health check bật            │  │  │  │  • :web-base-latest          │    │ │
│  │  │  • .env mount (RO)             │  │  │  └──────────────────────────────┘    │ │
│  │  │  • News uploads (RW) ◄─────────┼──┼──┼──┐                                   │ │
│  │  │                                │  │  │  │  ┌──────────────────────────────┐ │ │
│  │  └────────────────────────────────┘  │  │  └──│    AWS EFS (NFS)             │ │ │
│  │                                      │  │     │  • :/uploads-wp              │ │ │
│  └──────────────────────────────────────┘  │     │  • Lưu trữ media WordPress   │ │ │
│                                            │     │  • Chia sẻ giữa instances    │ │ │
│  Networks: prod-network, backend-network   │     └──────────────────────────────┘ │ │
│                                            │                                      │ │
└────────────────────────────────────────────┴────────────────────────────────────────┘

📦 Yêu Cầu Tiên Quyết#

Công cụ cần thiết#

Công cụPhiên bản tối thiểuMục đích
Docker≥ 24.0.0Build và chạy container
Docker Compose≥ 2.20.0Điều phối nhiều container
AWS CLI≥ 2.0Xác thực và push lên AWS ECR
Git≥ 2.30Quản lý source code & submodules

Yêu cầu AWS#

Tài khoản AWS đã cấu hình quyền truy cập ECR
ECR Repository đã tạo cho dự án (ví dụ: sports/thscore-live-prod)
AWS RDS instance MySQL đã provisioned và có thể truy cập
AWS ElastiCache Redis cluster đã provisioned và có thể truy cập
AWS EFS file system đã provisioned cho lưu trữ chia sẻ uploads WordPress news
IAM credentials với quyền ecr:GetAuthorizationToken, ecr:BatchCheckLayerAvailability, ecr:PutImage

Hạ tầng (Server Production)#

Tài nguyênTối thiểuKhuyến nghị
CPU4 Core8 Core
RAM4 GB8 GB
SWAP1 GB2 GB
Ổ cứng40 GB65 GB
OSUbuntu ≥ 22.04Ubuntu ≥ 24.04
Lưu ý: Nếu server chưa có swap partition mặc định, bạn có thể khởi tạo swap để đảm bảo hiệu năng ứng dụng khi tải cao.

❄️ Cấu Hình#

Hiểu Về Các File Môi Trường#

Mỗi dự án Sport có hai lớp cấu hình môi trường:

1. Biến Môi Trường Docker Compose (.env-live.production)#

Kiểm soát tên service, image tag, và networking cho Docker. File này được docker-compose sử dụng để thay thế biến.

2. Biến Môi Trường Laravel (build/source/.env)#

Kiểm soát ứng dụng Laravel, kết nối đến AWS RDS và ElastiCache. File này được mount read-only vào container FPM khi chạy.
⚠️ Quan trọng: File .env trong build/source/.env được load khi runtime qua volume mount. Nó KHÔNG được nhúng vào Docker image, đảm bảo các thông tin nhạy cảm luôn được bảo mật.

Cấu Hình Nginx#

Template Nginx (build/conf/nginx/template/default-live.conf.template.example) sử dụng biến môi trường $FPM_HOST để tự động resolve PHP-FPM backend:
Để tùy chỉnh cho dự án cụ thể:

Cấu Hình PHP#

php.ini (build/data/php/php.ini):
php-fpm.conf (build/data/php/php-fpm.conf):
Để tùy chỉnh cấu hình FPM pool:

Robots.txt#

🔨 Build & Đẩy Image Lên AWS ECR#

Bước 1: Chuẩn bị Source Code#

1.1 Clone repository triển khai và khởi tạo submodule#

1.2 Chuyển sang nhánh đúng cho submodule#

Bước 2: Build Base Image (Lần đầu hoặc khi base thay đổi)#

Base image chứa setup hệ thống (user, supervisor, PHP extensions, Nginx) hiếm khi thay đổi. Build riêng để tận dụng Docker layer caching.

Bước 3: Build Production Image#

Bước 4: Xác thực và Push lên AWS ECR#

🚀 Triển Khai Lên Production#

Bước 1: Tạo Docker Networks#

Tạo các external network cần thiết (thiết lập một lần):

Bước 2: Tạo Docker Volumes#

Tạo các external volume cho dữ liệu persistent (một lần cho mỗi dự án):

2.1 Volume tiêu chuẩn (local driver)#

2.2 Volume WordPress News (NFS-backed qua AWS EFS)#

Mỗi dự án Sport có tích hợp site WordPress cho tin tức/bài viết. Hình ảnh được upload sẽ lưu trên AWS EFS và mount dưới dạng Docker volume NFS-backed. Điều này cho phép chia sẻ truy cập media files giữa nhiều container instances.
Tạo volume news với tùy chọn NFS trỏ tới AWS EFS file system:
Ví dụ (cho thscore):
Bạn có thể kiểm tra cấu hình volume bằng lệnh:
Kết quả mong đợi:
[
    {
        "Driver": "local",
        "Name": "<dự-án>_news_storage-data",
        "Options": {
            "device": ":/uploads-wp",
            "o": "addr=<efs-id>.efs.<region>.amazonaws.com,nfsvers=4.1,rw",
            "type": "nfs"
        }
    }
]
Volume này sau đó được mount vào cả hai container để phục vụ thư mục uploads của WordPress:
Dự ánTên VolumeĐường dẫn mount trong Container (FPM — RW, Web — RO)
thscorethscore_news_storage-data/opt/apps/laravel/public/prediction/wp-content/uploads
bongdakobongdako_news_storage-data/opt/apps/laravel/public/nhan-dinh-bong-da/wp-content/uploads
bongdalubongdalu_news_storage-data/opt/apps/laravel/public/news/wp-content/uploads
bongdapibongdapi_news_storage-data/opt/apps/laravel/public/tin-moi/wp-content/uploads
Lưu ý: Container FPM mount volume news ở chế độ read-write (để WordPress upload hình ảnh), trong khi container Web mount ở chế độ read-only (Nginx chỉ phục vụ file tĩnh). Bản thân các file source WordPress được mount từ build/source/public/<đường-dẫn-news> vào cùng thư mục cha.

Bước 3: Cấu hình File Môi Trường#

3.1 Copy và cấu hình biến Docker Compose#

Kiểm tra image tag trỏ đúng ECR repository:

3.2 Cấu hình biến môi trường Laravel#

Cấu hình cơ sở dữ liệu cần thiết (AWS RDS):
Cấu hình cache cần thiết (AWS ElastiCache):

3.3 Copy các template cấu hình#

Bước 4: Copy File Docker Compose#

Bước 5: Pull Image và Triển Khai#

Bước 6: Kiểm Tra Triển Khai#

Bước 7: Chạy Lệnh Laravel Sau Triển Khai#

Chạy các lệnh này bên trong container FPM sau lần triển khai đầu tiên:

🔄 Cập Nhật & Triển Khai Lại#

Cho các lần triển khai tiếp theo (cập nhật code):

📋 Tham Chiếu Services Docker Compose#

Services Production (docker-compose-live.yml.production)#

ServiceImage SourcePortMục đích
<dự-án>-live.fpmECR :fpm-latest9000Xử lý PHP-FPM, ứng dụng Laravel
<dự-án>-live.webECR :web-latest80Nginx reverse proxy, static assets

Volume Mounts#

Đường dẫn mount (Container)NguồnChế độMục đích
/opt/apps/laravel/storageDocker Volume (local)RWLaravel storage (logs, cache)
/opt/apps/laravel/bootstrapDocker Volume (local)RWLaravel bootstrap cache
/opt/apps/laravel/.envbuild/source/.envROBiến môi trường ứng dụng
/usr/local/etc/php/conf.d/custom.inibuild/data/php/php.iniROOverride cấu hình PHP
/usr/local/etc/php-fpm.d/www.confbuild/data/php/php-fpm.confROCấu hình PHP-FPM pool
/opt/apps/laravel/public/robots.txtbuild/conf/robots.txtROFile robots.txt
/etc/nginx/templates/default.conf.templatebuild/conf/nginx/template/...ROTemplate Nginx server block
/opt/apps/laravel/public/<news-path>build/source/public/<news-path>RW/ROSource WordPress news
/opt/apps/laravel/public/<news-path>/wp-content/uploadsDocker Volume (NFS qua AWS EFS)RW/ROMedia WordPress đã upload (EFS-backed)

Health Check#

Service FPM bao gồm health check sử dụng php-fpm-healthcheck:
Service Web phụ thuộc vào health của FPM:

🛡️ Các Thực Hành Bảo Mật#

1.
.env không bao giờ được nhúng vào image — được mount dưới dạng read-only volume khi runtime
2.
Container non-root — cả FPM và Nginx đều chạy dưới user không có đặc quyền (UID: 1200)
3.
Supervisor quản lý — PHP-FPM được quản lý bởi Supervisor với khả năng auto-restart
4.
Chặn file .ht và file ẩn — Cấu hình Nginx chặn truy cập vào .htaccess và file ẩn
5.
cgi.fix_pathinfo = 0 — Ngăn chặn tấn công PHP path info injection
6.
Cloudflare real IP — Nginx giải mã đúng IP thật của client phía sau Cloudflare và ALB
7.
Health checks — Health của FPM được giám sát, Web service chỉ khởi động sau khi FPM healthy

🔧 Xử Lý Sự Cố#

Container không khởi động được#

Health check PHP-FPM thất bại#

Lỗi kết nối cơ sở dữ liệu#

Lỗi kết nối cache#

📚 Tài Liệu Liên Quan#

Tài liệu Docker
Triển khai Laravel
Hướng dẫn AWS ECR
AWS RDS cho MySQL
AWS ElastiCache cho Redis
Cài đặt Swap Memory
Modified at 2026-03-21 16:58:21
Next
Tài liệu triển khai dự án Landing Page
Built with