如何从Node.js应用中获取Docker映射的端口?
获取Docker容器映射端口的Node.js实现思路
嘿,这个需求我之前刚好处理过,结合你已经挂载/var/run/docker.sock的前提,给你几个实用的解决办法:
思路1:直接调用Docker API(无额外依赖)
因为容器已经挂载了Docker套接字,我们可以直接在Node.js里请求本地Docker API来获取端口映射信息,不用额外安装包:
- 先获取当前容器的ID:
Linux环境下可以读取/proc/self/cgroup文件提取容器ID,也可以直接用容器的HOSTNAME环境变量(默认是容器ID的前12位)。
示例代码:const fs = require('fs'); function getContainerId() { try { const cgroupContent = fs.readFileSync('/proc/self/cgroup', 'utf8'); const match = cgroupContent.match(/docker\/([0-9a-f]{64}|[0-9a-f]{12})/); return match ? match[1] : process.env.HOSTNAME; } catch (err) { return process.env.HOSTNAME; } } - 调用API查询端口映射:
用Node.js内置的http模块请求Docker API,解析返回的容器信息拿到映射端口:const http = require('http'); async function getMappedPort(containerId, internalPort) { return new Promise((resolve, reject) => { const request = http.get({ socketPath: '/tmp/docker.sock', // 和你挂载的路径一致 path: `/containers/${containerId}/json` }, (res) => { let rawData = ''; res.on('data', chunk => rawData += chunk); res.on('end', () => { try { const containerInfo = JSON.parse(rawData); const portEntry = containerInfo.NetworkSettings.Ports[`${internalPort}/tcp`]; if (portEntry && portEntry.length) { resolve(portEntry[0].HostPort); } else { reject(new Error(`未找到${internalPort}对应的映射端口`)); } } catch (parseErr) { reject(parseErr); } }); }); request.on('error', reject); }); } // 实际使用 (async () => { const containerId = getContainerId(); const mappedPort = await getMappedPort(containerId, 80); console.log('当前容器的映射端口:', mappedPort); // 输出33962 })();
思路2:启动时传入环境变量(最简洁)
如果不想在代码里处理Docker相关逻辑,最直接的方式是在启动容器时把映射端口作为环境变量传入:
- 配合脚本传递端口:
写个简单的启动脚本,先启动容器,再获取映射端口注入到容器环境:# 启动容器 docker-compose up -d my-app # 获取80端口对应的宿主机端口 MAPPED_PORT=$(docker inspect --format '{{(index (index .NetworkSettings.Ports "80/tcp") 0).HostPort}}' my-app) # 把端口注入到容器环境(需确保容器支持动态设置环境变量,或重启容器时传入) docker-compose run --rm -e MAPPED_PORT=$MAPPED_PORT my-app - Node.js直接读取:
代码里不用任何额外逻辑,直接读取环境变量即可:
这个方式代码最简洁,但需要依赖启动脚本配合。const mappedPort = process.env.MAPPED_PORT; console.log('映射端口:', mappedPort);
思路3:使用官方Docker SDK(最优雅)
官方提供了dockerode这个npm包,封装了Docker API,用起来更顺手,代码可读性也更高:
- 安装依赖:
npm install dockerode - 示例代码:
这种方式代码结构清晰,维护起来更方便,适合在生产环境使用。const Docker = require('dockerode'); const fs = require('fs'); // 连接到挂载的Docker套接字 const docker = new Docker({ socketPath: '/tmp/docker.sock' }); function getContainerId() { try { const cgroupContent = fs.readFileSync('/proc/self/cgroup', 'utf8'); const match = cgroupContent.match(/docker\/([0-9a-f]+)/); return match ? match[1] : process.env.HOSTNAME; } catch (err) { return process.env.HOSTNAME; } } async function getMappedPort() { const containerId = getContainerId(); const container = docker.getContainer(containerId); const containerInfo = await container.inspect(); const portMapping = containerInfo.NetworkSettings.Ports['80/tcp']; return portMapping ? portMapping[0].HostPort : null; } // 使用示例 getMappedPort().then(port => console.log('映射端口:', port));
内容的提问来源于stack exchange,提问作者Niezborala
相关产品推荐
相关产品推荐

