在当今快速发展的软件开发环境中,容器化技术已成为部署应用程序的标准方式。Docker 作为容器化技术的代表,为 PHP 应用提供了轻量级、可移植且一致的运行环境。本文将详细介绍使用 Docker 部署 PHP 应用的完整流程,帮助开发者实现高效的应用部署与管理。

问题背景与适用场景

PHP 作为广泛使用的服务器端脚本语言,在 Web 开发领域占据重要地位。然而,传统的 PHP 应用部署常面临环境不一致、依赖管理复杂、扩展安装繁琐等问题。Docker 容器化技术可以有效解决这些问题,特别适用于以下场景:

  1. 多环境一致性需求(开发、测试、生产环境)
  2. 微服务架构中的 PHP 组件部署
  3. CI/CD 流程中的自动化部署
  4. 需要快速扩展的应用服务

Docker 部署原理

Docker 通过容器化技术将应用及其依赖打包到一个可移植的容器中。PHP 应用容器化的核心原理包括:

  1. 镜像分层:Docker 镜像采用分层结构,基础镜像(如 PHP 官方镜像)包含运行环境,应用层镜像添加特定依赖和应用代码
  2. 资源隔离:容器通过 Linux 内核特性(如命名空间和控制组)实现进程、文件系统、网络等资源的隔离
  3. 一致性保证:无论在何种环境下运行,容器都能提供相同的运行环境,确保应用行为一致

操作步骤

1. 环境准备

首先确保系统已安装 Docker 和 Docker Compose:

# 安装 Docker(以 Ubuntu 为例)
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

# 安装 Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

2. 创建 Dockerfile

在项目根目录创建 Dockerfile,定义 PHP 应用的构建过程:

# 使用官方 PHP 镜像作为基础
FROM php:7.4-fpm

# 安装系统依赖和 PHP 扩展
RUN apt-get update && apt-get install -y \
    libzip-dev \
    unzip \
    && docker-php-ext-install pdo_mysql zip

# 设置工作目录
WORKDIR /var/www/html

# 复制依赖文件并安装 Composer
COPY composer.json composer.lock ./
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
RUN composer install --no-dev --optimize-autoloader

# 复制应用代码
COPY . .

# 设置正确的文件权限
RUN chown -R www-data:www-data /var/www/html

# 暴露 PHP-FPM 端口
EXPOSE 9000

3. 配置 docker-compose.yml

创建 docker-compose.yml 文件,定义服务、网络和数据卷:

version: '3.8'

services:
  app:
    build: .
    container_name: php-app
    restart: unless-stopped
    working_dir: /var/www/html
    volumes:
      - .:/var/www/html
      - ./php.ini:/usr/local/etc/php/php.ini
    networks:
      - app-network

  webserver:
    image: nginx:alpine
    container_name: nginx-webserver
    restart: unless-stopped
    ports:
      - "8080:80"
    volumes:
      - .:/var/www/html
      - ./nginx.conf:/etc/nginx/nginx.conf
      - ./sites.conf:/etc/nginx/conf.d/sites.conf
    networks:
      - app-network

networks:
  app-network:
    driver: bridge

4. 构建和运行容器

使用 Docker Compose 构建并启动服务:

# 构建镜像并启动容器
docker-compose up -d --build

# 查看容器状态
docker-compose ps

# 查看容器日志
docker-compose logs -f

5. 部署优化

为了优化部署流程,可以添加以下脚本:

# deploy.sh
#!/bin/bash

echo "停止现有容器..."
docker-compose down

echo "拉取最新代码..."
git pull origin main

echo "重新构建并启动容器..."
docker-compose up -d --build

echo "清理无用的镜像..."
docker image prune -f

给脚本添加执行权限:

chmod +x deploy.sh

示例代码

简单的 PHP 应用示例

创建一个简单的 PHP 应用文件 index.php:

<?php
// 数据库连接配置
$dbHost = getenv('DB_HOST') ?: 'localhost';
$dbName = getenv('DB_NAME') ?: 'test_db';
$dbUser = getenv('DB_USER') ?: 'root';
$dbPass = getenv('DB_PASS') ?: '';

try {
    $pdo = new PDO("mysql:host=$dbHost;dbname=$dbName", $dbUser, $dbPass);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    
    // 查询示例
    $stmt = $pdo->query("SELECT * FROM users LIMIT 5");
    $users = $stmt->fetchAll(PDO::FETCH_ASSOC);
    
    echo "<h1>PHP Docker 部署示例</h1>";
    echo "<h2>用户列表</h2>";
    echo "<ul>";
    
    foreach ($users as $user) {
        echo "<li>" . htmlspecialchars($user['name']) . "</li>";
    }
    
    echo "</ul>";
    
} catch (PDOException $e) {
    echo "数据库连接失败: " . $e->getMessage();
}
?>

Nginx 配置示例

创建 sites.conf 文件:

server {
    listen 80;
    server_name localhost;
    root /var/www/html;
    index index.php index.html;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        fastcgi_pass app:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}

常见问题与注意事项

1. 常见问题

问题:容器启动失败

  • 检查 Dockerfile 语法是否正确
  • 确认端口是否被占用
  • 查看 docker-compose 日志:docker-compose logs

问题:PHP 扩展安装失败

  • 确认基础镜像版本是否支持所需扩展
  • 检查系统依赖是否安装完整
  • 尝试手动安装扩展:docker-php-ext-install <extension>

问题:文件权限问题

  • 确保容器内用户权限正确:RUN chown -R www-data:www-data /var/www/html
  • 考虑使用 volumes 时权限映射问题

2. 注意事项

  1. 安全性:避免在 Dockerfile 中硬编码敏感信息,使用环境变量或 Docker Secrets
  2. 镜像大小:选择合适的基础镜像,使用多阶段构建减小镜像体积
  3. 数据持久化:使用 Docker volumes 或 bind mounts 持久化重要数据
  4. 资源限制:在 docker-compose.yml 中设置适当的资源限制

3. 排错思路

  1. 逐步排查:先确保基础容器能启动,再添加应用层
  2. 检查日志:使用 docker logs <container_id> 查看详细错误信息
  3. 本地测试:先在本地环境测试应用逻辑,再部署到容器
  4. 网络问题:确认容器间网络配置正确,服务发现正常

总结

Docker 部署 PHP 应用提供了环境一致性、简化依赖管理和快速扩展的优势。通过合理配置 Dockerfile 和 docker-compose.yml,可以实现高效的应用部署流程。在实际应用中,还需注意安全性、性能优化和问题排查,以确保容器化部署的稳定性和可靠性。

通过本文介绍的完整流程,开发者可以轻松将 PHP 应用容器化,并在不同环境中实现一致部署,为现代 Web 应用开发提供有力支持。

主楼