Docker部署NGINX反向代理

🧑‍💻 User

我有一台云服务器A,IP地址为47.99.145.66。企业内部有一台算力服务器B,通过DDNS将本地3001端口转发到tsiliang.com:3001。我想在A中使用docker部署NGINX服务,实现用户访问ai.tsiliang.com,实际服务为B的3001端口服务,保护算力服务器的安全。


🤖 Assistant

已深度思考 我们想要实现的是:用户访问ai.tsiliang.com时,通过云服务器A上的Nginx反向代理到企业内部算力服务器B的3001端口服务(通过DDNS域名tsiliang.com:3001访问)。
步骤:
1. 在云服务器A上使用Docker部署Nginx。
2. 配置Nginx,将对ai.tsiliang.com的请求转发到tsiliang.com:3001。
3. 确保云服务器A的Nginx配置正确,并且能够解析ai.tsiliang.com到云服务器A的IP。

注意:由于算力服务器B是通过DDNS将本地3001端口转发到tsiliang.com:3001,所以我们可以通过tsiliang.com:3001来访问B的服务。

我们需要做的是:
- 在云服务器A上,使用Docker运行Nginx,并配置一个反向代理服务器块(server block),将请求代理到tsiliang.com:3001。
- 同时,我们需要确保域名ai.tsiliang.com的DNS记录指向云服务器A的IP地址(47.99.145.66)。

下面我们来实现Docker部署Nginx并配置反向代理。

首先,在云服务器A上创建一个目录,用于存放Nginx配置文件和日志等。
例如,我们创建目录:/home/nginx/conf,并在其中创建nginx.conf文件。

但是,为了简单起见,我们可以先创建一个简单的nginx.conf,然后通过Docker卷挂载到容器中。

假设我们使用以下目录结构:
/home/nginx/
├── conf/
│ └── nginx.conf
├── logs/
└── html/

现在,我们编写nginx.conf文件,内容如下:
我来帮您设计一个使用Docker部署NGINX的反向代理方案,保护您的算力服务器安全。

方案设计

1. 创建目录结构

# 在云服务器A上创建目录
mkdir -p ~/nginx-proxy/{conf,logs,html}
cd ~/nginx-proxy

2. 创建NGINX配置文件

创建 conf/nginx.conf 文件:

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
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;
    tcp_nopush on;
    keepalive_timeout 65;
    types_hash_max_size 2048;

    # 上游服务器配置
    upstream backend_server {
        server tsiliang.com:3001;
        keepalive 32;
    }

    # 主服务器配置
    server {
        listen 80;
        server_name ai.tsiliang.com;
        
        # 安全头部
        add_header X-Frame-Options DENY;
        add_header X-Content-Type-Options nosniff;
        add_header X-XSS-Protection "1; mode=block";
        add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
        
        # 反向代理配置
        location / {
            proxy_pass http://backend_server;
            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_connect_timeout 30s;
            proxy_send_timeout 30s;
            proxy_read_timeout 30s;
            
            # 缓冲区设置
            proxy_buffering on;
            proxy_buffer_size 4k;
            proxy_buffers 8 4k;
            
            # 禁用代理缓存(适用于动态内容)
            proxy_no_cache 1;
            proxy_cache_bypass 1;
        }

        # 健康检查端点
        location /nginx-health {
            access_log off;
            return 200 "healthy\n";
            add_header Content-Type text/plain;
        }

        # 拒绝访问隐藏文件
        location ~ /\. {
            deny all;
            access_log off;
            log_not_found off;
        }
    }
}

3. 创建Docker Compose文件

创建 docker-compose.yml

version: '3.8'

services:
  nginx-proxy:
    image: nginx:alpine
    container_name: nginx-proxy
    restart: unless-stopped
    ports:
      - "80:80"
      # 如果需要HTTPS,添加:"443:443"
    volumes:
      - ./conf/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./logs:/var/log/nginx
      - ./html:/usr/share/nginx/html
    environment:
      - TZ=Asia/Shanghai
    networks:
      - nginx-network

networks:
  nginx-network:
    driver: bridge

4. 部署和启动

# 启动服务
docker-compose up -d

# 查看日志
docker-compose logs -f

# 检查服务状态
docker-compose ps

5. 增强安全配置(可选)

创建 conf/security.conf 用于额外的安全配置:

# 限制请求方法
if ($request_method !~ ^(GET|HEAD|POST)$ ) {
    return 405;
}

# 限制请求大小
client_max_body_size 10m;

# 隐藏Nginx版本号
server_tokens off;

# 限制连接频率
limit_conn_zone $binary_remote_addr zone=addr:10m;
limit_conn addr 100;

6. 监控和日志(可选)

创建简单的监控脚本 monitor.sh

#!/bin/bash
# 监控NGINX状态

CONTAINER_NAME="nginx-proxy"

check_nginx() {
    if docker exec $CONTAINER_NAME nginx -t > /dev/null 2>&1; then
        echo "$(date): NGINX configuration is valid"
    else
        echo "$(date): ERROR - NGINX configuration is invalid"
    fi
}

check_response() {
    response=$(curl -s -o /dev/null -w "%{http_code}" http://ai.tsiliang.com/nginx-health)
    if [ "$response" = "200" ]; then
        echo "$(date): Service is healthy"
    else
        echo "$(date): ERROR - Service response: $response"
    fi
}

# 执行检查
check_nginx
check_response

7. 域名解析配置

确保您的域名解析设置正确:

  • ai.tsiliang.com A记录指向 47.99.145.66

8. 验证配置

# 测试NGINX配置
docker exec nginx-proxy nginx -t

# 检查容器状态
docker ps | grep nginx-proxy

# 测试代理是否工作
curl -H "Host: ai.tsiliang.com" http://localhost

安全优势

  1. 隐藏后端服务器:用户只看到云服务器A,不知道后端算力服务器B的存在
  2. 访问控制:可以在NGINX层面实现IP白名单、速率限制等
  3. Docker隔离:服务运行在容器中,与宿主机隔离
  4. 日志记录:所有访问请求都有完整日志
  5. 易于维护:配置文件和证书更新方便

后续扩展

如果需要HTTPS支持,可以:

  1. 申请SSL证书
  2. 修改NGINX配置监听443端口
  3. 配置SSL证书路径
  4. 设置HTTP到HTTPS的重定向

这个方案既保护了您的算力服务器安全,又提供了良好的可维护性和扩展性。


🧑‍💻 User

不使用docker compose


🤖 Assistant

已深度思考 由于用户要求不使用docker compose,我们将直接使用docker run命令来部署nginx容器。
同时,我们假设云服务器A上已经安装了docker。

步骤:
1. 在云服务器A上创建必要的目录和配置文件。
2. 使用docker run命令启动nginx容器,并挂载配置文件和日志目录。

注意:我们将使用之前创建的nginx配置文件,但需要稍作调整以适应直接使用docker run的情况。

我们先创建目录和配置文件:

在云服务器A上:
创建目录:~/nginx-proxy/conf, ~/nginx-proxy/logs, ~/nginx-proxy/html
将nginx.conf放在~/nginx-proxy/conf/下。

然后使用以下docker run命令:

但是注意,我们之前创建的nginx.conf中已经指定了上游服务器为tsiliang.com:3001,并且监听80端口,服务器名为ai.tsiliang.com。

由于我们使用docker运行,需要将容器的80端口映射到宿主机的80端口(如果宿主机80端口已被占用,可以映射到其他端口,但域名解析需要对应修改)。

假设我们使用宿主机的80端口,那么命令如下:
好的,我将为您提供不使用 Docker Compose 的纯 Docker 部署方案。

1. 创建目录结构

# 在云服务器A上创建目录
mkdir -p ~/nginx-proxy/{conf,logs,html}
cd ~/nginx-proxy

2. 创建NGINX配置文件

创建 conf/nginx.conf 文件:

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
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;
    tcp_nopush on;
    keepalive_timeout 65;
    types_hash_max_size 2048;

    # 上游服务器配置
    upstream backend_server {
        server tsiliang.com:3001;
        keepalive 32;
    }

    # 主服务器配置
    server {
        listen 80;
        server_name ai.tsiliang.com;
        
        # 安全头部
        add_header X-Frame-Options DENY;
        add_header X-Content-Type-Options nosniff;
        add_header X-XSS-Protection "1; mode=block";
        
        # 反向代理配置
        location / {
            proxy_pass http://backend_server;
            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_connect_timeout 30s;
            proxy_send_timeout 30s;
            proxy_read_timeout 30s;
            
            # 缓冲区设置
            proxy_buffering on;
            proxy_buffer_size 4k;
            proxy_buffers 8 4k;
            
            # 禁用代理缓存
            proxy_no_cache 1;
            proxy_cache_bypass 1;
        }

        # 健康检查端点
        location /nginx-health {
            access_log off;
            return 200 "healthy\n";
            add_header Content-Type text/plain;
        }

        # 拒绝访问隐藏文件
        location ~ /\. {
            deny all;
            access_log off;
            log_not_found off;
        }
    }
}

3. 使用 Docker 运行 NGINX

直接运行命令:

docker run -d \
  --name nginx-proxy \
  --restart unless-stopped \
  -p 80:80 \
  -v ~/nginx-proxy/conf/nginx.conf:/etc/nginx/nginx.conf:ro \
  -v ~/nginx-proxy/logs:/var/log/nginx \
  -v ~/nginx-proxy/html:/usr/share/nginx/html \
  -e TZ=Asia/Shanghai \
  nginx:alpine

或者创建启动脚本

创建 start-nginx.sh 文件:

#!/bin/bash

# 停止并删除现有容器
docker stop nginx-proxy 2>/dev/null
docker rm nginx-proxy 2>/dev/null

# 启动新的NGINX容器
docker run -d \
  --name nginx-proxy \
  --restart unless-stopped \
  -p 80:80 \
  -v ~/nginx-proxy/conf/nginx.conf:/etc/nginx/nginx.conf:ro \
  -v ~/nginx-proxy/logs:/var/log/nginx \
  -v ~/nginx-proxy/html:/usr/share/nginx/html \
  -e TZ=Asia/Shanghai \
  nginx:alpine

echo "NGINX proxy started successfully!"
echo "Container name: nginx-proxy"

给脚本执行权限并运行:

chmod +x start-nginx.sh
./start-nginx.sh

4. 管理命令

查看容器状态

docker ps -f name=nginx-proxy

查看容器日志

# 查看实时日志
docker logs -f nginx-proxy

# 查看最近100行日志
docker logs --tail 100 nginx-proxy

进入容器检查配置

# 进入容器
docker exec -it nginx-proxy sh

# 在容器内测试NGINX配置
nginx -t

# 查看NGINX进程
ps aux | grep nginx

# 退出容器
exit

重启容器

docker restart nginx-proxy

停止容器

docker stop nginx-proxy

删除容器

docker rm nginx-proxy

5. 验证部署

测试NGINX配置

docker exec nginx-proxy nginx -t

测试代理功能

# 测试健康检查
curl http://localhost/nginx-health

# 测试代理(需要在DNS解析生效后)
curl -H "Host: ai.tsiliang.com" http://localhost

检查端口监听

netstat -tulpn | grep :80
# 或使用
ss -tulpn | grep :80

6. 更新配置时的操作流程

当需要修改NGINX配置时:

# 1. 修改配置文件
vi ~/nginx-proxy/conf/nginx.conf

# 2. 测试配置文件语法
docker exec nginx-proxy nginx -t

# 3. 重载NGINX配置(不重启容器)
docker exec nginx-proxy nginx -s reload

# 或者重启容器
docker restart nginx-proxy

7. 备份和恢复

备份配置和日志

# 备份整个nginx-proxy目录
tar -czf nginx-backup-$(date +%Y%m%d).tar.gz ~/nginx-proxy

# 只备份配置
cp -r ~/nginx-proxy/conf ~/nginx-backup-conf

从备份恢复

# 停止当前容器
docker stop nginx-proxy
docker rm nginx-proxy

# 恢复配置文件
cp -r ~/nginx-backup-conf/* ~/nginx-proxy/conf/

# 重新启动
./start-nginx.sh

优势说明

这个纯Docker方案:

  1. 简单直接:不需要安装Docker Compose
  2. 易于管理:使用标准的Docker命令管理
  3. 资源友好:容器轻量,基于Alpine Linux
  4. 灵活性高:可以轻松修改配置和挂载卷
  5. 自动重启:配置了--restart unless-stopped确保服务高可用

这样就完成了不使用Docker Compose的NGINX反向代理部署,可以有效保护您的算力服务器安全。