Docker容器访问宿主机网络

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

<think> 我们参考用户的问题和提供的引用信息,用户希望让Docker容器能够访问宿主机上设置的域名。根据引用内容,有两种主要方法: 1. 使用`--net=host`参数:这样容器会直接使用宿主机网络,但这样会导致`-p`指定的端口映射无效,因为容器直接使用宿主机网络栈。 2. 使用`--add-host`参数:通过添加一个主机名映射,将宿主机的网关地址映射到一个特定的主机名(如`host.docker.internal`),这样容器就可以通过该主机名访问宿主机。 但是,引用[2]中提到的方法`--add-host=host.docker.internal:host-gateway`是Docker在较新版本中支持的特性(Docker Desktop for Mac/Windows和部分Linux版本)。在Linux上,`host-gateway`是一个特殊的值,会被替换为宿主机的IP地址(通常通过docker0网桥的网关地址,一般为172.17.0.1,但可能因配置而变化)。 因此,我们推荐使用第二种方法,因为它不需要改变容器网络模式,端口映射仍然有效。 具体步骤: 1. 在运行容器时,添加`--add-host`参数,将宿主机的网关地址映射到一个域名(如`host.docker.internal`): ``` docker run --add-host=host.docker.internal:host-gateway <其他参数> <镜像> ``` 这样,在容器内部就可以通过`host.docker.internal`这个主机名访问宿主机。 2. 在容器内部,访问宿主机上监听的端口时,使用`host.docker.internal`作为主机名。例如,宿主机上运行了一个Web服务在80端口,那么在容器内可以使用`http://host.docker.internal:80`来访问。 注意:这种方法要求Docker版本支持`host-gateway`(Docker v20.10及以上版本支持,Linux上需要配置)。对于旧版本的Docker,可能需要手动指定宿主机的IP地址。获取宿主机容器网络中的IP地址可以通过查看网关地址: - 在Linux上,通常可以通过`ip route show | grep docker0 | awk '{print $9}'`来获取(如果没有docker0,则查看默认网关),或者使用`hostname -I | awk '{print $1}'`获取宿主机的一个IP地址(但注意这个IP可能不在容器网络范围内,所以通常使用网关地址)。 如果使用旧版本Docker且不支持`host-gateway`,则可以手动指定IP: ``` docker run --add-host=host.docker.internal:<宿主机IP> <其他参数> <镜像> ``` 另外,引用[1]中提到了使用`--net=host`的方式,但这种方式会使容器共享宿主机网络命名空间,容器内直接使用宿主机的IP和端口,这样虽然可以访问宿主机,但同时也失去了网络隔离性,端口映射无效,且容器内服务可能会与宿主机端口冲突。 因此,我们推荐使用`--add-host`的方法,因为它更灵活且不影响其他网络配置。 总结: - 推荐使用`--add-host=host.docker.internal:host-gateway`来添加一个主机名映射。 - 在容器内部通过`host.docker.internal`访问宿主机。 注意事项:如果宿主机有防火墙设置,需要确保宿主机防火墙允许来自Docker容器网络的连接。 如果用户是在Mac或Windows上使用Docker Desktop,则默认已经支持`host.docker.internal`这个主机名,无需额外添加(但Linux需要显式添加)。 对于Linux系统,请确保Docker版本在20.10及以上。如果低于此版本,可以考虑升级,或者手动指定宿主机IP。 示例命令: docker run -it --add-host=host.docker.internal:host-gateway alpine sh 然后在容器内执行:`ping host.docker.internal` 应该能解析到宿主机的网关IP。 如果手动指定IP(例如宿主机docker0网桥上的IP为172.17.0.1): docker run -it --add-host=host.docker.internal:172.17.0.1 alpine sh 这样,容器就可以通过`host.docker.internal`访问宿主机的服务了。 相关问题: 1. 如何检查Docker容器网络配置? 2. 除了`--add-host`,还有哪些方法可以让Docker容器访问宿主机上的服务? 3. Docker容器如何访问宿主机的localhost? </think> ### Docker容器访问宿主机域名的解决方案 要让Docker容器访问宿主机上设置的域名,主要有以下两种解决方案: #### ✅ 方案1:使用 `--add-host` 参数映射域名(推荐) ```bash docker run --add-host=自定义域名:host-gateway <镜像名> ``` - **原理**:通过`host-gateway`自动解析宿主机IP(通常是`172.17.0.1`),并将其绑定到指定域名 - **示例**:宿主机有域名`api.local` ```bash docker run --add-host=api.local:host-gateway nginx ``` - **容器内验证**: ```bash ping api.local # 应返回宿主机IP curl http://api.local:端口 ``` - **优点**: - ✅ 端口映射(`-p`参数)仍然有效 - ✅ 网络隔离性完好 - ✅ 兼容Docker v20.10+(Linux/Mac/Windows通用)[^2] #### ⚠️ 方案2:使用 `--net=host` 共享网络(特定场景) ```bash docker run --net=host <镜像名> ``` - **原理**:容器直接共享宿主机网络栈 - **访问方式**:在容器内直接用`localhost`或宿主机域名访问 - **缺点**: - ❌ `-p` 端口映射失效 - ❌ 容器直接暴露在主机网络 - ❌ 安全风险(如容器服务占用主机端口)[^1] --- ### 📝 操作步骤示例 1. **查看宿主机域名配置** ```bash cat /etc/hosts # 假设有记录 192.168.1.100 api.local ``` 2. **启动容器并映射域名** ```bash docker run -it --add-host=api.local:host-gateway alpine sh ``` 3. **在容器内验证访问** ```bash ping api.local # 应返回宿主机IP curl http://api.local # 访问宿主机服务 ``` --- ### ⚠️ 注意事项 1. 宿主机防火墙需开放对应端口(如UFW): ```bash sudo ufw allow from 172.17.0.0/16 ``` 2. 旧版Docker(<v20.10)需手动指定IP: ```bash docker run --add-host=api.local:$(ip route | grep docker0 | awk '{print $9}') ... ``` 3. Windows/Mac无需特殊配置,默认支持`host.docker.internal`[^2] --- ### 📚 相关问题 1. Docker容器如何访问宿主机的MySQL数据库? 2. `--add-host`和`extra_hosts`在Docker Compose中如何配置? 3. 如何调试Docker容器宿主机网络连接问题? [^1]: 容器共享宿主机网络时端口映射失效机制 [^2]: `host-gateway`的跨平台支持原理
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值