# 使用 Docker 搭建 Laravel 集群指南

本指南将介绍如何使用 Docker 和 Docker Compose 搭建一个 Laravel 应用集群，包含 Web 服务器、MySQL 数据库、Redis 缓存和负载均衡。

（通过GitHub和DockerHub的集成实现自动化构建流程。包括设置GitHub组织、配置DockerHub访问权限、创建仓库及使用webhook触发构建过程。）

## 1. 准备工作

确保已安装：
- Docker (>= 20.10)
- Docker Compose (>= 2.0)
- Git

## 2. 项目结构

```
laravel-cluster/
├── docker/
│   ├── nginx/
│   │   ├── Dockerfile
│   │   └── default.conf
│   ├── php/
│   │   └── Dockerfile
│   └── haproxy/
│       └── haproxy.cfg
├── src/ (Laravel 项目)
├── docker-compose.yml
└── .env
```

## 3. 配置 Docker 环境

### docker-compose.yml

```yaml
version: '3.8'

services:
  # MySQL 数据库
  mysql:
    image: mysql:8.0
    container_name: mysql
    environment:
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
      MYSQL_DATABASE: ${DB_DATABASE}
      MYSQL_USER: ${DB_USERNAME}
      MYSQL_PASSWORD: ${DB_PASSWORD}
    volumes:
      - mysql_data:/var/lib/mysql
    networks:
      - laravel-network

  # Redis 缓存
  redis:
    image: redis:alpine
    container_name: redis
    ports:
      - "6379:6379"
    networks:
      - laravel-network

  # PHP-FPM 服务 (多个实例)
  php1:
    build:
      context: ./docker/php
    container_name: php1
    volumes:
      - ./src:/var/www/html
    environment:
      - DB_HOST=mysql
      - REDIS_HOST=redis
    networks:
      - laravel-network
    depends_on:
      - mysql
      - redis

  php2:
    build:
      context: ./docker/php
    container_name: php2
    volumes:
      - ./src:/var/www/html
    environment:
      - DB_HOST=mysql
      - REDIS_HOST=redis
    networks:
      - laravel-network
    depends_on:
      - mysql
      - redis

  # Nginx Web 服务器 (多个实例)
  nginx1:
    build:
      context: ./docker/nginx
    container_name: nginx1
    ports:
      - "8081:80"
    volumes:
      - ./src:/var/www/html
    depends_on:
      - php1
    networks:
      - laravel-network

  nginx2:
    build:
      context: ./docker/nginx
    container_name: nginx2
    ports:
      - "8082:80"
    volumes:
      - ./src:/var/www/html
    depends_on:
      - php2
    networks:
      - laravel-network

  # HAProxy 负载均衡
  haproxy:
    image: haproxy:2.4
    container_name: haproxy
    ports:
      - "80:80"
      - "8404:8404" # 统计页面
    volumes:
      - ./docker/haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg
    depends_on:
      - nginx1
      - nginx2
    networks:
      - laravel-network

volumes:
  mysql_data:

networks:
  laravel-network:
    driver: bridge
```

### docker/php/Dockerfile

```dockerfile
FROM php:8.1-fpm

# 安装依赖
RUN apt-get update && apt-get install -y \
    libzip-dev \
    zip \
    unzip \
    libpq-dev \
    libonig-dev \
    libxml2-dev

# 安装 PHP 扩展
RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath zip

# 安装 Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

# 设置工作目录
WORKDIR /var/www/html
```

### docker/nginx/default.conf

```nginx
server {
    listen 80;
    index index.php index.html;
    server_name localhost;
    error_log  /var/log/nginx/error.log;
    access_log /var/log/nginx/access.log;
    root /var/www/html/public;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass php1:9000; # 修改为对应的 PHP 容器名
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
}
```

### docker/haproxy/haproxy.cfg

```cfg
global
    stats socket /var/run/api.sock user haproxy group haproxy mode 660 level admin expose-fd listeners
    log stdout format raw local0 info

defaults
    mode http
    timeout connect 5000ms
    timeout client 50000ms
    timeout server 50000ms

frontend http_front
    bind *:80
    stats uri /stats
    default_backend http_back

backend http_back
    balance roundrobin
    server nginx1 nginx1:80 check
    server nginx2 nginx2:80 check

listen stats
    bind *:8404
    stats enable
    stats uri /
    stats refresh 5s
```

## 4. 部署步骤

1. 克隆 Laravel 项目到 `src` 目录：
   ```bash
   git clone https://github.com/laravel/laravel.git src
   ```

2. 创建 `.env` 文件：
   ```bash
   cp src/.env.example src/.env
   ```

3. 修改 `src/.env` 数据库配置：
   ```env
   DB_CONNECTION=mysql
   DB_HOST=mysql
   DB_PORT=3306
   DB_DATABASE=laravel
   DB_USERNAME=laravel
   DB_PASSWORD=secret
   ```

4. 创建项目 `.env` 文件：
   ```bash
   cat > .env <<EOF
   DB_ROOT_PASSWORD=root
   DB_DATABASE=laravel
   DB_USERNAME=laravel
   DB_PASSWORD=secret
   EOF
   ```

5. 构建并启动容器：
   ```bash
   docker-compose up -d --build
   ```

6. 安装 Laravel 依赖：
   ```bash
   docker-compose exec php1 composer install
   ```

7. 生成应用密钥：
   ```bash
   docker-compose exec php1 php artisan key:generate
   ```

8. 运行数据库迁移：
   ```bash
   docker-compose exec php1 php artisan migrate
   ```

## 5. 访问应用

- 应用: http://localhost
- HAProxy 统计页面: http://localhost:8404/stats

## 6. 扩展集群

要增加更多 PHP 和 Nginx 实例：

1. 在 `docker-compose.yml` 中添加 `php3` 和 `nginx3` 服务
2. 更新 HAProxy 配置添加新服务器
3. 重新部署：
   ```bash
   docker-compose up -d --scale php=3 --scale nginx=3
   ```

## 7. 监控与管理

- 查看容器日志：
  ```bash
  docker-compose logs -f
  ```

- 进入容器：
  ```bash
  docker-compose exec php1 bash
  ```

- 停止集群：
  ```bash
  docker-compose down
  ```

这个配置提供了基本的 Laravel 集群环境，您可以根据需要添加更多服务如队列 worker、Horizon 监控等。