PHP项目怎么容器化部署

wen PHP项目 3

本文目录导读:

PHP项目怎么容器化部署

  1. 基础Docker部署
  2. Docker Compose配置
  3. Nginx配置
  4. PHP配置优化
  5. 进阶优化
  6. CI/CD集成
  7. 安全最佳实践
  8. 监控和日志

我来详细介绍PHP项目的容器化部署方法,包括基础实践和进阶优化。

基础Docker部署

1 最简Dockerfile

# 使用官方PHP镜像
FROM php:8.2-apache
# 安装扩展
RUN docker-php-ext-install pdo_mysql mysqli
# 复制项目文件
COPY . /var/www/html/
# 设置工作目录
WORKDIR /var/www/html
# 配置Apache
RUN a2enmod rewrite
EXPOSE 80

2 生产环境优化版

# 多阶段构建
FROM composer:2 AS composer
WORKDIR /app
COPY composer.json composer.lock ./
RUN composer install --no-dev --no-scripts --prefer-dist
# 运行时镜像
FROM php:8.2-fpm-alpine
# 安装系统依赖
RUN apk add --no-cache \
    nginx \
    curl \
    icu-dev \
    libzip-dev \
    oniguruma-dev \
    libxml2-dev \
    freetype-dev \
    libjpeg-turbo-dev \
    libpng-dev
# 安装PHP扩展
RUN docker-php-ext-configure gd --with-freetype --with-jpeg \
    && docker-php-ext-install \
        pdo_mysql \
        mysqli \
        gd \
        zip \
        intl \
        mbstring \
        exif \
        pcntl \
        bcmath \
        opcache
# 复制项目代码
COPY --from=composer /app/vendor /app/vendor
COPY . /app
# 配置目录权限
RUN chown -R www-data:www-data /app \
    && chmod -R 755 /app/storage /app/bootstrap
WORKDIR /app
EXPOSE 9000
CMD ["php-fpm"]

Docker Compose配置

version: '3.8'
services:
  # PHP应用
  app:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: php_app
    restart: unless-stopped
    working_dir: /var/www/html
    volumes:
      - ./src:/var/www/html
      - ./docker/php/php.ini:/usr/local/etc/php/conf.d/php.ini:ro
    networks:
      - app-network
    depends_on:
      - db
      - redis
  # Nginx服务
  nginx:
    image: nginx:alpine
    container_name: nginx_server
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./src:/var/www/html
      - ./docker/nginx/conf.d:/etc/nginx/conf.d:ro
      - ./docker/nginx/ssl:/etc/nginx/ssl:ro
    networks:
      - app-network
    depends_on:
      - app
  # MySQL数据库
  db:
    image: mysql:8.0
    container_name: mysql_db
    restart: unless-stopped
    environment:
      MYSQL_DATABASE: ${DB_DATABASE}
      MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
      MYSQL_USER: ${DB_USERNAME}
      MYSQL_PASSWORD: ${DB_PASSWORD}
    volumes:
      - db_data:/var/lib/mysql
      - ./docker/mysql/init:/docker-entrypoint-initdb.d
    ports:
      - "3306:3306"
    networks:
      - app-network
  # Redis缓存
  redis:
    image: redis:7-alpine
    container_name: redis_cache
    restart: unless-stopped
    ports:
      - "6379:6379"
    volumes:
      - redis_data:/data
    networks:
      - app-network
networks:
  app-network:
    driver: bridge
volumes:
  db_data:
  redis_data:

Nginx配置

1 Nginx配置文件 (docker/nginx/conf.d/default.conf)

server {
    listen 80;
    server_name localhost;
    root /var/www/html/public;
    index index.php index.html;
    # 请求头配置
    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Content-Type-Options "nosniff";
    # 日志配置
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;
    # 静态文件缓存
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";
    }
    # PHP请求处理
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
    location ~ \.php$ {
        fastcgi_pass app:9000;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param HTTP_PROXY "";
        fastcgi_read_timeout 120s;
    }
    # 拒绝访问隐藏文件
    location ~ /\.(?!well-known) {
        deny all;
    }
}

PHP配置优化

1 php.ini配置 (docker/php/php.ini)

; 内存限制
memory_limit = 256M
max_execution_time = 120
max_input_time = 60
post_max_size = 50M
upload_max_filesize = 50M
; 错误报告
display_errors = Off
log_errors = On
error_log = /var/log/php/error.log
error_reporting = E_ALL
; 时区设置
date.timezone = Asia/Shanghai
; 会话配置
session.save_handler = files
session.gc_maxlifetime = 1440
session.cookie_httponly = 1
session.use_strict_mode = 1
; OpCache优化
opcache.enable = 1
opcache.memory_consumption = 128
opcache.interned_strings_buffer = 8
opcache.max_accelerated_files = 4000
opcache.revalidate_freq = 60
opcache.fast_shutdown = 1

进阶优化

1 健康检查

# docker-compose.yml 中添加
app:
  healthcheck:
    test: ["CMD", "curl", "-f", "http://localhost:9000/ping"]
    interval: 30s
    timeout: 3s
    retries: 3
    start_period: 40s
db:
  healthcheck:
    test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
    interval: 30s
    timeout: 5s
    retries: 5

2 日志轮转

# 使用logrotate
logging:
  driver: "json-file"
  options:
    max-size: "10m"
    max-file: "3"

3 自动部署脚本

#!/bin/bash
# deploy.sh
set -e
# 环境变量
ENV=${1:-production}
COMPOSE_FILE="docker-compose.${ENV}.yml"
echo "部署环境: ${ENV}"
# 构建新镜像
docker compose -f ${COMPOSE_FILE} build --no-cache
# 停止旧容器
docker compose -f ${COMPOSE_FILE} down
# 启动新容器
docker compose -f ${COMPOSE_FILE} up -d
# 清理旧镜像
docker image prune -f
# 等待服务启动
sleep 10
# 执行数据库迁移
docker compose -f ${COMPOSE_FILE} exec app php artisan migrate --force
# 缓存清理
docker compose -f ${COMPOSE_FILE} exec app php artisan config:cache
docker compose -f ${COMPOSE_FILE} exec app php artisan route:cache
# 检查状态
docker compose -f ${COMPOSE_FILE} ps
echo "部署完成!"

CI/CD集成

1 GitHub Actions示例

name: CI/CD Pipeline
on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: 设置环境
      uses: actions/setup-php@v2
      with:
        php-version: '8.2'
        extensions: mbstring, intl, pdo_mysql
    - name: 安装依赖
      run: composer install --no-dev --prefer-dist --no-interaction
    - name: 构建Docker镜像
      run: |
        docker build -t ${{ secrets.DOCKER_REGISTRY }}/php-app:${{ github.sha }} .
        docker tag ${{ secrets.DOCKER_REGISTRY }}/php-app:${{ github.sha }} ${{ secrets.DOCKER_REGISTRY }}/php-app:latest
    - name: 推送镜像
      run: |
        docker push ${{ secrets.DOCKER_REGISTRY }}/php-app:${{ github.sha }}
        docker push ${{ secrets.DOCKER_REGISTRY }}/php-app:latest
    - name: 部署到服务器
      uses: appleboy/ssh-action@master
      with:
        host: ${{ secrets.SERVER_HOST }}
        username: ${{ secrets.SERVER_USERNAME }}
        key: ${{ secrets.SSH_PRIVATE_KEY }}
        script: |
          cd /var/www/php-app
          docker-compose pull
          docker-compose up -d

安全最佳实践

1 Dockerfile安全建议

# 使用非root用户
RUN useradd -m -u 1000 app
# 限制资源使用
RUN ulimit -n 65536
# 最小化攻击面
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
# 设置只读文件系统
VOLUME ["/app/storage", "/app/bootstrap/cache"]

2 网络隔离

# 使用不同的网络分段
networks:
  frontend:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/16
  backend:
    driver: bridge
    internal: true

监控和日志

# 集成Prometheus
prometheus:
  image: prom/prometheus
  volumes:
    - ./prometheus.yml:/etc/prometheus/prometheus.yml
  ports:
    - "9090:9090"

这个完整方案涵盖了PHP项目容器化的所有核心要素,建议从小型项目开始实践,逐步增加功能,记住定期更新镜像和依赖,保持系统安全。

抱歉,评论功能暂时关闭!