Skip to main content

用 Nginx 的反向代理映射出容器的端口

docker 的容器运行过程中不能动态修改映射的端口号,但是可以在这个容器的环境跑一个 Nginx 反向代理,把容器的端口暴露出来。

反向代理 HTTP

替换:

参数 说明 示例
<对外端口> 映射到主机的端口 8000
<容器URL> 能够访问目标容器的URL http://container
docker run --rm --entrypoint /bin/sh -p <对外端口>:1080 nginx:1.19.0 -c 'echo "server { listen 1080;server_name default_server;location / { proxy_pass <容器URL>; }}" > /etc/nginx/conf.d/1080.conf && exec nginx -g "daemon off;"'

反向代理 HTTPS

要求变量:

参数 说明 示例
CERT_DIR 宿主机证书路径 ~/mycert
CERT_FILENAME 证书文件名(相对证书路径) mycert.pem
KEY_FILENAME 私钥文件名(相对证书路径) mycert.key
TARGET_URL 目标容器 URL http://container
HOST_SERVER_NAME 域名,必须与证书表达的相同 domain
HOST_PORT 映射到主机的端口 443
bash

CERT_DIR=`pwd`/cert
CERT_FILENAME=mycert.pem
KEY_FILENAME=mycert.key
TARGET_URL=http://container
HOST_SERVER_NAME=domain
HOST_PORT=443

PROXY_CERT=$CERT_DIR:/cert

BLOCK=`cat << EOF

server { 
  listen *:443 ssl http2;
  include h5bp/ssl/ssl_engine.conf;
  server_name ${HOST_SERVER_NAME};
  ssl_certificate /cert/${CERT_FILENAME};
  ssl_certificate_key /cert/${KEY_FILENAME};
  location / {
    proxy_pass ${TARGET_URL};
    proxy_connect_timeout 60s;
    proxy_send_timeout 60s;
    proxy_read_timeout 60s;
  }
  include h5bp/ssl/policy_intermediate.conf;
  include h5bp/basic.conf;
  include h5bp/errors/custom_errors.conf;
  include h5bp/security/strict-transport-security.conf;
}

EOF`



if [ "$(which node)" == "" ]; then 
  
  # 本机没有 node,用 docker node 镜像,传入 BLOCK 环境变量再用 node 去掉换行符
  BLOCK=`docker run --rm --env BLOCK="${BLOCK}" node:alpine -e 'console.log( process.env.BLOCK.toString().split("\n").join("") )'`

else 
  
  # 本机有 node,打印 BLOCK,再传到 node 的 stdin 将 BLOCK 去掉换行符
  BLOCK=`echo $BLOCK | node -e 'console.log( require("fs").readFileSync(0).toString().split("\n").join("") )'`

fi


# 启动
docker run --rm --entrypoint /bin/sh -p "$HOST_PORT":443 -v "$PROXY_CERT" enix223/awesome-nginx:alpine -c 'echo "'"$BLOCK"'" > /etc/nginx/conf.d/443.conf && exec nginx -g "daemon off;"'

反向代理 TCP

替换:

参数 说明 示例
<对外端口> 映射到主机的端口 9660
<容器Host:Port> 容器主机名称和端口 container:9662
docker run --rm -p <对外端口>:10000 --entrypoint /bin/bash nginx:1.19.0 -c 'echo "stream{ server{ listen *:10000; proxy_pass <容器Host:Port>; } }" >> /etc/nginx/nginx.conf && exec nginx -g "daemon off;"'