1. 为什么选择Docker Compose部署Nginx?
在容器化部署的世界里,Nginx作为高性能的Web服务器和反向代理服务器,其容器化部署已经成为现代应用交付的标准实践。相比直接使用docker run命令启动单个容器,Docker Compose方案具有几个显著优势:
首先,Docker Compose通过YAML文件定义多容器应用,使得Nginx的配置、网络、存储卷等关键参数全部代码化。我经历过多次服务器迁移,只需一个docker-compose.yml文件就能在新环境快速重建完整的Nginx服务,避免了手工配置可能导致的遗漏和错误。
其次,当Nginx需要与后端服务(如Node.js、PHP应用)配合时,Compose可以轻松定义服务间的依赖关系和网络连接。上周我刚用Compose部署了一个包含Nginx+PHP-FPM+MySQL的三层应用,所有服务通过内部网络自动互联,省去了手动配置DNS的麻烦。
最重要的是版本控制友好。我把docker-compose.yml和Nginx配置文件都纳入Git仓库,每次修改都有迹可循。当需要回滚时,直接checkout历史版本就能恢复整套环境,这种可重复性对生产环境尤为重要。
2. 环境准备与基础配置
2.1 安装Docker引擎和Compose插件
虽然很多教程会分别安装Docker和Docker Compose,但从Docker 23.0开始,Compose已经作为官方插件集成到Docker CLI中。我推荐直接安装最新版Docker引擎,它会自动包含compose插件:
# Ubuntu/Debian系统安装命令 sudo apt-get update sudo apt-get install docker-ce docker-ce-cli containerd.io验证安装时,我发现新手常犯的错误是忘记将用户加入docker组,导致每次都要sudo。正确的做法是:
sudo usermod -aG docker $USER newgrp docker # 立即生效无需重启注意:生产环境要考虑安全风险,建议通过sudoers精细控制docker命令权限
2.2 项目目录结构设计
合理的目录结构是可持续维护的基础。经过多个项目的实践,我总结出以下结构:
/nginx-compose ├── docker-compose.yml ├── config/ │ ├── nginx.conf │ └── conf.d/ │ └── default.conf ├── logs/ │ ├── access.log │ └── error.log └── html/ └── index.html关键点:
- 将配置、日志、静态文件分别挂载到不同目录,避免容器内路径混乱
- conf.d目录用于存放各站点的独立配置,方便模块化管理
- 提前创建logs目录并设置777权限,防止容器因权限问题启动失败
3. 编写Docker Compose文件
3.1 基础服务定义
这是经过生产验证的docker-compose.yml模板:
version: '3.8' services: nginx: image: nginx:1.25-alpine container_name: nginx-web restart: unless-stopped ports: - "80:80" - "443:443" volumes: - ./config/nginx.conf:/etc/nginx/nginx.conf - ./config/conf.d:/etc/nginx/conf.d - ./logs:/var/log/nginx - ./html:/usr/share/nginx/html networks: - frontend networks: frontend: driver: bridge几个经验之谈:
- 使用alpine版本镜像,体积比常规镜像小60%,安全性更高
- restart策略设为unless-stopped,保证服务异常退出后自动恢复
- 网络单独定义方便后续扩展,比如添加PHP容器时只需加入同一网络
3.2 性能调优参数
对于高流量场景,需要在compose文件中添加资源限制:
deploy: resources: limits: cpus: '2' memory: 1G reservations: memory: 512M同时建议在nginx.conf中调整worker进程数:
worker_processes auto; # 自动匹配CPU核心数 events { worker_connections 1024; # 每个worker处理连接数 multi_accept on; }4. Nginx配置最佳实践
4.1 主配置文件拆分
传统的nginx.conf往往臃肿难维护。我的方案是将主配置拆分为:
# config/nginx.conf user nginx; worker_processes auto; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } 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; keepalive_timeout 65; include /etc/nginx/conf.d/*.conf; }然后在conf.d目录中按功能划分配置:
conf.d/ ├── default.conf # 默认站点 ├── gzip.conf # 压缩配置 ├── security.conf # 安全头设置 └── ssl.conf # SSL相关配置4.2 静态站点配置示例
这是经过优化的静态站点配置模板:
# config/conf.d/default.conf server { listen 80; server_name localhost; root /usr/share/nginx/html; index index.html; location / { try_files $uri $uri/ =404; } # 启用Gzip压缩 include gzip.conf; # 静态资源缓存 location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ { expires 30d; add_header Cache-Control "public, no-transform"; } # 禁止访问隐藏文件 location ~ /\. { deny all; } }5. 高级部署技巧
5.1 HTTPS证书自动化
使用Let's Encrypt配合Certbot实现自动续期:
services: certbot: image: certbot/certbot volumes: - ./certbot/www:/var/www/certbot - ./certbot/conf:/etc/letsencrypt command: certonly --webroot -w /var/www/certbot --email your@email.com -d yourdomain.com --agree-tos --non-interactive --keep-until-expiring nginx: volumes: - ./certbot/www:/var/www/certbot - ./certbot/conf:/etc/letsencrypt配合crontab设置每月自动续期:
0 3 1 * * docker compose run --rm certbot renew && docker compose exec nginx nginx -s reload5.2 多站点管理
通过不同compose项目隔离环境:
/projects ├── blog/ │ ├── docker-compose.yml │ └── config/ ├── shop/ │ ├── docker-compose.yml │ └── config/ └── proxy/ ├── docker-compose.yml └── config/使用Traefik或Nginx Proxy Manager实现统一入口,这是比传统nginx反向代理更现代的方案。
6. 常见问题排查
6.1 容器启动失败排查步骤
- 查看容器日志:
docker compose logs -f nginx- 检查配置语法:
docker compose exec nginx nginx -t- 进入容器调试:
docker compose exec -it nginx sh6.2 典型错误解决方案
问题1:端口冲突
错误信息:Bind for 0.0.0.0:80 failed: port is already allocated
解决方法:
# 查找占用进程 sudo lsof -i :80 # 或停止冲突容器 docker stop $(docker ps -q --filter "publish=80")问题2:权限拒绝
错误信息:Permission denied
解决方法:
# 对挂载目录赋权 chmod -R a+rwx ./logs # 或调整SELinux策略 sudo chcon -Rt svirt_sandbox_file_t ./config问题3:配置缓存
修改配置后不生效时,需要强制重建:
docker compose up -d --force-recreate --no-deps nginx