Docker容器獲(huo)取宿主機信息
最近在做產品授權的東西,開始宿主機為Window,程序獲取機器硬件信息相對簡單些,后來部署時發現各種各樣的的環境問題,所有后來改用dokcer部署,docker方式獲取宿主機信息時花了些時間,特此記錄一下
docker 獲取宿主機的信息
// dmidecode -t 4 | grep ID | tail -1 // CPUID // 系統(tong) // dmidecode -s system-serial-number // 查看系統序列號 // dmidecode -s system-uuid // 查看系統UUID // dmidecode -s system-product-name //查(cha)看服務(wu)器系統型(xing)號 // dmidecode -s processor-manufacturer | tail -1 // 處理器廠家(jia) // 主板(ban) // dmidecode -s baseboard-product-name // 主板型號 // dmidecode -s baseboard-serial-number // 主(zhu)板序(xu)列號(hao) // dmidecode -s baseboard-manufacturer // 主板廠家
實際項目(mu)當中,我獲(huo)取(qu)了CPUID、系統(tong)(tong)序(xu)列號、系統(tong)(tong)UUID、系統(tong)(tong)型號、處理器廠家,之所有獲(huo)取(qu)這么多信息標識(shi)機(ji)器,是考慮到有些(xie)信息在某些(xie)系統(tong)(tong)可(ke)能為空(kong),而且CPUID也不(bu)唯一了,所以就多獲(huo)取(qu)些(xie)。
調查下來,docker 獲取宿主機信息大體可以通過三種方式
- 通過環境變量由外部傳入容器內
-
使用掛載(zai)宿(su)主機目(mu)錄方(fang)式
- 在容器中使用ssh連接到主機
一:通過環境變量由外部傳入容器內
大體(ti)思路(lu)是docker 支(zhi)持通過-e來傳遞參(can)數(shu)到容器(qi)內部(bu)程序,就像安裝docker-mysql那(nei)樣密(mi)碼可(ke)以通過參(can)數(shu)傳遞一樣
- 在DockeFile中增加環境變量配置節點 (此步驟主要用來設置參數默認,也可以省略,通過其它方式設置)
- 在程序啟動時應用獲取程序變量并應用
- 在docker run 時通過-e參數傳遞到容器中
二:使用掛載宿主機目錄方式
確保宿主機能執行(xing)dmidecode命令(必須(xu))
將(jiang)宿主機的如下兩(liang)個目錄掛(gua)載到容器中
// dmidecode程(cheng)序的(de)目錄,如果(guo)不掛載那么容器中識別(bie)不了dmidecode命令 /usr/sbin/dmidecode或者/sbin/dmidecode // dmidecode調(diao)用時會(hui)使用到mem這個文件(jian),如果不掛(gua)載會(hui)找不到文件(jian) /dev/mem
在(zai)容(rong)器啟動(dong)時增(zeng)加 --privileged = true參數,讓容(rong)器獲得近(jin)似于宿主機root的權限
三:在容器中使用ssh連接到主機
思路(lu):在docker容器(qi)內安裝ssh,sshpass服務(wu),通過ssh連(lian)接到(dao)宿(su)主(zhu)機執行(xing)命令,獲 取宿(su)主(zhu)機信息(必(bi)須知道宿(su)主(zhu)機Ip和密(mi)碼)
步驟:
- 安裝服務 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 獲取設備信息幫助類
1 /// <summary> 2 /// 注(zhu)冊幫助類(lei) 3 /// </summary> 4 public class RegisterHelper 5 { 6 // 機(ji)器指紋字符串 7 private static string m_FingerPrintString = string.Empty; 8 9 /// <summary> 10 /// Get a string Unique Identification code of a computer 11 /// </summary> 12 /// <returns></returns> 13 public static string StringValue(string mac) 14 { 15 if (string.IsNullOrEmpty(m_FingerPrintString)) 16 { 17 m_FingerPrintString = "MAC >> " + mac + "\nCPU >> " + GetCpuId() + "\nBIOS >> " + GetBiosId() + "\nBASE >> " + GetBaseId() 18 + "\nDISK >> " + GetDiskId() + "\nVIDEO >> " + GetVideoId(); 19 } 20 return m_FingerPrintString; 21 } 22 23 /// <summary> 24 /// First enabled network card ID 25 /// </summary> 26 /// <returns></returns> 27 public static string GetMacId() 28 { 29 return Identifier("Win32_NetworkAdapterConfiguration", "MACAddress", "IPEnabled"); 30 } 31 32 /// <summary> 33 /// Get the cpuID 34 /// </summary> 35 /// <returns></returns> 36 private static string GetCpuId() 37 { 38 //Uses first CPU identifier available in order of preference 39 //Don't get all identifiers, as it is very time consuming 40 string retVal = Identifier("Win32_Processor", "UniqueId"); 41 if (string.IsNullOrEmpty(retVal)) //If no UniqueID, use ProcessorID 42 { 43 retVal = Identifier("Win32_Processor", "ProcessorId"); 44 if (string.IsNullOrEmpty(retVal)) //If no ProcessorId, use Name 45 { 46 retVal = Identifier("Win32_Processor", "Name"); 47 if (string.IsNullOrEmpty(retVal)) //If no Name, use Manufacturer 48 { 49 retVal = Identifier("Win32_Processor", "Manufacturer"); 50 } 51 //Add clock speed for extra security 52 retVal += Identifier("Win32_Processor", "MaxClockSpeed"); 53 } 54 } 55 return retVal; 56 } 57 58 /// <summary> 59 /// BIOS Identifier 60 /// </summary> 61 /// <returns></returns> 62 private static string GetBiosId() 63 { 64 return Identifier("Win32_BIOS", "Manufacturer") + " | " + Identifier("Win32_BIOS", "SMBIOSBIOSVersion") 65 + " | " + Identifier("Win32_BIOS", "IdentificationCode") + " | " + Identifier("Win32_BIOS", "SerialNumber") 66 + " | " + Identifier("Win32_BIOS", "ReleaseDate") + " | " + Identifier("Win32_BIOS", "Version") 67 + " | " + Identifier("Win32_BIOS", "Name"); 68 } 69 70 /// <summary> 71 /// Main physical hard drive ID 72 /// </summary> 73 /// <returns></returns> 74 private static string GetDiskId() 75 { 76 return Identifier("Win32_DiskDrive", "Model") + " | " + Identifier("Win32_DiskDrive", "SerialNumber") 77 + " | " + Identifier("Win32_DiskDrive", "Signature") + " | " + Identifier("Win32_DiskDrive", "TotalHeads"); 78 } 79 80 /// <summary> 81 /// Motherboard ID 82 /// </summary> 83 /// <returns></returns> 84 private static string GetBaseId() 85 { 86 return Identifier("Win32_BaseBoard", "Model") + " | " + Identifier("Win32_BaseBoard", "Manufacturer") 87 + " | " + Identifier("Win32_BaseBoard", "Name") + " | " + Identifier("Win32_BaseBoard", "SerialNumber") 88 + " | " + Identifier("Win32_BaseBoard", "SKU") + " | " + Identifier("Win32_BaseBoard", "Product"); 89 } 90 91 /// <summary> 92 /// Primary video controller ID 93 /// </summary> 94 /// <returns></returns> 95 private static string GetVideoId() 96 { 97 return Identifier("Win32_VideoController", "Name") + " | " + Identifier("Win32_VideoController", "AdapterRAM"); 98 } 99 100 /// <summary> 101 /// Return a hardware identifier 102 /// </summary> 103 /// <param name="wmiClass"></param> 104 /// <param name="wmiProperty"></param> 105 /// <returns></returns> 106 private static string Identifier(string wmiClass, string wmiProperty) 107 { 108 string result = string.Empty; 109 System.Management.ManagementClass mc = new System.Management.ManagementClass(wmiClass); 110 System.Management.ManagementObjectCollection moc = mc.GetInstances(); 111 foreach (System.Management.ManagementObject mo in moc) 112 { 113 //Only get the first one 114 if (string.IsNullOrEmpty(result)) 115 { 116 try 117 { 118 result = mo[wmiProperty]?.ToString(); 119 break; 120 } 121 catch(Exception e) 122 { 123 LogSingleton.CreateInstance().Error(e, "Window獲取硬件信息(xi)失(shi)敗"); 124 } 125 } 126 } 127 return result; 128 } 129 130 /// <summary> 131 /// Return a hardware identifier 132 /// </summary> 133 /// <param name="wmiClass"></param> 134 /// <param name="wmiProperty"></param> 135 /// <param name="wmiMustBeTrue"></param> 136 /// <returns></returns> 137 private static string Identifier(string wmiClass, string wmiProperty, string wmiMustBeTrue) 138 { 139 string result = string.Empty; 140 System.Management.ManagementClass mc = new System.Management.ManagementClass(wmiClass); 141 System.Management.ManagementObjectCollection moc = mc.GetInstances(); 142 foreach (System.Management.ManagementObject mo in moc) 143 { 144 if (mo[wmiMustBeTrue].ToString() == "True") 145 { 146 //Only get the first one 147 if (string.IsNullOrEmpty(result)) 148 { 149 try 150 { 151 result = mo[wmiProperty]?.ToString(); 152 break; 153 } 154 catch(Exception e) 155 { 156 LogSingleton.CreateInstance().Error(e,"Window獲取硬(ying)件信息(xi)失(shi)敗"); 157 } 158 } 159 } 160 } 161 return result; 162 } 163 }
Linux 獲取設備信息幫助類
1 public class LinuxHelper 2 { 3 4 // sudo dmidecode -t 4 | grep ID | tail -1 // CPUID 5 6 // 系統 7 // sudo dmidecode -s system-serial-number // 查看系統序(xu)列號 8 // sudo dmidecode -s system-uuid // 查看系統UUID 9 // sudo dmidecode -s system-product-name // 查看(kan)服務(wu)器系統型號 10 // sudo dmidecode -s processor-manufacturer | tail -1 // 處理器廠(chang)家 11 12 // 主板 13 // sudo dmidecode -s baseboard-product-name // 主板型號 14 // sudo dmidecode -s baseboard-serial-number // 主板序(xu)列號 15 // sudo dmidecode -s baseboard-manufacturer // 主(zhu)板(ban)廠家 16 17 /// <summary> 18 /// Get a string Unique Identification code of a computer 19 /// </summary> 20 /// <returns></returns> 21 public static string StringValue() 22 { 23 string cpuID = GetCpuId(); 24 string serialNumber = GetSerialNumber(); 25 string productName = GetProductName(); 26 string processorManufacturer = GetProcessorManufacturer(); 27 if (string.IsNullOrWhiteSpace(cpuID) && string.IsNullOrWhiteSpace(serialNumber) && string.IsNullOrWhiteSpace(productName) && string.IsNullOrWhiteSpace(processorManufacturer)) 28 { 29 return string.Empty; 30 } 31 return "CPU >> " + cpuID + "\nSerialNumber >> " + serialNumber + "\nProductName >> " + productName + "\nProcessorManufacturer >> " + processorManufacturer; 32 } 33 34 35 /// <summary> 36 /// Get the cpuID 37 /// </summary> 38 /// <returns></returns> 39 private static string GetCpuId() 40 { 41 return ProcessShell("dmidecode -t 4 | grep ID | tail -1"); 42 } 43 44 /// <summary> 45 /// SerialNumber 46 /// </summary> 47 /// <returns></returns> 48 private static string GetSerialNumber() 49 { 50 return ProcessShell("dmidecode -s system-serial-number"); 51 } 52 53 /// <summary> 54 /// product-name 55 /// </summary> 56 /// <returns></returns> 57 private static string GetProductName() 58 { 59 return ProcessShell("dmidecode -s system-product-name"); 60 } 61 62 /// <summary> 63 /// ProcessorManufacturer 64 /// </summary> 65 /// <returns></returns> 66 private static string GetProcessorManufacturer() 67 { 68 return ProcessShell("dmidecode -s processor-manufacturer | tail -1"); 69 } 70 71 /// <summary> 72 /// 執行Shell命令 73 /// </summary> 74 /// <param name="shellCmd"></param> 75 /// <returns></returns> 76 private static string ProcessShell(string shellCmd) 77 { 78 string result = string.Empty; 79 try 80 { 81 using Process process = new Process 82 { 83 StartInfo = new ProcessStartInfo("/bin/bash", "") 84 }; 85 process.StartInfo.RedirectStandardInput = true; 86 process.StartInfo.RedirectStandardOutput = true; 87 process.StartInfo.UseShellExecute = false; 88 process.Start(); 89 process.StandardInput.WriteLine(shellCmd); 90 process.StandardInput.Close(); 91 result = process.StandardOutput.ReadToEnd(); 92 process.WaitForExit(); 93 } 94 catch (Exception e) 95 { 96 LogSingleton.CreateInstance().Error(e, "Linux獲取硬件信息失敗"); 97 } 98 return result; 99 }
補充:方案二在實際測試中,發布在Ubuntu 22.04 TSL版本中獲取宿主機信息失敗。大致錯誤為找不到相關文件。
最終采取(qu)的(de)(de)方式為(wei)在容器中獲(huo)取(qu)授權(quan)服務容器的(de)(de)ID,以此(ci)作為(wei)唯一標(biao)識(具體采用(yong)哪種(zhong)方式看(kan)自(zi)己的(de)(de)實(shi)際(ji)應用(yong)環(huan)境)
關鍵代碼
1 /// <summary> 2 /// 獲取(qu)所有容器信息 3 /// </summary> 4 /// <returns></returns> 5 private static List<ContainerListResponse> GetContainerList() 6 { 7 string apiVersion = Environment.GetEnvironmentVariable("DockerApiVersin", EnvironmentVariableTarget.Process); 8 apiVersion = string.IsNullOrWhiteSpace(apiVersion) ? "1.37" : apiVersion; 9 string result = ProcessShell($"curl --unix-socket /var/run/docker.sock //172.17.0.1/v{apiVersion}/containers/json"); 10 return JsonConvert.DeserializeObject<List<ContainerListResponse>>(result); 11 }
1 IList<ContainerListResponse> containers = GetContainerList(); 2 ContainerListResponse containerListResponse = containers.FirstOrDefault(c => c.Names.Any(n => n.Contains("tuguan-server-license"))); 3 return containerListResponse?.ID;
// 目(mu)錄掛載(zai) -v /var/run/docker.sock:/var/run/docker.sock
參考信息 :
