Nginx代理主机内多容器向外暴露


Nginx代理主机内多容器向外暴露

我们知道,docker容器通过端口暴露与宿主机映射可以将服务对外暴露使用,但正常情况下一台宿主机不可能只通过docker对外暴露一个服务,然而服务端口有相同的,比如80或者443,这种情况我们可以通过Nginx的反向代理与端口转发来实现需求。

Nginx安装

# 新建Nginx仓库地址
sudo vim /etc/yum.repos.d/nginx.repo
# 填入如下内容,保存退出
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key

# 使用yum方式安装nginx
sudo yum -y install nginx
# 启动nginx服务以及添加开机启动
sudo systemctl start nginx && systemctl enable nginx

查看docker端口暴露

# 此处我们以rsshub容器为例
docker ps
CONTAINER ID   IMAGE           COMMAND              CREATED        STATUS                 PORTS                        NAMES
4efac40036f2   diygod/rsshub "dumb-init -- npm ru…"   2 months ago   Up 19 hours   0.0.0.0:1200->1200/tcp             rsshub

经过查询,我们知道,rsshub容器当前1200端口与宿主机1200端口映射,外部通过访问宿主机的1200端口可以访问到容器内,我们现在的需求是通过访问宿主机的443端口从而访问到容器内的1200端口。

通过acme签发ssl证书

因要通过443端口访问,所以我们还需要申请签发ssl证书,此处我们以acme申请签发并自动续期免费证书。

acme 安装

curl https://get.acme.sh | sh

acme.sh 会安装到 ~/.acme.sh/目录下,并创建新的自动计划(cronjob)在凌晨0点检查所有证书

证书生成的方式

  1. 网站文件方式,适合于已经部署好apache或是nginx服务器的情况

    acme.sh  --issue  -d <域名>  --webroot  <网站根目录>
    acme.sh  --issue  -d demo.example.com  --webroot /home/wwwroot/demo.example.com/
  2. 临时监听80端口方式,适合于没有部署好服务的服务器

    yum install socat
    acme.sh  --issue -d demo.example.com --standalone
  3. 手动配置DNS,需要有手动配置DNS的权限,适合没有服务器或是不想更改服务器的情况

    # 首先获得认证需要的解析记录
    acme.sh --issue --dns -d demo.example.com
    # 然后在DNS服务商中添加记录,最后重新生成证书
    acme.sh --renew -d demo.example.com
    # 使用这种方式 acme.sh 将无法自动更新证书,每次都需要手动再次重新解析验证域名所有权。
  4. 自动方式

    dns 方式的真正强大之处在于可以使用域名解析商提供的 api 自动添加 txt 记录完成验证,首先需要在云上申请有DNS配置权限的账号密码

    以阿里云为例,在阿里云官网登录添加拥有DNS配置权限的子账户 https://ram.console.aliyun.com/overview

    # 配置阿里云API密钥,在/root/.acme.sh/account.conf 中添加aliyun API密钥
    export Ali_Key="AccessKeyId"
    export Ali_Secret="AccessKeySecret"
    
    # 颁发证书,支持单域名、多域名、泛域名进行颁发,证书生成目录位于~/.acme.sh/ 对应域名文件夹下
    # 进行域名的 DNS 验证,使用api自动添加解析,中间会等待20秒左右验证正确性,验证成功后会有成功标记。
    sudo acme.sh --issue --dns dns_ali -d xx.com -d *.xx.com --debug #开启日志,如有报错便于定位问题
    [Thu Jul  1 09:56:55 CST 2021] Lets find script dir.
    …… …… #中间省略中间
    -----END CERTIFICATE-----
    [Thu Jul  1 09:57:49 CST 2021] Your cert is in  /root/.acme.sh/xx.com/xx.com.cer 
    [Thu Jul  1 09:57:49 CST 2021] Your cert key is in  /root/.acme.sh/xx.com/xx.com.key 
    [Thu Jul  1 09:57:49 CST 2021] The intermediate CA cert is in  /root/.acme.sh/xx.com/ca.cer 
    [Thu Jul  1 09:57:49 CST 2021] And the full chain certs is there:  /root/.acme.sh/xx.com/fullchain.cer 
    [Thu Jul  1 09:57:49 CST 2021] _on_issue_success
    # 直到出现以上,整个证书颁发完成
    
    # 个人喜好,将证书复制到单独目录,非必要操作
    sudo cp /root/.acme.sh/xx.com/*.cer /app/rsshub/ssl/
    sudo cp /root/.acme.sh/xx.com/*.key /app/rsshub/ssl/

Nginx 修改默认配置

# Nginx配置文件位于/etc/nginx/conf.d/default.conf

server{
    listen 80; #监听80端口
    #listen [::]:80;
    server_name rss.xx.com;
    return 301 https://$host$request_uri; #将80端口通过301跳转转发到443端口
}

server{
    listen 443 ssl http2; #启用https也就是443端口
    server_name rss.xx.com; #绑定的域名,需要先到域名控制台将域名解析到宿主机
    ssl_certificate /app/rsshub/ssl/xx.com.cer; #证书存放路径,个人喜好,此处将证书复制到单独目录中
    ssl_certificate_key /app/rsshub/ssl/xx.com.key;#证书存放路径,个人喜好,此处将证书复制到单独目录中
    ssl_session_timeout 5m;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on; #启用加密算法
    location / {
    proxy_set_header Host $http_host; #代理设置
    proxy_pass http://127.0.0.1:1200; #代理的地址与端口
}
}    

# 如还有其他容器需要映射添加的可直接复制一段server{}字段,按实际需要修改即可。
server{
    listen 80;
    server_name i.xx.com;
    return 301 https://$host$request_uri;
}
server{
    listen 443 ssl http2;
      server_name i.xx.com;

      # Specify SSL config if using a shared one.
      #include conf.d/ssl/ssl.conf;
      ssl_certificate  /app/bitwarden/data/cert/i.xx.com.cer;
      ssl_certificate_key /app/bitwarden/data/cert/i.xx.com.key; 
      ssl_session_timeout 5m;
     ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
      ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
     ssl_prefer_server_ciphers on;
     location / {
        proxy_set_header Host $http_host;
        proxy_pass http://127.0.0.1:8090; 
}
}

访问测试

通过上述配置后,基本实现了通过nginx代理容器内服务需求,可以看到可以通过https访问,并查看证书当前状态一切正常。


文章作者: Webpoplayer
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Webpoplayer !
评论
  目录