# Docker怎么配置Nginx+PHP+MySQL
## 前言
在當今的Web開發環境中,Docker已經成為部署應用程序的標準工具之一。它通過容器化技術,使得開發、測試和部署過程變得更加高效和一致。本文將詳細介紹如何使用Docker配置一個完整的Nginx+PHP+MySQL開發環境,涵蓋從基礎概念到實際操作的方方面面。
## 目錄
1. [Docker基礎概念](#docker基礎概念)
2. [環境準備](#環境準備)
3. [配置MySQL容器](#配置mysql容器)
4. [配置PHP容器](#配置php容器)
5. [配置Nginx容器](#配置nginx容器)
6. [容器互聯與網絡配置](#容器互聯與網絡配置)
7. [持久化數據存儲](#持久化數據存儲)
8. [Docker Compose簡化部署](#docker-compose簡化部署)
9. [性能優化與安全配置](#性能優化與安全配置)
10. [常見問題解決](#常見問題解決)
11. [最佳實踐](#最佳實踐)
12. [總結](#總結)
## Docker基礎概念
### 什么是Docker
Docker是一個開源的應用容器引擎,基于Go語言開發。它允許開發者將應用及其依賴打包到一個輕量級、可移植的容器中,然后發布到任何流行的Linux機器上,也可以實現虛擬化。
### 核心組件
1. **Docker鏡像(Image)**:類似于虛擬機鏡像,包含運行應用所需的所有內容
2. **Docker容器(Container)**:鏡像的運行實例
3. **Docker倉庫(Registry)**:用于存儲和分發鏡像
4. **Dockerfile**:用于構建鏡像的腳本文件
5. **Docker Compose**:用于定義和運行多容器應用的工具
### 容器與虛擬機的區別
| 特性 | 容器 | 虛擬機 |
|------|------|--------|
| 啟動時間 | 秒級 | 分鐘級 |
| 性能 | 接近原生 | 較差 |
| 系統資源 | 占用少 | 占用多 |
| 隔離性 | 進程級 | 系統級 |
| 鏡像大小 | 通常以MB計 | 通常以GB計 |
## 環境準備
### 系統要求
- 支持的操作系統:
- Linux (推薦Ubuntu 20.04/22.04, CentOS 7/8)
- macOS 10.15+
- Windows 10/11 (需啟用WSL2)
- 硬件要求:
- 至少4GB RAM
- 20GB可用磁盤空間
- 支持虛擬化的CPU
### Docker安裝
#### Linux系統安裝
```bash
# 卸載舊版本
sudo apt-get remove docker docker-engine docker.io containerd runc
# 安裝依賴
sudo apt-get update
sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg \
lsb-release
# 添加Docker官方GPG密鑰
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
# 設置穩定版倉庫
echo \
"deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 安裝Docker引擎
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
# 驗證安裝
sudo docker run hello-world
docker --version
docker-compose --version
docker run hello-world
官方提供了多個MySQL鏡像版本,推薦使用:
docker pull mysql:8.0
docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:8.0
-e MYSQL_ROOT_PASSWORD:設置root用戶密碼-e MYSQL_DATABASE:創建指定名稱的數據庫-e MYSQL_USER:創建新用戶-e MYSQL_PASSWORD:設置新用戶密碼-p 3306:3306:端口映射-v /my/own/datadir:/var/lib/mysql:數據卷掛載my.cnf:[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
default_authentication_plugin=mysql_native_password
docker run --name some-mysql \
-v /path/to/my.cnf:/etc/mysql/conf.d/my.cnf \
-e MYSQL_ROOT_PASSWORD=my-secret-pw \
-d mysql:8.0
docker run --name some-mysql \
-v /my/own/datadir:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=my-secret-pw \
-d mysql:8.0
# 進入MySQL容器
docker exec -it some-mysql bash
# 連接MySQL
mysql -u root -p
# 查看運行中的容器
docker ps
# 停止容器
docker stop some-mysql
# 啟動已停止的容器
docker start some-mysql
# 刪除容器
docker rm some-mysql
官方PHP鏡像提供了多個版本和變體:
php:8.1-apache:包含Apache的PHP 8.1php:8.1-fpm:PHP-FPM版本php:8.1-cli:命令行版本對于Nginx+PHP環境,我們選擇FPM版本:
docker pull php:8.1-fpm
docker run --name my-php -d php:8.1-fpm
PHP-FPM鏡像默認只包含基本擴展,需要手動安裝其他擴展:
FROM php:8.1-fpm
RUN docker-php-ext-install pdo pdo_mysql mysqli
RUN pecl install redis && docker-php-ext-enable redis
常用擴展安裝命令:
# 安裝PDO MySQL擴展
docker-php-ext-install pdo_mysql
# 安裝GD庫
docker-php-ext-install gd
# 安裝Zip擴展
docker-php-ext-install zip
# 安裝Redis擴展
pecl install redis && docker-php-ext-enable redis
# 安裝Xdebug
pecl install xdebug && docker-php-ext-enable xdebug
php.ini文件:upload_max_filesize = 20M
post_max_size = 20M
memory_limit = 256M
date.timezone = Asia/Shanghai
docker run --name my-php \
-v /path/to/php.ini:/usr/local/etc/php/conf.d/custom.ini \
-d php:8.1-fpm
docker run --name my-php \
-v /path/to/your/project:/var/www/html \
-d php:8.1-fpm
# 構建階段
FROM php:8.1-fpm AS builder
WORKDIR /var/www/html
COPY . .
RUN composer install --no-dev --optimize-autoloader
# 生產階段
FROM php:8.1-fpm
COPY --from=builder /var/www/html /var/www/html
RUN chown -R www-data:www-data /var/www/html \
&& find /var/www/html -type d -exec chmod 755 {} \; \
&& find /var/www/html -type f -exec chmod 644 {} \;
docker pull nginx:alpine
docker run --name my-nginx -p 80:80 -d nginx:alpine
default.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 php:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
docker run --name my-nginx \
-v /path/to/your/project:/var/www/html \
-v /path/to/default.conf:/etc/nginx/conf.d/default.conf \
-p 80:80 \
-d nginx:alpine
# 啟用gzip壓縮
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
# 客戶端緩存控制
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 30d;
}
# 禁止訪問隱藏文件
location ~ /\. {
deny all;
}
docker run --name my-nginx \
-v /path/to/nginx/logs:/var/log/nginx \
-p 80:80 \
-d nginx:alpine
docker network create my-network
# MySQL容器
docker run --name my-mysql \
--network my-network \
-e MYSQL_ROOT_PASSWORD=secret \
-e MYSQL_DATABASE=myapp \
-e MYSQL_USER=myapp \
-e MYSQL_PASSWORD=myapp \
-v mysql_data:/var/lib/mysql \
-d mysql:8.0
# PHP容器
docker run --name my-php \
--network my-network \
-v /path/to/your/project:/var/www/html \
-d php:8.1-fpm
# Nginx容器
docker run --name my-nginx \
--network my-network \
-v /path/to/your/project:/var/www/html \
-v /path/to/nginx.conf:/etc/nginx/conf.d/default.conf \
-p 80:80 \
-d nginx:alpine
在Nginx配置中,PHP容器可以通過容器名my-php訪問:
fastcgi_pass my-php:9000;
在PHP應用中,MySQL可以通過容器名my-mysql訪問:
$db = new PDO('mysql:host=my-mysql;dbname=myapp', 'myapp', 'myapp');
# 創建數據卷
docker volume create mysql_data
# 使用數據卷
docker run --name my-mysql \
-v mysql_data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=secret \
-d mysql:8.0
docker run --name my-php \
-v /path/to/your/project:/var/www/html \
-d php:8.1-fpm
# 備份MySQL數據
docker run --rm --volumes-from my-mysql -v $(pwd):/backup alpine \
tar cvf /backup/mysql_backup.tar /var/lib/mysql
# 恢復MySQL數據
docker run --rm --volumes-from my-mysql -v $(pwd):/backup alpine \
sh -c "rm -rf /var/lib/mysql/* && tar xvf /backup/mysql_backup.tar -C /var/lib/mysql --strip 1"
version: '3.8'
services:
mysql:
image: mysql:8.0
container_name: my-mysql
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: myapp
MYSQL_USER: myapp
MYSQL_PASSWORD: myapp
volumes:
- mysql_data:/var/lib/mysql
networks:
- my-network
restart: unless-stopped
php:
build:
context: .
dockerfile: Dockerfile.php
container_name: my-php
volumes:
- ./src:/var/www/html
networks:
- my-network
depends_on:
- mysql
restart: unless-stopped
nginx:
image: nginx:alpine
container_name: my-nginx
volumes:
- ./src:/var/www/html
- ./nginx.conf:/etc/nginx/conf.d/default.conf
ports:
- "80:80"
networks:
- my-network
depends_on:
- php
restart: unless-stopped
volumes:
mysql_data:
networks:
my-network:
driver: bridge
# 啟動服務
docker-compose up -d
# 停止服務
docker-compose down
# 查看日志
docker-compose logs -f
# 重建服務
docker-compose up -d --build
# 執行命令
docker-compose exec php bash
# worker進程數
worker_processes auto;
# 每個worker的最大連接數
worker_connections 1024;
# 啟用epoll事件模型
use epoll;
# 開啟高效文件傳輸模式
sendfile on;
# 減少數據包數量
tcp_nopush on;
# 保持連接超時時間
keepalive_timeout 65;
; 進程管理方式
pm = dynamic
; 最大子進程數
pm.max_children = 50
; 啟動時的進程數
pm.start_servers = 5
; 空閑時的最小進程數
pm.min_spare_servers = 2
; 空閑時的最大進程數
pm.max_spare_servers = 8
[mysqld]
# 緩沖池大小 (總內存的50-70%)
innodb_buffer_pool_size = 1G
# 日志文件大小
innodb_log_file_size = 256M
# 刷新方法
innodb_flush_method = O_DIRECT
# 并發線程數
innodb_thread_concurrency = 8
MySQL安全:
PHP安全:
disable_functions = exec,passthru,shell_exec,systemdisplay_errors = Offupload_max_filesize = 2MNginx安全:
server_tokens off;if ($request_method !~ ^(GET|HEAD|POST)$ ) { return 444; }
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
查看日志:
docker logs container_name
常見原因:
檢查MySQL容器是否運行:
docker ps
檢查網絡配置:
docker network inspect my-network
從PHP容器測試連接:
docker exec -it my-php bash
apt-get update && apt-get install -y mysql-client
mysql -h my-mysql -u myapp -p
查看文件權限:
docker exec my-php ls -la /var/www/html
解決方案:
docker exec my-php chown -R www-data:www-data /var/www/html
監控容器資源使用:
docker stats
調整配置:
使用綁定掛載實現代碼熱更新: “`yaml volumes:
”`
啟用Xdebug調試:
zend_extension=xdebug.so
xdebug.mode=debug
xdebug.start_with_request=yes
xdebug.client_host=host.docker.internal
xdebug.client_port=9003
使用Makefile簡化命令: “`makefile
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。