业务请求量小的时候,我们会把一些工程部署到同一台机器上。 这些工程之间也会相互访问。 如果是http的接口, 我们最方便的是使用localhost带地本机的ip。不过结合docker容器后出现了问题。 docker容器中localhost表示容器的ip地址。不是宿主机ip。
其实Docker容器运行的时候有host、bridge、none三种网络可供配置。默认是bridge,即桥接网络,以桥接模式连接到宿主机;host是宿主网络,即与宿主机共用网络;none则表示无网络,容器将无法联网。
host
当容器使用host网络时,容器与宿主共用网络,这样就能在容器中访问宿主机网络,那么容器的localhost就是宿主机的localhost。
在docker中使用–network host来为容器配置host网络:
docker run -d --name nginx --network host nginx
如果使用了host就没有必要使用-p 80:80 -p 443:443来映射端口,是因为本身与宿主机共用了网络,容器中暴露端口等同于宿主机暴露端口。虽然通用性好。但是由于host网络没有bridge网络的隔离性好,使用host网络安全性不如bridge高。
bridge
使用桥接的方式我们可以通过参数把宿主机的ip传入到容器中
docker run -d --name nginx --env hostip="172.17.32.60"
先通过命令看看能不能在容器中取到传入的参数hostip
-
通过命令登入容器
# 666555444 是容器ip sudo docker exec -i -t 666555444 /bin/bash
-
在容器中执行命令获取参数
env|grep hostip
得到结果“hostip=10.10.10.10”
下面提供下程序中执行系统命令的方法
- java
java中执行带有管道符的命令需要使用exec中传入数组的方式执行
// cmd 可以传入 env|grep hostip
public static String run(String command) {
String result = "";
Scanner input = null;
Process process = null;
try {
process = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", command});
process.waitFor(2, TimeUnit.SECONDS);
input = new Scanner(process.getInputStream());
while (input.hasNextLine()) {
result += input.nextLine() + "\n";
}
} catch (Exception e) {
logger.error(e);
} finally {
if (input != null) {
input.close();
}
if (process != null) {
process.destroy();
}
}
return result;
}
- go
// cmd 可以传入 env|grep hostip
func Cmd(cmd string) []byte {
out, err := exec.Command("/bin/bash", "-c", cmd).Output()
if err != nil {
return nil
}
return out
}
从系统配合的角度推荐使用传入参数的方式获取系统ip
1. 安全性更好
2. 端口和ip或者其他的参数都交给运维,开发和运维解耦,当系统发生部署相关的变化的时候不需要开发关心。