用 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 |
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;"'