Skip to content

云计算平台安装

随着云计算的普及,越来越多的 PHP 应用部署在云端环境中。各大云服务商都提供了便捷的 PHP 运行环境部署方案,而 Docker 容器化技术更是让 PHP 应用的部署和运维变得标准化、可移植。本节将介绍主流云计算平台上的 PHP 安装方法,重点讲解 Docker 容器化部署方案。

前置知识

  • 了解基本的云计算概念(实例、镜像、容器、负载均衡)
  • 熟悉 Docker 基础操作(docker run、docker build、Dockerfile)
  • 具备基本的 Linux 命令行操作能力

基础概念

云计算平台选择

不同的云平台提供了不同程度的 PHP 集成支持:

云平台PHP 部署方式特点
Docker容器化部署最灵活,跨平台,推荐方案
AWSEC2 / Elastic Beanstalk / Lambda企业级,全球覆盖
阿里云ECS / SAE / 函数计算国内访问速度快
腾讯云CVM / 轻量应用服务器 / SCF国内生态完善

Docker 基础概念

Docker 通过容器技术将应用及其依赖打包为一个可移植的单元:

  • 镜像(Image):只读模板,包含运行应用所需的所有文件
  • 容器(Container):镜像的运行实例
  • Dockerfile:定义镜像构建步骤的脚本文件
  • Compose:定义多容器应用编排的工具

Docker 安装 PHP

官方 PHP 镜像

PHP 官方提供了预构建的 Docker 镜像,位于 Docker Hub:

bash
# 拉取 PHP 8.2 CLI 镜像(基础版)
docker pull php:8.2-cli

# 拉取带 FPM 的镜像(用于 Web 应用)
docker pull php:8.2-fpm

# 拉取带 Apache 的镜像
docker pull php:8.2-apache

# 查看可用的镜像标签
# https://hub.docker.com/_/php/tags

镜像标签说明

PHP 官方镜像标签格式为 php:<version>-<variant>

  • php:8.2-cli — 命令行版本
  • php:8.2-fpm — FastCGI 进程管理器版本
  • php:8.2-apache — 预装 Apache 的版本
  • php:8.2-fpm-alpine — 基于 Alpine Linux 的精简版本(体积更小)
  • php:8.2-zts — 线程安全版本

快速启动 PHP 容器

bash
# 运行 CLI 容器
docker run --rm -it php:8.2-cli php -v

# 运行交互式 Shell
docker run --rm -it php:8.2-cli bash

# 挂载本地目录运行 PHP 文件
docker run --rm -it -v $(pwd):/app -w /app php:8.2-cli php script.php

# 运行内置 Web 服务器
docker run --rm -it -p 8080:8080 -v $(pwd):/app -w /app php:8.2-cli \
    php -S 0.0.0.0:8080

# 运行 FPM 容器(配合 Nginx 使用)
docker run --rm -d -p 9000:9000 -v $(pwd):/app php:8.2-fpm

Dockerfile 最佳实践

以下是一个生产级的 PHP 应用 Dockerfile 示例:

dockerfile
# ============================================
# 第一阶段:安装依赖
# ============================================
FROM composer:2.6 AS deps

WORKDIR /app

# 复制 Composer 文件(利用 Docker 缓存层)
COPY composer.json composer.lock ./

# 安装生产依赖(不含开发依赖)
RUN composer install --no-dev --prefer-dist --no-progress --no-scripts \
    && composer clear-cache

# ============================================
# 第二阶段:构建应用镜像
# ============================================
FROM php:8.2-fpm-alpine AS production

# 安装系统依赖和 PHP 扩展
RUN apk add --no-cache \
    libzip-dev \
    libjpeg-turbo-dev \
    libpng-dev \
    freetype-dev \
    libwebp-dev \
    icu-dev \
    oniguruma-dev \
    linux-headers \
    $PHPIZE_DEPS

# 编译安装 PHP 扩展
RUN docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp \
    && docker-php-ext-install -j$(nproc) \
        pdo_mysql \
        mysqli \
        gd \
        zip \
        intl \
        mbstring \
        opcache \
        pcntl \
    && pecl install redis-6.0.2 \
    && docker-php-ext-enable redis \
    && apk del $PHPIZE_DEPS

# 配置 PHP
RUN cp /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini

# 优化配置
RUN { \
    echo 'memory_limit = 256M'; \
    echo 'upload_max_filesize = 64M'; \
    echo 'post_max_size = 128M'; \
    echo 'date.timezone = Asia/Shanghai'; \
    } > /usr/local/etc/php/conf.d/custom.ini

# OPcache 配置(JIT 编译)
RUN { \
    echo 'opcache.enable = 1'; \
    echo 'opcache.enable_cli = 1'; \
    echo 'opcache.memory_consumption = 256'; \
    echo 'opcache.max_accelerated_files = 20000'; \
    echo 'opcache.revalidate_freq = 0'; \
    echo 'opcache.validate_timestamps = 0'; \
    echo 'opcache.jit = 1255'; \
    echo 'opcache.jit_buffer_size = 64M'; \
    } > /usr/local/etc/php/conf.d/opcache.ini

# 创建应用用户
RUN addgroup -g 1000 appuser \
    && adduser -u 1000 -G appuser -s /bin/sh -D appuser

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

# 从 deps 阶段复制 vendor 目录
COPY --from=deps --chown=appuser:appuser /app/vendor ./vendor

# 复制应用代码
COPY --chown=appuser:appuser . .

# 切换到非 root 用户
USER appuser

# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
    CMD php-fpm -t 2>/dev/null || exit 1

EXPOSE 9000

CMD ["php-fpm"]

Docker Compose 多容器编排

一个完整的 PHP Web 应用通常需要多个容器协同工作:

yaml
# docker-compose.yml
version: '3.8'

services:
  nginx:
    image: nginx:1.25-alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./:/var/www/html
      - ./docker/nginx/conf.d:/etc/nginx/conf.d
      - ./docker/nginx/ssl:/etc/nginx/ssl
    depends_on:
      php:
        condition: service_healthy
    restart: unless-stopped
    networks:
      - app-network

  php:
    build:
      context: .
      dockerfile: Dockerfile
      target: production
    volumes:
      - ./:/var/www/html
    depends_on:
      mysql:
        condition: service_healthy
      redis:
        condition: service_started
    restart: unless-stopped
    networks:
      - app-network

  mysql:
    image: mysql:8.0
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD:-secret}
      MYSQL_DATABASE: ${DB_DATABASE:-app_db}
      MYSQL_USER: ${DB_USERNAME:-app_user}
      MYSQL_PASSWORD: ${DB_PASSWORD:-app_secret}
    volumes:
      - mysql_data:/var/lib/mysql
      - ./docker/mysql/conf.d:/etc/mysql/conf.d
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 3s
      retries: 5
    restart: unless-stopped
    networks:
      - app-network

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    volumes:
      - redis_data:/data
    command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD:-redis_secret}
    restart: unless-stopped
    networks:
      - app-network

volumes:
  mysql_data:
    driver: local
  redis_data:
    driver: local

networks:
  app-network:
    driver: bridge
nginx
# docker/nginx/conf.d/default.conf
upstream php-fpm {
    server php:9000;
}

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

    charset utf-8;

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

    location ~ \.php$ {
        fastcgi_pass php-fpm;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
        fastcgi_buffer_size 128k;
        fastcgi_buffers 4 256k;
        fastcgi_busy_buffers_size 256k;
        fastcgi_read_timeout 300;
    }

    location ~ /\.ht {
        deny all;
    }

    # 静态资源缓存
    location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff2?)$ {
        expires 30d;
        access_log off;
        add_header Cache-Control "public, immutable";
    }
}

AWS 安装部署

EC2 实例安装

在 AWS EC2 上安装 PHP 与在普通 Linux 服务器上安装相同:

bash
# 连接到 EC2 实例后
ssh -i your-key.pem ec2-user@your-instance-ip

# Amazon Linux 2023
sudo dnf update -y
sudo dnf install -y php php-cli php-fpm php-mysqlnd php-pdo \
    php-gd php-mbstring php-xml php-curl php-zip php-intl \
    php-opcache php-pecl-redis5

sudo systemctl enable php-fpm
sudo systemctl start php-fpm

# Ubuntu(在 EC2 上使用 Ubuntu AMI)
sudo apt update
sudo apt install -y software-properties-common
sudo add-apt-repository ppa:ondrej/php -y
sudo apt update
sudo apt install -y php8.2-fpm php8.2-cli php8.2-common \
    php8.2-mysql php8.2-mbstring php8.2-xml php8.2-curl \
    php8.2-zip php8.2-gd php8.2-intl php8.2-opcache

Elastic Beanstalk 部署

AWS Elastic Beanstalk (EB) 支持一键部署 PHP 应用:

bash
# 安装 EB CLI
pip install awsebcli

# 初始化 EB 应用
eb init -p "PHP 8.2 running on 64bit Amazon Linux 2023" my-app

# 创建环境
eb create production --tier webserver-standard

# 部署应用
eb deploy

# 查看状态
eb status

Elastic Beanstalk 的 PHP 平台支持以下配置方式:

  • 在项目根目录放置 .ebextensions/ 目录中的配置文件
  • 使用 composer.json 安装依赖
  • 支持自定义 Nginx 配置

AWS Lambda(Serverless)

PHP 也可以通过 Lambda 运行,使用 Bref 框架:

bash
# 安装 Bref
composer require bref/bref

# 创建 serverless.yml
# 定义 Lambda 函数
yaml
# serverless.yml
service: php-app

provider:
  name: aws
  region: ap-southeast-1
  runtime: provided.al2023

functions:
  api:
    handler: index.php
    description: 'PHP HTTP API'
    layers:
      - ${bref:layer.php-82-fpm}
    events:
      - httpApi: '*'

阿里云安装部署

ECS 实例安装

bash
# 连接到阿里云 ECS 实例
ssh root@your-instance-ip

# CentOS / Alibaba Cloud Linux
sudo yum install -y epel-release
sudo rpm -ivh https://rpms.remirepo.net/enterprise/remi-release-7.rpm
sudo yum-config-manager --enable remi-php82
sudo yum install -y php php-fpm php-cli php-mysqlnd php-mbstring \
    php-xml php-curl php-zip php-gd php-intl php-opcache php-pecl-redis5

sudo systemctl enable php-fpm nginx
sudo systemctl start php-fpm nginx

# Ubuntu(阿里云 Ubuntu AMI)
sudo apt update
sudo apt install -y software-properties-common
sudo add-apt-repository ppa:ondrej/php -y
sudo apt update
sudo apt install -y php8.2-fpm php8.2-cli php8.2-common \
    php8.2-mysql php8.2-mbstring php8.2-xml php8.2-curl \
    php8.2-zip php8.2-gd php8.2-intl php8.2-opcache

SAE(Serverless 应用引擎)

阿里云 SAE 支持直接部署 PHP 应用容器镜像:

bash
# 构建 Docker 镜像
docker build -t registry.cn-hangzhou.aliyuncs.com/your-namespace/php-app:latest .

# 推送到阿里云容器镜像服务
docker login --username=your-username registry.cn-hangzhou.aliyuncs.com
docker push registry.cn-hangzhou.aliyuncs.com/your-namespace/php-app:latest

# 在 SAE 控制台创建应用,选择推送的镜像

腾讯云安装部署

CVM 安装

腾讯云 CVM(云服务器)的 PHP 安装方式与标准 Linux 安装相同:

bash
# 连接到 CVM 实例
ssh ubuntu@your-instance-ip

# 标准安装流程
sudo apt update
sudo apt install -y software-properties-common
sudo add-apt-repository ppa:ondrej/php -y
sudo apt update
sudo apt install -y php8.2-fpm php8.2-cli php8.2-common \
    php8.2-mysql php8.2-mbstring php8.2-xml php8.2-curl \
    php8.2-zip php8.2-gd php8.2-intl php8.2-opcache

轻量应用服务器

腾讯云轻量应用服务器提供 LAMP/LEMP 应用镜像,可一键创建已配置好 PHP 的环境:

  1. 登录腾讯云控制台
  2. 选择"轻量应用服务器" -> "创建服务器"
  3. 在"应用镜像"中选择 LAMP 或 LEMP
  4. 选择 PHP 版本(支持 8.1/8.2)
  5. 创建完成后即可使用

Dockerfile 高级示例

多阶段构建 + 开发/生产分离

dockerfile
# ============================================
# 开发环境镜像
# ============================================
FROM php:8.2-fpm-alpine AS development

# 安装所有扩展(含开发工具)
RUN apk add --no-cache \
    libzip-dev libjpeg-turbo-dev libpng-dev freetype-dev \
    libwebp-dev icu-dev oniguruma-dev linux-headers \
    $PHPIZE_DEPS git npm

RUN docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp \
    && docker-php-ext-install -j$(nproc) \
        pdo_mysql mysqli gd zip intl mbstring opcache pcntl \
    && pecl install xdebug redis-6.0.2 \
    && docker-php-ext-enable xdebug redis

# 开发环境配置
RUN { \
    echo 'xdebug.mode = debug,develop'; \
    echo 'xdebug.start_with_request = yes'; \
    echo 'xdebug.client_host = host.docker.internal'; \
    echo 'xdebug.client_port = 9003'; \
    echo 'xdebug.discover_client_host = true'; \
    } > /usr/local/etc/php/conf.d/xdebug.ini

WORKDIR /var/www/html

EXPOSE 9000

CMD ["php-fpm"]

# ============================================
# 生产环境镜像
# ============================================
FROM php:8.2-fpm-alpine AS production

# 生产环境不安装开发工具
RUN apk add --no-cache \
    libzip-dev libjpeg-turbo-dev libpng-dev freetype-dev \
    libwebp-dev icu-dev oniguruma-dev linux-headers \
    $PHPIZE_DEPS

RUN docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp \
    && docker-php-ext-install -j$(nproc) \
        pdo_mysql mysqli gd zip intl mbstring opcache pcntl \
    && pecl install redis-6.0.2 \
    && docker-php-ext-enable redis \
    && apk del $PHPIZE_DEPS

# 生产环境 PHP 配置
RUN cp /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini \
    && { \
    echo 'opcache.enable = 1'; \
    echo 'opcache.jit = 1255'; \
    echo 'opcache.jit_buffer_size = 128M'; \
    echo 'opcache.validate_timestamps = 0'; \
    } > /usr/local/etc/php/conf.d/opcache.ini

WORKDIR /var/www/html

EXPOSE 9000

CMD ["php-fpm"]
yaml
# docker-compose.yml(区分环境)
version: '3.8'

services:
  php:
    build:
      context: .
      target: ${APP_ENV:-production}  # 通过变量切换开发/生产
    volumes:
      - ./:/var/www/html
    environment:
      APP_ENV: ${APP_ENV:-production}
bash
# 构建开发环境
APP_ENV=development docker-compose build php

# 构建生产环境
APP_ENV=production docker-compose build php

验证安装

Docker 容器验证

bash
# 验证 PHP 版本
docker run --rm php:8.2-fpm php -v

# 验证扩展
docker run --rm php:8.2-fpm php -m

# 验证 FPM 配置
docker run --rm php:8.2-fpm php-fpm -t

# 验证自定义镜像
docker build -t my-php-app .
docker run --rm my-php-app php -v
docker run --rm my-php-app php -m | grep redis

云服务器验证

bash
# 标准验证
php -v
php -m
php --ini

# FPM 验证
php-fpm -t

# Web 验证
curl -I http://localhost

注意事项

安全注意事项

  1. 不要在镜像中硬编码密码:使用 Docker 环境变量或 Docker Secrets 传递敏感信息
  2. 使用非 root 用户运行:Dockerfile 中应创建专用用户运行 PHP-FPM 进程
  3. 定期更新基础镜像:关注 Alpine、Ubuntu 等基础镜像的安全更新
  4. 最小化镜像体积:生产环境不安装开发工具和 Xdebug

性能注意事项

  1. 启用 OPcache:容器环境中 OPcache 的性能提升更加明显(JIT +30%~50%)
  2. 关闭 OPcache 时间戳验证:容器部署中文件不会变化,可以安全关闭
  3. 使用 Alpine 基础镜像:Alpine 镜像体积约为 Debian 的 1/3,启动速度更快
  4. 合理设置容器资源限制:通过 --memory--cpus 参数控制资源

常见问题

问题原因解决方案
容器内无法连接数据库网络配置问题使用 Docker 网络或 host.docker.internal
权限拒绝错误文件所有权问题确保容器内用户与挂载目录的权限一致
Composer 安装超时网络问题使用国内镜像源 composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
扩展编译失败缺少编译依赖在安装扩展前确保安装了对应的 -dev

最佳实践

  1. 使用多阶段构建:将依赖安装、代码构建和最终运行分离为不同阶段,减小镜像体积并提高安全性。

  2. 使用 .dockerignore:排除不需要的文件(如 .gitnode_modulesvendor),加速构建过程。

  3. 固定基础镜像版本:使用明确的版本标签(如 php:8.2-fpm-alpine3.18),避免使用 latest 标签导致的不可预期变更。

  4. 利用构建缓存:将 composer.jsonpackage.json 等依赖文件先于源码复制,充分利用 Docker 层缓存。

  5. 健康检查:为所有服务容器配置 HEALTHCHECK,确保编排系统可以正确判断服务状态。

  6. 日志管理:配置 PHP-FPM 和 Nginx 的日志输出到 stdout/stderr,便于容器化环境下的日志收集。

  7. 使用编排工具:生产环境推荐使用 Docker Compose、Kubernetes 或云服务商的容器编排服务来管理 PHP 容器。

下一节

你已经了解了在云计算平台和 Docker 上部署 PHP 的方法。接下来,我们深入探讨 PHP-FPM 的配置与性能调优:

参考链接