You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从Node.js应用中获取Docker映射的端口?

获取Docker容器映射端口的Node.js实现思路

嘿,这个需求我之前刚好处理过,结合你已经挂载/var/run/docker.sock的前提,给你几个实用的解决办法:

思路1:直接调用Docker API(无额外依赖)

因为容器已经挂载了Docker套接字,我们可以直接在Node.js里请求本地Docker API来获取端口映射信息,不用额外安装包:

  1. 先获取当前容器的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;
      }
    }
    
  2. 调用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相关逻辑,最直接的方式是在启动容器时把映射端口作为环境变量传入:

  1. 配合脚本传递端口:
    写个简单的启动脚本,先启动容器,再获取映射端口注入到容器环境:
    # 启动容器
    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
    
  2. Node.js直接读取:
    代码里不用任何额外逻辑,直接读取环境变量即可:
    const mappedPort = process.env.MAPPED_PORT;
    console.log('映射端口:', mappedPort);
    
    这个方式代码最简洁,但需要依赖启动脚本配合。

思路3:使用官方Docker SDK(最优雅)

官方提供了dockerode这个npm包,封装了Docker API,用起来更顺手,代码可读性也更高:

  1. 安装依赖:
    npm install dockerode
    
  2. 示例代码:
    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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:46:17