+4

Thực chiến Laravel với Docker Compose

Trong bài viết trước, ta đã làm quen với Docker Compose và Traefik. Bây giờ là lúc “thực chiến” — triển khai một dự án Laravel đậm chất PHP trong container, kết nối với MySQL, routing qua Traefik. 🐳

📦 Mục tiêu của phần này

  • Khởi tạo một dự án Laravel mới (hoặc dùng dự án có sẵn).
  • Cấu hình docker-compose.yml gồm Laravel, MySQL.
  • Xem thành quả.

🛠️ 1. Khởi tạo dự án Laravel

  • Để khởi tạo dự án bạn có thể tham khảo tại đây hoặc chạy:
cd laravel-docker
composer create-project laravel/laravel laravel-docker-demo
// mở vscode
code .
  • Thêm file docker-compose.yml cùng thư mục với dự án Laravel.

Kết quả:

laravel-docker/
├── laravel-docker-demo/
├── docker-compose.yml

🐳 2. File docker-compose.yml

Để code ra được 1 file docker-compose.yml chạy được thì chúng ta cần có:

  • traefik: Đảm nhận việc điều phối routing tới các app laravel của chúng ta.
  • laravel: Cấu hình của app.
  • mysql: Cấu hình database.

Bắt đầu thôi nào 🏃

2.1 traefik

services:
    traefik:
      image: traefik:v2.11
      container_name: traefik
      command:
        - "--api.dashboard=true"
        - "--providers.docker=true"
        - "--entrypoints.web.address=:80"
      ports:
        - "80:80"
      volumes:
        - /var/run/docker.sock:/var/run/docker.sockk
  • version: "3.8" – Chọn phiên bản cấu trúc Compose.
  • image: Phiên bản traefik mà chúng ta sử dụng.
  • command: cấu hình nhanh cho Traefik
    • --api.dashboard=true: cho phép truy cập traefik dashboard
    • --providers.docker=true: Cho phép Traefik nhìn thấy các container Docker khác (để tự định tuyến).
    • --entrypoints.web.address=:80: Mở cổng 80 – như cổng chính ngôi nhà vậy 🏠️
  • volumes: Traefik cần đọc docker.sock để "nghe ngóng" xem container vừa lên sóng, container vừa tắt.

2.2 laravel app

laravel:
  image: php:8.2-fpm
  working_dir: /var/www
  volumes:
    - ./laravel-docker-demo:/var/www
  labels:
    - "traefik.enable=true"
    - "traefik.http.routers.laravel.rule=Host(`localhost`)"
    - "traefik.http.routers.laravel.entrypoints=web"
  depends_on:
    - mysql
  command: >
    sh -c "
      apt-get update &&
      apt-get install -y zip unzip git curl libonig-dev libxml2-dev libzip-dev &&
      docker-php-ext-install pdo pdo_mysql mbstring zip exif pcntl &&
      curl -sS https://getcomposer.org/installer | php &&
      mv composer.phar /usr/local/bin/composer &&
      composer install &&
      php-fpm
    "
  • image: Dùng image php:8.2-fpm.
  • working_dir: thư mục làm việc chính.
  • volumes: Gắn thư mục code vào trong container.
  • labels: Cấu hình để Traefik thấy được app của chúng ta - "à, thằng Laravel này khi gọi localhost thì đưa tao điều hướng tới nó nhé"
  • depends_on: đợi mysql chạy xong mới bắt đầu
  • command:
    • Cài Linux packages
    • Bật PHP extensions
    • Cài Composer
    • Cài Laravel dependencies
    • Và cuối cùng... chạy php-fpm để phục vụ web

2.3 mysql

mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: laravel
      MYSQL_USER: laravel
      MYSQL_PASSWORD: secret
    volumes:
      - mysql_data:/var/lib/mysql
      
volumes:
  mysql_data:
  • image: Dùng luôn bản chính chủ MySQL 8.0.
  • environment: Mấy dòng khai sinh ra database, user và password. Laravel sẽ dùng thông tin này để kết nối.
  • volumes: Gắn ổ cứng riêng cho database. Có restart hay build lại thì data vẫn còn.
  • Cuối cùng volumes: mysql_data: giống như ổ đĩa ngoài cho MySQL, giúp lưu dữ liệu của container khi bị dừng hoặc xóa.

🚀 Khởi chạy dự án

Cấu hình Laravel

Trong file .env trong thư mục laravel-docker-demo. Sửa các giá trị sau:

DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=laravel
DB_PASSWORD=secret

Thêm config để app của chúng ta có thể connect tới database mysql

Khởi chạy và test

docker-compose up --build

Sau khi dịch xong, mở browser truy cập: http://localhost

Nếu bạn bạn thấy kết quả như trên thì xin chúc mừng. Bạn đã tự build thành công dự án đầu tiên của mình với docker rồi 👏👏👏

dưới đây là file docker-compose.yml hoàn chỉnh:

services:
  traefik:
    image: traefik:v2.11
    command:
      - "--api.dashboard=true"
      - "--providers.docker=true"
      - "--entrypoints.web.address=:80"
    ports:
      - "80:80"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

  laravel:
    image: php:8.2-fpm
    working_dir: /var/www
    volumes:
      - ./myapp:/var/www
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.laravel.rule=Host(`localhost`)"
      - "traefik.http.routers.laravel.entrypoints=web"
    depends_on:
      - mysql
    command: >
      sh -c "
        apt-get update &&
        apt-get install -y zip unzip git curl libonig-dev libxml2-dev libzip-dev &&
        docker-php-ext-install pdo pdo_mysql mbstring zip exif pcntl &&
        curl -sS https://getcomposer.org/installer | php &&
        mv composer.phar /usr/local/bin/composer &&
        composer install &&
        php-fpm
      "

  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: laravel
      MYSQL_USER: laravel
      MYSQL_PASSWORD: secret
    volumes:
      - mysql_data:/var/lib/mysql

volumes:
  mysql_data:

Note: trên thực tế thì sau khi khởi chạy docker xong thì mọi người sẽ sh vào trong container và chạy command để giảm gánh nặng khi khởi tạo. Ở đây mình thêm command chạy vì là demo nên khi vào thực tế mọi người nên bỏ command và chạy bằng tay nhé 😅

✅Kết luận

Việc dùng Docker Compose để triển khai Laravel giúss chúng ta:

  • Loại bỏ rắc rối khi cài môi trường PHP.
  • Triển khai nhênh, gọn, dễ scale.
  • Kết hợp Traefik giúp routing linh hoạt và sau này dễ dàng thêm HTTPS, staging...

Tài liệu tham khảo:


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.