Mac通过容器ip访问服务

背景

对于redis、kafka、rocketmq等中间件,进行服务注册时节点会自动从网卡获取ip,这会使得获取到虚拟网卡的容器内网ip,当我们的程序通过注册中心获取到注册的地址去访问服务时,mac和windows都无法正常访问容器内的服务。

原因

windows/mac上的docker desktop的实现并不与linux一致,容器实际上运行在一台轻量级虚拟机上,因此容器真实的宿主机是虚拟机而不是windows/mac本身,这样就导致我们的开发机器与容器不在一个网络中,网络不通。

解决办法

目前docker仍然没有解决该问题,因此无法直接通过docker的配置参数实现。

另辟蹊径🐛

在mac主机上,基本都是开发测试环境,在存在服务发现测试集群中,需要能够通过容器ip访问节点的能力。解决办法主要考虑两点,一个是ip通,一个是端口通。

  • ip

    主要思路是将容器的ip加入到lo0网卡,使得mac访问对应地址的时候会访问到localhost

  • port

    服务需要对外暴露端口,且暴露的端口与其在容器内的端口一致,比如6380:6380,这样需要修改服务的端口

通过以上操作,即可通过容器ip + 服务端口访问对应容器,可以使用如下脚本:

bash 复制代码
#!/bin/bash

# 配置
ALLOWED_NETS="^(172|10|192\.168)\."  # 允许绑定的 Docker 网段(正则)
LOCK_FILE="/tmp/docker_ip_manager.lock"  # 单例锁文件

### 清理函数:移除所有已绑定的 Docker IP
clean_aliases() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] 清理所有绑定的 Docker IP..."
    ifconfig lo0 | grep "inet " | awk '{print $2}' | while read -r ip; do
        if [[ "$ip" =~ $ALLOWED_NETS ]]; then
            sudo ifconfig lo0 -alias "$ip" 2>/dev/null && \
            echo "  ✅ 已移除: $ip"
        fi
    done
    exit 0
}

### 帮助信息
show_help() {
    echo "用法: $0 [选项]"
    echo "选项:"
    echo "  --clean   清理所有绑定的 Docker 容器 IP"
    echo "  --help    显示帮助信息"
    echo ""
    echo "默认模式:自动监控并绑定/解绑 Docker 容器 IP。"
    exit 0
}

### 检查是否已有脚本在运行
check_running() {
    if [ -f "$LOCK_FILE" ]; then
        echo "⚠️ 脚本已在运行(PID=$(cat "$LOCK_FILE")),请勿重复启动!"
        exit 1
    fi
    echo $$ > "$LOCK_FILE"
}

### 终止时清理锁文件
cleanup() {
    rm -f "$LOCK_FILE"
}
trap cleanup EXIT

### 获取当前 Docker 容器所有有效 IP
get_active_ips() {
    docker ps -q | xargs -n1 docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' 2>/dev/null | grep -E "$ALLOWED_NETS"
}

### 获取当前已绑定的 IP
get_bound_ips() {
    ifconfig lo0 | grep "inet " | awk '{print $2}' | grep -E "$ALLOWED_NETS"
}

### 主逻辑:智能绑定/解绑 IP
monitor_ips() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] 🚀 启动 Docker IP 自动管理..."
    while true; do
        active_ips=$(get_active_ips)
        bound_ips=$(get_bound_ips)

        ### 解绑失效的 IP(绑定存在但容器不在运行)
        for ip in $bound_ips; do
            if ! echo "$active_ips" | grep -q "^$ip$"; then
                sudo ifconfig lo0 -alias "$ip" 2>/dev/null && \
                echo "  🔄 解绑失效 IP: $ip"
            fi
        done

        ### 绑定新 IP(容器存在但未绑定)
        for ip in $active_ips; do
            if ! echo "$bound_ips" | grep -q "^$ip$"; then
                sudo ifconfig lo0 alias "$ip" 2>/dev/null && \
                echo "  🔄 绑定新 IP: $ip"
            fi
        done

        sleep 5  # 每 5 秒检测一次
    done
}

### 参数处理
case "$1" in
    --clean) clean_aliases ;;
    --help) show_help ;;
esac

### 检查 Docker 是否运行
if ! docker info >/dev/null 2>&1; then
    echo "❌ Docker 未运行!"
    exit 1
fi

### 主流程
check_running  # 确保单例运行
monitor_ips    # 进入 IP 自动管理

参考

github issue

相关推荐
weixin_462446232 小时前
使用 Python 脚本自动化管理 Docker 容器:启动、修改密码、删除及系统资源监控
python·docker·自动化·系统监控
溜达的大象3 小时前
Navidrome 打造专属无损音乐库,加载cpolar局域网外访问也能超丝滑
阿里云·docker·云原生·eureka
Wpa.wk4 小时前
Docker容器 - 了解Docker基础命令(容器+镜像命令)
运维·经验分享·测试工具·docker·容器
步菲5 小时前
Windows系统安装Docker Desktop配置daemon.json不生效问题解决
windows·docker·容器
sxy_97615 小时前
AX86u官方固件温度监控(CPU,WIFI芯片)
python·docker·curl·nc·nas·温度·ax86u
optimistic_chen6 小时前
【Docker入门】Docker Registry(镜像仓库)
linux·运维·服务器·docker·容器·镜像仓库·空间隔离
木卫二号Coding6 小时前
Docker-构建自己的Web-Linux系统-镜像kasmweb/ubuntu-jammy-desktop
linux·ubuntu·docker
加油vekiki6 小时前
linux服务器搭建docker、docker-compose
linux·服务器·docker·容器
JavaLearnerZGQ7 小时前
Docker安装ElasticSearch8.13.0、Kibana、中文分词器,版本
docker·中文分词·jenkins
亿牛云爬虫专家7 小时前
采集架构的三次升级:脚本、Docker 与 Kubernetes
爬虫·docker·架构·kubernetes·脚本·代理ip·采集