业务请求量小的时候,我们会把一些工程部署到同一台机器上。 这些工程之间也会相互访问。 如果是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或者其他的参数都交给运维,开发和运维解耦,当系统发生部署相关的变化的时候不需要开发关心。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐