Docker的网络模式
文章初衷:
## 在网上扒了一些文章,驴头不对马嘴,废话一堆,浪费时间,索性自己沉下心来,实现一下,分享出来给大家节省时间 ##
这里我们不详细探讨其网络模式,只说问题解决方案:
详细可参考:Docker容器之网络模式
host模式
容器不会虚拟出自己网卡,配置自己的主机ip等,而是使用宿主机的ip和端口
- container模式
创建的容器不回创建自己的网卡,配置自己的ip,而是和一个指定的容器共享ip、端口的范围 - none模式
该模式关闭了容器的网络功能 - bridge模式
默认为该模式,桥接,此模式会为每一个容器分配,设置ip等,并将容器连接到一个docker0的虚拟网桥,在通过docker0网段以及iptables nat表配置与宿主机通信
本案例主要讲解Docker - - bridge网络模式下,容器内部获取宿主机网卡ip的方式
案例说明:
说明:docker-compose + bridge 模式 + java (宿主机是centos7,其他系统未测试)
注意:下面案例获取的是网卡列表中的第一个
这里因为要在容器中获取宿主机的配置,所以要把这部分的宿主机配置挂载到容器中
volumes:
- /proc:/host/proc
docker-compose.yml
version: '3'
services:
stone-system:
image: stone-system:${TAG}
container_name: stone-system
environment:
- TZ=Asia/Shanghai
volumes:
- /proc:/host/proc
privileged: true
restart: always
pid: "host"
command:
- --spring.profiles.active=${PROFILE}
networks:
- stone_net
networks:
stone_net:
driver: bridge
ipam:
config:
- subnet: 172.30.0.0/16
java代码
@GetMapping("/test/q4")
public void test4() {
String os = System.getProperty("os.name");
if(!os.toLowerCase().startsWith("win")){
getLinuxLocalIP();
}else {
getWinLocalIP();
}
}
private static String getWinLocalIP() {
String hostAddress = "127.0.0.1";
try {
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
NetworkInterface ni = interfaces.nextElement();
if (ni.isLoopback() || ni.isVirtual() || !ni.isUp()) {
continue;
}
Enumeration<InetAddress> addresses = ni.getInetAddresses();
while (addresses.hasMoreElements()) {
InetAddress addr = addresses.nextElement();
hostAddress = addr.getHostAddress();
if (addr.isLinkLocalAddress() || addr.isLoopbackAddress() || addr.isMulticastAddress()) {
continue;
}
return hostAddress;
}
}
} catch (SocketException e) {
e.printStackTrace();
}
return hostAddress;
}
private static String getLinuxLocalIP() {
String ipAddress = "127.0.0.1";
// 构造命令,获取所有网卡信息,并使用grep命令过滤掉docker、veth和br-等虚拟网卡,并过滤掉状态不为up的网卡
// String command = "ip addr show | grep -v docker | grep -v veth | grep -v br- | grep 'state UP'";
String command = "nsenter --mount=/host/proc/1/ns/mnt --net=/host/proc/1/ns/net ip addr";
String c1 = command + " | grep -v docker | grep -v br- | grep -v veth | grep 'state UP'";
try {
// 执行命令并获取结果
Process process = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", c1});
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
StringBuilder output = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
output.append(line).append("\n");
}
String ipOutput = output.toString();
// 使用awk命令提取出物理网卡的名称,并输出第一个物理网卡的IP地址
String physicalNic = executeCommand("echo \"" + ipOutput + "\" | awk '/^[0-9]/ { print $2 }' | sed 's/://' | head -n 1");
System.out.println("physicalNic: ========" + physicalNic);
ipAddress = executeCommand(command + " show dev " + physicalNic + " | grep \"inet \" | awk '{print $2}' | cut -d '/' -f 1");
System.out.println("ipAddress: =========" + ipAddress);
} catch (IOException e) {
e.printStackTrace();
}
return ipAddress;
}
/**
* 执行指定的命令并返回结果
*/
private static String executeCommand(String command) throws IOException {
Process process = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", command});
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
StringBuilder output = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
output.append(line).append("\n");
}
return output.toString().trim();
}