为什么选择Docker容器化部署
在传统部署方式中,开发环境和生产环境的不一致常常导致”在我本地能跑”的尴尬情况。Docker通过容器化技术,将应用及其依赖打包成标准化单元,实现了”一次构建,到处运行”的目标。
环境准备
首先确保系统已安装Docker和Docker Compose:
# 检查Docker版本
docker --version
# 检查Docker Compose版本
docker compose version
# 如果未安装,使用以下命令(Ubuntu/Debian)
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
项目目录结构
创建一个清晰的项目结构便于管理:
mkdir -p docker-lamp/{nginx,mysql,redis,web}
cd docker-lamp
# 目录结构
# docker-lamp/
# ├── docker-compose.yml
# ├── nginx/
# │ ├── nginx.conf
# │ └── conf.d/
# │ └── default.conf
# ├── mysql/
# │ └── my.cnf
# ├── redis/
# │ └── redis.conf
# └── web/
# └── index.html
Docker Compose核心配置
创建docker-compose.yml文件,定义三个核心服务:
version: '3.8'
services:
# Nginx反向代理
nginx:
image: nginx:1.25-alpine
container_name: nginx-server
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./nginx/conf.d:/etc/nginx/conf.d:ro
- ./web:/usr/share/nginx/html:ro
- ./logs/nginx:/var/log/nginx
depends_on:
- web
networks:
- app-network
restart: unless-stopped
# Web应用服务
web:
image: php:8.2-fpm-alpine
container_name: web-app
volumes:
- ./web:/var/www/html
networks:
- app-network
restart: unless-stopped
# MySQL数据库
mysql:
image: mysql:8.0
container_name: mysql-db
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: your_root_password
MYSQL_DATABASE: app_db
MYSQL_USER: app_user
MYSQL_PASSWORD: your_app_password
volumes:
- ./mysql/my.cnf:/etc/mysql/conf.d/my.cnf:ro
- mysql-data:/var/lib/mysql
- ./logs/mysql:/var/log/mysql
networks:
- app-network
restart: unless-stopped
# Redis缓存
redis:
image: redis:7.2-alpine
container_name: redis-cache
ports:
- "6379:6379"
volumes:
- ./redis/redis.conf:/usr/local/etc/redis/redis.conf:ro
- redis-data:/data
command: redis-server /usr/local/etc/redis/redis.conf
networks:
- app-network
restart: unless-stopped
networks:
app-network:
driver: bridge
volumes:
mysql-data:
redis-data:
Nginx配置详解
创建高性能Nginx配置文件:
# nginx/nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
use epoll;
multi_accept on;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# 日志格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
# 性能优化
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
# Gzip压缩
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css application/json application/javascript
text/xml application/xml application/xml+rss text/javascript;
include /etc/nginx/conf.d/*.conf;
}
站点配置文件:
# nginx/conf.d/default.conf
upstream php_backend {
server web:9000;
keepalive 32;
}
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.php index.html;
# 安全头
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass php_backend;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_keep_conn on;
}
# 静态资源缓存
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}
# 禁止访问隐藏文件
location ~ /\. {
deny all;
}
}
MySQL配置优化
# mysql/my.cnf
[mysqld]
# 基础配置
port = 3306
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
default-storage-engine = InnoDB
# 性能优化
innodb_buffer_pool_size = 1G
innodb_log_file_size = 256M
innodb_flush_log_at_trx_commit = 2
innodb_flush_method = O_DIRECT
innodb_file_per_table = 1
max_connections = 200
thread_cache_size = 16
query_cache_type = 0
query_cache_size = 0
# 慢查询日志
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 2
[client]
default-character-set = utf8mb4
Redis配置优化
# redis/redis.conf
# 网络配置
bind 0.0.0.0
port 6379
protected-mode no
# 内存管理
maxmemory 512mb
maxmemory-policy allkeys-lru
# 持久化配置
appendonly yes
appendfsync everysec
save 900 1
save 300 10
save 60 10000
# 日志
loglevel notice
logfile ""
一键启动服务
# 启动所有服务
docker compose up -d
# 查看服务状态
docker compose ps
# 查看日志
docker compose logs -f nginx
docker compose logs -f mysql
docker compose logs -f redis
# 停止服务
docker compose down
# 停止并删除数据卷
docker compose down -v
常用运维命令
# 进入容器
docker exec -it nginx-server sh
docker exec -it mysql-db mysql -uroot -p
docker exec -it redis-cache redis-cli
# 查看资源使用
docker stats
# 备份MySQL数据库
docker exec mysql-db mysqldump -uroot -pyour_root_password app_db > backup.sql
# 恢复数据库
docker exec -i mysql-db mysql -uroot -pyour_root_password app_db < backup.sql
# 清理未使用的资源
docker system prune -a
# 查看网络
docker network ls
docker network inspect docker-lamp_app-network
健康检查配置
在docker-compose.yml中添加健康检查:
services:
mysql:
# ... 其他配置
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 3
start_period: 30s
redis:
# ... 其他配置
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 3s
retries: 3
总结
通过Docker Compose编排,我们实现了一套完整的Web服务架构。这种方式不仅简化了部署流程,还确保了环境的一致性和可移植性。生产环境中,建议结合CI/CD流水线实现自动化部署,并配置监控告警系统保障服务稳定性。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END












暂无评论内容