Docker容器获取宿主机信息

最近在做产品授权的东西,开始宿主机为Window,程序获取机器硬件信息相对简单些,后来部署时发现各种各样的的环境问题,所有后来改用dokcer部署,docker方式获取宿主机信息时花了些时间,特此记录一下
docker 获取宿主机的信息

// dmidecode -t 4 | grep ID | tail -1 // CPUID

    // 系统

    // dmidecode -s system-serial-number // 查看系统序列号

    // dmidecode -s system-uuid // 查看系统UUID

    // dmidecode -s system-product-name  //查看服务器系统型号

    // dmidecode -s processor-manufacturer | tail -1 // 处理器厂家

    
     // 主板

     // dmidecode -s baseboard-product-name // 主板型号

     // dmidecode -s baseboard-serial-number // 主板序列号

     // dmidecode -s baseboard-manufacturer // 主板厂家

实际项目当中,我获取了CPUID、系统序列号、系统UUID、系统型号、处理器厂家,之所有获取这么多信息标识机器,是考虑到有些信息在某些系统可能为空,而且CPUID也不唯一了,所以就多获取些。

调查下来,docker 获取宿主机信息大体可以通过三种方式

  • 通过环境变量由外部传入容器内
  • 使用挂载宿主机目录方式

  • 在容器中使用ssh连接到主机

一:通过环境变量由外部传入容器内

 大体思路是docker 支持通过-e来传递参数到容器内部程序,就像安装docker-mysql那样密码可以通过参数传递一样

  • 在DockeFile中增加环境变量配置节点 (此步骤主要用来设置参数默认,也可以省略,通过其它方式设置)
  • 在程序启动时应用获取程序变量并应用
  • 在docker run 时通过-e参数传递到容器中

二:使用挂载宿主机目录方式

         确保宿主机能执行dmidecode命令(必须)

        将宿主机的如下两个目录挂载到容器中

// dmidecode程序的目录,如果不挂载那么容器中识别不了dmidecode命令

  /usr/sbin/dmidecode或者/sbin/dmidecode

  // dmidecode调用时会使用到mem这个文件,如果不挂载会找不到文件

   /dev/mem

       

   在容器启动时增加 --privileged = true参数,让容器获得近似于宿主机root的权限

三:在容器中使用ssh连接到主机

思路:在docker容器内安装ssh,sshpass服务,通过ssh连接到宿主机执行命令,获 取宿主机信息(必须知道宿主机Ip和密码)

步骤:

  • 安装服务 yum -y install openssh-server
  • 修改配置 vim /etc/ssh/sshd_config PermitRootLogin的值修改为yes保存退出
  • 启动ssh服务 systemctl start sshd.service
  • 设置开机启动 systemctl enable sshd.service
  • 安装sshpass yum -y install sshpass

Window 获取设备信息帮助类

/// <summary>
    /// 注册帮助类
    /// </summary>
    public class RegisterHelper
    {
        // 机器指纹字符串
        private static string m_FingerPrintString = string.Empty;

        /// <summary>
        /// Get a string Unique Identification code of a computer
        /// </summary>
        /// <returns></returns>
        public static string StringValue(string mac)
        {
            if (string.IsNullOrEmpty(m_FingerPrintString))
            {
                m_FingerPrintString = "MAC >> " + mac + "\nCPU >> " + GetCpuId() + "\nBIOS >> " + GetBiosId() + "\nBASE >> " + GetBaseId()
                        + "\nDISK >> " + GetDiskId() + "\nVIDEO >> " + GetVideoId();
            }
            return m_FingerPrintString;
        }

        /// <summary>
        /// First enabled network card ID
        /// </summary>
        /// <returns></returns>
        public static string GetMacId()
        {
            return Identifier("Win32_NetworkAdapterConfiguration", "MACAddress", "IPEnabled");
        }

        /// <summary>
        /// Get the cpuID
        /// </summary>
        /// <returns></returns>
        private static string GetCpuId()
        {
            //Uses first CPU identifier available in order of preference
            //Don't get all identifiers, as it is very time consuming
            string retVal = Identifier("Win32_Processor", "UniqueId");
            if (string.IsNullOrEmpty(retVal)) //If no UniqueID, use ProcessorID
            {
                retVal = Identifier("Win32_Processor", "ProcessorId");
                if (string.IsNullOrEmpty(retVal)) //If no ProcessorId, use Name
                {
                    retVal = Identifier("Win32_Processor", "Name");
                    if (string.IsNullOrEmpty(retVal)) //If no Name, use Manufacturer
                    {
                        retVal = Identifier("Win32_Processor", "Manufacturer");
                    }
                    //Add clock speed for extra security
                    retVal += Identifier("Win32_Processor", "MaxClockSpeed");
                }
            }
            return retVal;
        }

        /// <summary>
        /// BIOS Identifier
        /// </summary>
        /// <returns></returns>
        private static string GetBiosId()
        {
            return Identifier("Win32_BIOS", "Manufacturer") + " | " + Identifier("Win32_BIOS", "SMBIOSBIOSVersion")
                + " | " + Identifier("Win32_BIOS", "IdentificationCode") + " | " + Identifier("Win32_BIOS", "SerialNumber")
                + " | " + Identifier("Win32_BIOS", "ReleaseDate") + " | " + Identifier("Win32_BIOS", "Version")
                + " | " + Identifier("Win32_BIOS", "Name");
        }

        /// <summary>
        /// Main physical hard drive ID
        /// </summary>
        /// <returns></returns>
        private static string GetDiskId()
        {
            return Identifier("Win32_DiskDrive", "Model") + " | " + Identifier("Win32_DiskDrive", "SerialNumber")
                + " | " + Identifier("Win32_DiskDrive", "Signature") + " | " + Identifier("Win32_DiskDrive", "TotalHeads");
        }

        /// <summary>
        /// Motherboard ID
        /// </summary>
        /// <returns></returns>
        private static string GetBaseId()
        {
            return Identifier("Win32_BaseBoard", "Model") + " | " + Identifier("Win32_BaseBoard", "Manufacturer")
                + " | " + Identifier("Win32_BaseBoard", "Name") + " | " + Identifier("Win32_BaseBoard", "SerialNumber")
                + " | " + Identifier("Win32_BaseBoard", "SKU") + " | " + Identifier("Win32_BaseBoard", "Product");
        }

        /// <summary>
        /// Primary video controller ID
        /// </summary>
        /// <returns></returns>
        private static string GetVideoId()
        {
            return Identifier("Win32_VideoController", "Name") + " | " + Identifier("Win32_VideoController", "AdapterRAM");
        }

        /// <summary>
        /// Return a hardware identifier
        /// </summary>
        /// <param name="wmiClass"></param>
        /// <param name="wmiProperty"></param>
        /// <returns></returns>
        private static string Identifier(string wmiClass, string wmiProperty)
        {
            string result = string.Empty;
            System.Management.ManagementClass mc = new System.Management.ManagementClass(wmiClass);
            System.Management.ManagementObjectCollection moc = mc.GetInstances();
            foreach (System.Management.ManagementObject mo in moc)
            {
                //Only get the first one
                if (string.IsNullOrEmpty(result))
                {
                    try
                    {
                        result = mo[wmiProperty]?.ToString();
                        break;
                    }
                    catch(Exception e)
                    {
                        LogSingleton.CreateInstance().Error(e, "Window获取硬件信息失败");
                    }
                }
            }
            return result;
        }

        /// <summary>
        /// Return a hardware identifier
        /// </summary>
        /// <param name="wmiClass"></param>
        /// <param name="wmiProperty"></param>
        /// <param name="wmiMustBeTrue"></param>
        /// <returns></returns>
        private static string Identifier(string wmiClass, string wmiProperty, string wmiMustBeTrue)
        {
            string result = string.Empty;
            System.Management.ManagementClass mc = new System.Management.ManagementClass(wmiClass);
            System.Management.ManagementObjectCollection moc = mc.GetInstances();
            foreach (System.Management.ManagementObject mo in moc)
            {
                if (mo[wmiMustBeTrue].ToString() == "True")
                {
                    //Only get the first one
                    if (string.IsNullOrEmpty(result))
                    {
                        try
                        {
                            result = mo[wmiProperty]?.ToString();
                            break;
                        }
                        catch(Exception e)
                        {
                            LogSingleton.CreateInstance().Error(e,"Window获取硬件信息失败");
                        }
                    }
                }
            }
            return result;
        }
    }

Linux 获取设备信息帮助类

public class LinuxHelper
    {

        // sudo dmidecode -t 4 | grep ID | tail -1               // CPUID

        // 系统
        // sudo dmidecode -s system-serial-number                // 查看系统序列号
        // sudo dmidecode -s system-uuid                         // 查看系统UUID
        // sudo dmidecode -s system-product-name                 // 查看服务器系统型号
        // sudo dmidecode -s processor-manufacturer | tail -1    // 处理器厂家

        // 主板
        // sudo dmidecode -s baseboard-product-name              // 主板型号
        // sudo dmidecode -s baseboard-serial-number             // 主板序列号
        // sudo dmidecode -s baseboard-manufacturer              // 主板厂家

        /// <summary>
        /// Get a string Unique Identification code of a computer
        /// </summary>
        /// <returns></returns>
        public static string StringValue()
        {
            string cpuID = GetCpuId();
            string serialNumber = GetSerialNumber();
            string productName = GetProductName();
            string processorManufacturer = GetProcessorManufacturer();
            if (string.IsNullOrWhiteSpace(cpuID) && string.IsNullOrWhiteSpace(serialNumber) && string.IsNullOrWhiteSpace(productName) && string.IsNullOrWhiteSpace(processorManufacturer))
            {
                return string.Empty;
            }
            return "CPU >> " + cpuID + "\nSerialNumber >> " + serialNumber + "\nProductName >> " + productName + "\nProcessorManufacturer >> " + processorManufacturer;
        }


        /// <summary>
        /// Get the cpuID
        /// </summary>
        /// <returns></returns>
        private static string GetCpuId()
        {
            return ProcessShell("dmidecode -t 4 | grep ID | tail -1");
        }

        /// <summary>
        /// SerialNumber
        /// </summary>
        /// <returns></returns>
        private static string GetSerialNumber()
        {
            return ProcessShell("dmidecode -s system-serial-number");
        }

        /// <summary>
        /// product-name
        /// </summary>
        /// <returns></returns>
        private static string GetProductName()
        {
            return ProcessShell("dmidecode -s system-product-name");
        }

        /// <summary>
        /// ProcessorManufacturer
        /// </summary>
        /// <returns></returns>
        private static string GetProcessorManufacturer()
        {
            return ProcessShell("dmidecode -s processor-manufacturer | tail -1");
        }

        /// <summary>
        ///  执行Shell命令
        /// </summary>
        /// <param name="shellCmd"></param>
        /// <returns></returns>
        private static string ProcessShell(string shellCmd)
        {
            string result = string.Empty;
            try
            {
                using Process process = new Process
                {
                    StartInfo = new ProcessStartInfo("/bin/bash", "")
                };
                process.StartInfo.RedirectStandardInput = true;
                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.UseShellExecute = false;
                process.Start();
                process.StandardInput.WriteLine(shellCmd);
                process.StandardInput.Close();
                result = process.StandardOutput.ReadToEnd();
                process.WaitForExit();
            }
            catch (Exception e)
            {
                LogSingleton.CreateInstance().Error(e, "Linux获取硬件信息失败");
            }
            return result;
        }

补充:方案二在实际测试中,发布在Ubuntu 22.04 TSL版本中获取宿主机信息失败。大致错误为找不到相关文件。

最终采取的方式为在容器中获取授权服务容器的ID,以此作为唯一标识(具体采用哪种方式看自己的实际应用环境)

关键代码

/// <summary>
        /// 获取所有容器信息
        /// </summary>
        /// <returns></returns>
        private static List<ContainerListResponse> GetContainerList()
        {
            string apiVersion = Environment.GetEnvironmentVariable("DockerApiVersin", EnvironmentVariableTarget.Process);
            apiVersion = string.IsNullOrWhiteSpace(apiVersion) ? "1.37" : apiVersion;
            string result = ProcessShell($"curl --unix-socket /var/run/docker.sock http://172.17.0.1/v{apiVersion}/containers/json");
            return JsonConvert.DeserializeObject<List<ContainerListResponse>>(result);
        }

参考信息 :docker容器中获取宿主机任意信息_容器内获取宿主机唯一标识的方法-CSDN博客

                   在docker容器中如何获取宿主机的机器信息?这样做一步到位_java docker 设备码-CSDN博客

### 如何在Docker容器获取宿主机IP地址 为了使Docker容器能够访问其宿主机的IP地址,可以采用多种方法实现这一目标。以下是几种常见的解决方案: #### 方法一:通过环境变量传递宿主机IP地址 当启动容器时,可以通过`--env`选项向容器内部注入宿主机的IP地址作为环境变量[^3]。例如,在Linux系统上运行以下命令: ```bash docker run --rm -it \ --env HOST_IP=$(ip route show | grep ^default | awk '{print $3}') \ ubuntu bash ``` 在此示例中,宿主机默认网关(通常是外部网络接口的IP地址)会被设置为名为`HOST_IP`的环境变量。 #### 方法二:利用特殊DNS名称 `host.docker.internal` 对于Mac OS X 和 Windows 平台上的 Docker Desktop 用户而言,官方提供了一个特殊的 DNS 名称——`host.docker.internal`,该名称始终解析到当前正在运行 Docker 的机器的 IP 地址[^1]。因此无需额外配置即可轻松连接回宿主机服务。 需要注意的是此功能仅适用于上述两种操作系统;如果是在 Linux 上部署,则需手动完成相应操作[^5]。 #### 方法三:绑定宿主机网络模式 (`--network="host"`) 另一种简单的方式就是让容器共享宿主机本身的网络栈而不是创建独立的新网络命名空间。这样做的好处在于容器可以直接使用宿主机的真实IP而不需要任何转换或代理层介入其中[^2]: ```bash docker run --rm -it --network="host" ubuntu ip addr show eth0 ``` 然而这种方法也有局限性,比如可能会破坏某些依赖于隔离性的应用程序行为逻辑等,所以在实际生产环境中应谨慎考虑是否适用这种做法[^4]。 #### 方法四:查询默认路由网关 最后一种通用的技术是从容器内部执行标准 shell 脚本来找出通往外界流量所经过的第一个跃点设备即所谓的“缺省网关”,这实际上也就是我们常说的那个虚拟桥接器(`docker0`)对应的IPv4数值形式表示出来而已: ```bash #!/bin/sh DEFAULT_GATEWAY=$(ip route | awk '/default/{print $3}') echo "$DEFAULT_GATEWAY" ``` 以上脚本片段展示了如何捕获并打印出默认网关的信息给终端用户查看。 --- ### 总结 综上所述,有四种主要途径可以帮助开发者解决从Docker容器内检索到所属物理机公网可达唯一标识符的问题。每种方式都有各自的特点以及适应场景,请根据具体需求选择最合适的方案加以实施应用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值