问题背景与适用场景
在当前软件开发环境中,容器化技术已成为部署应用的标准方式之一。Docker 作为容器化技术的代表,为 PHP 应用提供了轻量级、可移植、可扩展的部署方案。无论是传统的 PHP 应用,还是基于现代框架(如 Laravel、Symfony)的应用,都可以通过 Docker 实现环境一致性,解决"在我机器上能运行"的问题。Docker 部署 PHP 应用特别适用于以下场景:
- 需要确保开发、测试和生产环境一致的情况
- 需要快速扩展 PHP 应用以应对流量高峰
- 多个应用共享同一台服务器,需要资源隔离
- 持续集成/持续部署(CI/CD)流程集成
- 微服务架构中的 PHP 服务部署
原理部分
Docker 使用容器来打包应用及其依赖,实现环境隔离。在 PHP 应用的 Docker 部署中,核心原理包括:
- 镜像(Image):包含应用代码、运行时环境、系统工具、依赖库等的只读模板。PHP 应用通常基于官方 PHP 镜像进行定制。
- 容器(Container):镜像的运行实例,拥有独立的文件系统、进程空间和网络栈。每个容器都是隔离的,互不影响。
- Dockerfile:定义如何构建应用镜像的文本文件,包含一系列命令和指令。
- Docker Compose:用于定义和运行多容器 Docker 应用工具,通过 YAML 文件配置应用的服务、网络和数据卷。
- 网络:容器间通信的机制,支持桥接、主机、覆盖等多种网络模式。
- 数据卷(Volume):用于持久化容器数据的存储机制,即使容器被删除,数据仍然保留。
操作步骤
1. 准备工作
- 安装 Docker 和 Docker Compose
- 准备 PHP 应用代码
2. 创建 Dockerfile
在项目根目录创建 Dockerfile,定义如何构建应用镜像:
# 选择基础镜像
FROM php:8.1-fpm
# 设置工作目录
WORKDIR /var/www/html
# 安装系统依赖和 PHP 扩展
RUN apt-get update && apt-get install -y \
git \
curl \
libpng-dev \
libonig-dev \
libxml2-dev \
zip \
unzip \
&& docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd
# 安装 Composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
# 复制应用代码
COPY . .
# 设置权限
RUN chown -R www-data:www-data /var/www/html
RUN usermod -u 1000 www-data
# 暴露端口
EXPOSE 9000
# 启动 PHP-FPM
CMD ["php-fpm"]3. 创建 docker-compose.yml
在项目根目录创建 docker-compose.yml,定义服务、网络和数据卷:
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile
container_name: php-app
volumes:
- ./:/var/www/html
networks:
- app-network
webserver:
image: nginx:alpine
container_name: nginx-server
ports:
- "8080:80"
volumes:
- ./:/var/www/html
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
depends_on:
- app
networks:
- app-network
networks:
app-network:
driver: bridge4. 创建 Nginx 配置
创建 docker/nginx/default.conf 文件:
server {
listen 80;
index index.php index.html;
root /var/www/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;
}
}5. 构建和运行容器
在项目根目录执行以下命令:
# 构建并启动服务
docker-compose up -d
# 查看运行状态
docker-compose ps
# 查看日志
docker-compose logs -f6. 访问应用
打开浏览器,访问 http://localhost:8080,即可查看 PHP 应用。
示例代码
下面是一个简单的 Laravel 应用的 Docker 部署示例:
Laravel 项目的 Dockerfile
FROM php:8.1-fpm
# 安装系统依赖
RUN apt-get update && apt-get install -y \
git \
curl \
libpng-dev \
libonig-dev \
libxml2-dev \
zip \
unzip \
&& rm -rf /var/lib/apt/lists/*
# 安装 PHP 扩展
RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd
# 安装 Composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
# 设置工作目录
WORKDIR /var/www
# 复制依赖文件
COPY composer.json composer.lock ./
# 安装依赖
RUN composer install --no-dev --no-interaction --no-scripts --optimize-autoloader
# 复制应用代码
COPY . .
# 设置权限
RUN chown -R www-data:www-data /var/www/storage /var/www/bootstrap/cache
RUN chmod -R 775 /var/www/storage /var/www/bootstrap/cache
# 暴露端口
EXPOSE 9000
# 启动 PHP-FPM
CMD ["php-fpm"]Laravel 项目的 docker-compose.yml
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile
container_name: laravel-app
volumes:
- ./:/var/www
environment:
- DB_HOST=mysql
- DB_PORT=3306
- DB_DATABASE=laravel
- DB_USERNAME=root
- DB_PASSWORD=root
depends_on:
- mysql
networks:
- app-network
webserver:
image: nginx:alpine
container_name: nginx-server
ports:
- "8080:80"
volumes:
- ./:/var/www
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
depends_on:
- app
networks:
- app-network
mysql:
image: mysql:5.7
container_name: mysql-db
environment:
MYSQL_DATABASE: laravel
MYSQL_ROOT_PASSWORD: root
volumes:
- mysql-data:/var/lib/mysql
networks:
- app-network
networks:
app-network:
driver: bridge
volumes:
mysql-data:
driver: local常见问题与注意事项
- 权限问题:
- 在容器内运行的应用可能没有足够的权限写入文件系统
主楼