Docker + Nginx 分离部署博客项目指南
2026/3/20大约 6 分钟
Docker + Nginx 分离部署博客项目指南
本文档详细介绍如何使用 Docker 分离部署 Nginx 和博客项目,实现容器化管理和灵活扩展。
目录
架构说明
架构优势:
- Nginx 独立部署,可作为多项目的统一入口
- 博客项目独立更新,不影响 Nginx 配置
- 便于横向扩展和负载均衡
- 容器隔离,安全性更高
环境准备
1. 安装 Docker
# Ubuntu/Debian
curl -fsSL https://get.docker.com | sh
# 启动 Docker 服务
sudo systemctl start docker
sudo systemctl enable docker
# 将当前用户加入 docker 组(免 sudo)
sudo usermod -aG docker $USER
# 验证安装
docker --version
2. 安装 Docker Compose
# 下载 Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# 添加执行权限
sudo chmod +x /usr/local/bin/docker-compose
# 验证安装
docker-compose --version
目录结构
在服务器上创建以下目录结构:
/opt/docker/
├── nginx/ # Nginx 容器相关文件
│ ├── conf.d/ # 站点配置目录
│ │ └── blog.conf # 博客站点配置
│ ├── nginx.conf # Nginx 主配置
│ ├── ssl/ # SSL 证书目录(可选)
│ │ ├── cert.pem
│ │ └── key.pem
│ └── logs/ # 日志目录
│
├── blog/ # 博客项目相关文件
│ ├── dist/ # 博客静态文件
│ ├── Dockerfile # 博客容器构建文件
│ └── nginx.conf # 博客内部 Nginx 配置
│
└── docker-compose.yml # 编排文件
创建目录:
sudo mkdir -p /opt/docker/{nginx/{conf.d,ssl,logs},blog/dist}
cd /opt/docker
Nginx 容器部署
1. Nginx 主配置文件
创建 /opt/docker/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_proxied any;
gzip_comp_level 6;
gzip_types
text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/xml+rss
application/atom+xml
image/svg+xml;
# 包含站点配置
include /etc/nginx/conf.d/*.conf;
}
2. 博客站点配置
创建 /opt/docker/nginx/conf.d/blog.conf:
# 上游服务器 - 博客容器
upstream blog_upstream {
server blog:8080;
keepalive 32;
}
server {
listen 801;
server_name blog.hsxisawd.icu; # 修改为你的域名
# 如需 HTTPS,取消下面注释并配置证书
# listen 443 ssl http2;
# ssl_certificate /etc/nginx/ssl/cert.pem;
# ssl_certificate_key /etc/nginx/ssl/key.pem;
# ssl_protocols TLSv1.2 TLSv1.3;
# ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
# ssl_prefer_server_ciphers off;
# HTTP 重定向到 HTTPS(启用 HTTPS 后取消注释)
# if ($scheme != "https") {
# return 301 https://$host$request_uri;
# }
# 代理到博客容器
location / {
proxy_pass http://blog_upstream;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Connection "";
# 缓存设置
proxy_cache_bypass $http_upgrade;
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
# 健康检查端点
location /health {
access_log off;
return 200 "OK";
add_header Content-Type text/plain;
}
}
博客项目容器部署
1. 博客 Dockerfile
创建 /opt/docker/blog/Dockerfile:
# 使用轻量级 Nginx Alpine 镜像
FROM nginx:alpine
# 设置维护者信息
LABEL maintainer="your-email@example.com"
LABEL description="Blog static site container"
# 删除默认配置
RUN rm -rf /etc/nginx/conf.d/default.conf
# 复制自定义 Nginx 配置
COPY nginx.conf /etc/nginx/conf.d/blog.conf
# 复制静态文件到容器
COPY dist/ /usr/share/nginx/html/
# 设置文件权限
RUN chown -R nginx:nginx /usr/share/nginx/html && \
chmod -R 755 /usr/share/nginx/html
# 暴露端口
EXPOSE 8080
# 健康检查
HEALTHCHECK \
CMD wget --quiet --tries=1 --spider http://localhost:8080/ || exit 1
# 启动 Nginx
CMD ["nginx", "-g", "daemon off;"]
2. 博客内部 Nginx 配置
创建 /opt/docker/blog/nginx.conf:
server {
listen 8080;
server_name localhost;
root /usr/share/nginx/html;
index index.html;
# 禁用目录列表
autoindex off;
# VuePress SPA 路由支持
location / {
try_files $uri $uri/ /index.html;
}
# 静态资源长期缓存
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|webp|avif|woff2?)$ {
expires 1y;
add_header Cache-Control "public, immutable, max-age=31536000";
try_files $uri =404;
}
# 保护隐藏文件
location ~ /\. {
deny all;
return 404;
}
# favicon 和 robots.txt
location = /favicon.ico {
access_log off;
log_not_found off;
expires 1y;
}
location = /robots.txt {
access_log off;
log_not_found off;
}
# 禁止访问 .map 文件
location ~* \.map$ {
deny all;
return 404;
}
# 错误页面
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
}
Docker Compose 编排
创建 /opt/docker/docker-compose.yml:
version: "3.8"
services:
# Nginx 反向代理服务
nginx:
image: nginx:alpine
container_name: nginx-proxy
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./nginx/conf.d:/etc/nginx/conf.d:ro
- ./nginx/ssl:/etc/nginx/ssl:ro
- ./nginx/logs:/var/log/nginx
networks:
- blog-network
depends_on:
- blog
healthcheck:
test: ["CMD", "nginx", "-t"]
interval: 30s
timeout: 10s
retries: 3
# 博客静态站点服务
blog:
build:
context: ./blog
dockerfile: Dockerfile
container_name: blog-site
restart: always
expose:
- "8080"
networks:
- blog-network
healthcheck:
test:
[
"CMD",
"wget",
"--quiet",
"--tries=1",
"--spider",
"http://localhost:8080/",
]
interval: 30s
timeout: 10s
retries: 3
networks:
blog-network:
driver: bridge
name: blog-network
部署操作
1. 上传文件到服务器
将本地 dist 目录上传到服务器:
# 方式一:使用 scp
scp -r ./dist/* user@your-server:/opt/docker/blog/dist/
# 方式二:使用 rsync(推荐,支持增量同步)
rsync -avz --delete ./dist/ user@your-server:/opt/docker/blog/dist/
2. 启动服务
cd /opt/docker
# 构建并启动所有服务
docker-compose up -d --build
# 查看服务状态
docker-compose ps
# 查看日志
docker-compose logs -f
3. 验证部署
# 检查容器运行状态
docker ps
# 测试博客服务
curl http://localhost
# 检查 Nginx 配置
docker exec nginx-proxy nginx -t
常用命令
服务管理
# 启动服务
docker-compose up -d
# 停止服务
docker-compose down
# 重启服务
docker-compose restart
# 重启单个服务
docker-compose restart blog
# 查看服务日志
docker-compose logs -f blog
docker-compose logs -f nginx
更新部署
# 更新博客内容(重新构建博客容器)
docker-compose up -d --build blog
# 更新 Nginx 配置(无需重建)
docker-compose restart nginx
# 完全重建所有服务
docker-compose down
docker-compose up -d --build
清理命令
# 删除停止的容器
docker container prune
# 删除无用镜像
docker image prune
# 删除所有未使用资源
docker system prune -a
故障排查
1. 容器无法启动
# 查看容器日志
docker-compose logs blog
docker-compose logs nginx
# 检查容器状态
docker inspect blog-site
2. 502 Bad Gateway
# 检查博客容器是否运行
docker ps | grep blog
# 检查网络连通性
docker exec nginx-proxy ping blog
# 查看 Nginx 错误日志
docker exec nginx-proxy cat /var/log/nginx/error.log
3. 静态资源 404
# 进入博客容器检查文件
docker exec -it blog-site sh
ls -la /usr/share/nginx/html/
# 检查文件权限
docker exec blog-site ls -la /usr/share/nginx/html/
4. 配置更新不生效
# 重新加载 Nginx 配置
docker exec nginx-proxy nginx -s reload
# 或重启容器
docker-compose restart nginx
快速部署脚本
创建 /opt/docker/deploy.sh:
#!/bin/bash
set -e
echo "=== 开始部署博客项目 ==="
cd /opt/docker
# 拉取最新代码/文件(如果使用 Git)
# git pull origin main
# 停止旧服务
echo "停止旧服务..."
docker-compose down
# 清理旧镜像
echo "清理旧镜像..."
docker image prune -f
# 构建并启动服务
echo "构建并启动服务..."
docker-compose up -d --build
# 等待服务启动
echo "等待服务启动..."
sleep 5
# 检查服务状态
echo "检查服务状态..."
docker-compose ps
# 健康检查
echo "执行健康检查..."
if curl -s -o /dev/null -w "%{http_code}" http://localhost | grep -q "200"; then
echo "✅ 部署成功!博客已上线。"
else
echo "❌ 部署可能存在问题,请检查日志。"
docker-compose logs
fi
添加执行权限:
chmod +x /opt/docker/deploy.sh
附录:HTTPS 配置
如需启用 HTTPS,请按以下步骤操作:
1. 获取 SSL 证书
# 使用 Let's Encrypt 免费证书
apt install certbot
certbot certonly --standalone -d your-domain.com
# 复制证书到 Docker 目录
cp /etc/letsencrypt/live/your-domain.com/fullchain.pem /opt/docker/nginx/ssl/cert.pem
cp /etc/letsencrypt/live/your-domain.com/privkey.pem /opt/docker/nginx/ssl/key.pem
2. 修改 Nginx 配置
编辑 /opt/docker/nginx/conf.d/blog.conf,取消 HTTPS 相关注释。
3. 重启服务
docker-compose restart nginx