一次centos Docker网桥模式无法访问宿主机Redis服务的故障排除经历

背景:

之前做了一个项目,需要在容器内访问宿主机提供的Redis 服务(这是一个比较常见的应用场景哈), 常规方案:

① 主机网络(docker run --network=host): 完全应用主机网络堆栈,在容器内localhost就是指向宿主机

② 网桥网络(docker run --network=bridge): 这也是docker容器默认的网络通信模式,容器内localhost 指向的是容器自身,不能使用 localhost 访问宿主机上localhost:6379承载的Redis服务 。

docker会默认建立docker0 网桥;

网桥有一个网关ip, 有一个子网段; 网桥内容器从子网段中确定容器ip( ip addr eth0), 网桥内容器可通过 service name相互访问;

网桥内容器通过 docker0 Getway得以访问外网。

不做骚操作,沿用常见的②网桥模式:

第一步:自定义网桥并应用该自定义网桥

docker network create --gateway 172.16.1.1 --subnet 172.16.1.0/24 app_bridge
docker run --network=app_bridge --name ......

# 以下截取自docker-compose.yml文件
......
networks:
 default:
 name: app_bridge
 external: true

为啥不利用默认docker0网桥?

本文开头已讲: docker0 是默认网桥,新建的容器默认都会加入这个网桥,所以我们需要建立一个专属于本程序的网桥app_bridge

第二步:容器内建立 对应于宿主机的别名

为实现在容器内网桥模式访问宿主机localhost:6379 的服务, 必须搭配docker 提供的 --add-host 选项(对应到docker-compose.yml这个配置是extra_host)。

docker run 的--add-host 选项能在 容器 /etc/hosts 文件增加行记录,便于我们使用该名称访问其他网络。

docker run -it --add-host dockerhost:172.16.1.1 ubuntu cat /etc/hosts
172.17.0.22 09d03f76bf2c
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
172.16.1.1 dockerhost

之后在程序的配置文件即可应用 dockerhost:6379 访问宿主机Redis服务。

------------------------------------------ 稍熟悉docker网络模型的朋友应该 都能理解并完成上述操作-----------------------------------------------------

一个状况:

我在公司CentOS7机器上使用上述操作, 容器内一直无法连通宿主机(容器间还是能正常访问)。

简化问题测试:新建容器,在容器内尝试ping docker0 网关, 哔了狗了,4台公司机器都ping不通docker0网关,外网还是正常访问。

那这个问题就成了: 使用默认的docker0网桥,容器内无法ping通docker0网关,进而无法访问宿主机。

呀呀呀呀, 八成是公司机器的配置问题 ~。。~

追问公司运维同学,发现:

Chain INPUT (policy DROP)

以上INPUT链的缺省策略是丢弃:从容器内访问宿主机的INPUT链规则并不匹配其中列出的任意一条,将被丢弃,所以我们从容器ping docker0网关会卡住收不到结果。

除非满足列出的INPUT链规则,否则缺省的策略就是丢弃。

后面还有转发和OUTPUT链缺省是 接受

这个策略的初衷是 服务器安全(尼玛, 导致容器访问宿主机的基础能力都没有了!!!)。

运维方案:

① 使用 sudo service iptables stop 关闭iptables

② 把要使用的网桥网段加入 INPUT链

sudo iptables -I INPUT -s 172.17.0.0/16 -j ACCEPT

【接受docker0子网段172.17.0.0/16 INPUT】 加入规则, 传送门

OK, That‘s All, 以后若有朋友在公司网络遇到 默认网桥容器内无法ping通网桥网关,进而无法访问宿主机,可参考本文排障。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对我们的支持。

(0)

相关推荐

  • Docker安装常用组件(mysql,redis)的方法

    docker安装mysql docker search mysql 搜索 docker pull mysql:5.6 下载 docker images |grep mysql 查看 docker run -p 3306:3306 --name mysql_docker -v $PWD/conf:/etc/mysql/conf.d -v $PWD/logs:/logs -v $PWD/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysq

  • docker创建redis镜像的方法

    本文介绍了docker创建redis镜像的方法,分享给大家,具体如下: 直接pull redis 镜像 创建redis的镜像有几种方式,可以直接从仓库中拉取. 首先说说docker的生命周期 1.docker的创建方式,有两种方式: 1)可以直接run ,跳过上面的步骤.举个栗子: 在构建镜像,要提供访问的端口,-p为端口映射的 1.创建并启动,设置端口映射 docker run -p 127.0.0.1:6379:6379 redis docker run 备注:docker run命令:重新

  • 详解docker搭建redis集群的环境搭建

    本文介绍了docker搭建redis集群的环境搭建,分享给大家,废话不多说,具体如下: 下载镜像 docker pull redis 准备配置文件 mkdir /home/docker/redis/ wget https://raw.githubusercontent.com/antirez/redis/3.0/redis.conf -O /home/docker/redis/redis.conf cd /home/docker/redis/ sed -i 's/# slaveof <maste

  • linux环境部署及docker安装redis的方法

    安装步骤 1. 安装Redis 通过docker search redis和docker pull redis下载redis镜像 2. 新建挂载配置文件夹 新建data和conf两个文件夹,位置随意. mkdir -p /root/docker/redis/data mkdir -p /root/docker/redis/conf 注:因为 redis 默认配置你会发现只能够本地连接,不能进行远程访问,使用 Redis Desktop Manager连接都会报错,因此需要手动挂载 redis 配

  • Ubuntu 搭建基于Docker的LNMP+Redis的开发环境(图文)

    Ubuntu 搭建基于Docker的LNMP+Redis的开发环境 服务器环境:Ubuntu 14.04 1.安装Docker 1.1 执行update命令,和服务器同步软件包,执行apt-get install * 时可以下载最新的软件. 1.2 安装Docker和创建软链接   1.3 启用Docker服务 2. 获取搭建环境所需镜像 2.1 MySQL镜像 2.2 Redis镜像   2.3 nginx-php-fpm镜像 2.4 查看已下载的镜像 对于Docker初学者来说,可以使用现有

  • 基于docker搭建redis-sentinel集群的方法示例

    1.概述 Redis 集群可以在一组 redis 节点之间实现高可用性和 sharding.在集群中会有 1 个 master 和多个 slave 节点.当 master 节点失效时,应选举出一个 slave 节点作为新的 master.然而 Redis 本身(包括它的很多客户端)没有实现自动故障发现并进行主备切换的能力,需要外部的监控方案来实现自动故障恢复. Redis Sentinel 是官方推荐的高可用性解决方案.它是 Redis 集群的监控管理工具,可以提供节点监控.通知.自动故障恢复和

  • Docker下redis的主从配置教程详解

    1.拉取redis镜像 docker pull redis 2.启动3个redis容器服务,分别使用到6379.6380.6381端口 docker run --name redis-6379 -p 6379:6379 -d redis docker run --name redis-6380 -p 6380:6379 -d redis docker run --name redis-6381 -p 6381:6379 -dredis 3.查看容器 [tcy@tcy1 ~]$ docker ps

  • Docker安装官方Redis镜像并启用密码认证

    参考:docker官方redis文档 1.有特殊版本需求的可以查看redis镜像tag版本 3.2.11, 3.2, 3 (3.2/Dockerfile) 3.2.11-32bit, 3.2-32bit, 3-32bit (3.2/32bit/Dockerfile) 3.2.11-alpine, 3.2-alpine, 3-alpine (3.2/alpine/Dockerfile) 4.0.9, 4.0, 4, latest (4.0/Dockerfile) 4.0.9-32bit, 4.0-

  • 一次centos Docker网桥模式无法访问宿主机Redis服务的故障排除经历

    背景: 之前做了一个项目,需要在容器内访问宿主机提供的Redis 服务(这是一个比较常见的应用场景哈), 常规方案: ① 主机网络(docker run --network=host): 完全应用主机网络堆栈,在容器内localhost就是指向宿主机 ② 网桥网络(docker run --network=bridge): 这也是docker容器默认的网络通信模式,容器内localhost 指向的是容器自身,不能使用 localhost 访问宿主机上localhost:6379承载的Redis服

  • docker容器访问宿主机的MySQL操作

    背景: 有一个flask项目提供接口,使用docker容器构建并且运行,MySQL在宿主机运行,需要在容器中可以让flask连接上宿主机的mysql 使用ifconfig命令可以看到,有一个docker0和eth0,在docker容器中可以通过eth0的IP地址加上端口号(3306)这样就可以连接上宿主机的MySQL了:另外,nginx可以通过docker0的IP地址加上构建容器时指定的端口号进行访问容器. 补充:docker的mysql容器运行正常,但是宿主机却连不上数据库,解决方法来啦 do

  • docker容器中无法获取宿主机hostname的解决方案

    在nodejs环境中测试通过,其它语言同理,只需要使用获取环境变量的方法即可. 思路: docker容器和宿主机环境是隔离的,但是可以在启动docker容器时将宿主机的主机名以环境变量的形式传入,代码在容器中获取该值即可. 操作: docker run -d -p 3000:3000 --name myTest -e HOST_Q=$(hostname) mytest:v1 # 使用-e 参数传入环境变量,值为主机名 如果使用yml文件启动: version: '3' services: mys

  • 在docker容器中调用和执行宿主机的docker操作

    首先这个帖子,献给docker新手.当然如果你是一个老手,文中分割线后的操作方法也是一种思路. 首先说一下,如何在docker中执行宿主机的docker操作,我们管它叫docker in docker. 至于为什么要在docker中操作宿主机的docker,优点不言而喻,你既可以将你的具体需求容器化部署,又不用直接在宿主机上安装(假设我们没有办法在docker中操作宿主机的docker,那么我们只能将这样的软件程序直接安装到宿主机上,这样显然是不利于管理和维护的). 实现这种需求,其实非常简单,

  • Docker 网络模式(四种)详细介绍

    Docker 网络模式 本文首先介绍了Docker自身的4种网络工作方式, Docker作为目前最火的轻量级容器技术,有很多令人称道的功能,如Docker的镜像管理.然而,Docker同样有着很多不完善的地方,网络方面就是Docker比较薄弱的部分.因此,我们有必要深入了解Docker的网络知识,以满足更高的网络需求. 四种网络模式 我们在使用docker run创建Docker容器时,可以用--net选项指定容器的网络模式,Docker有以下4种网络模式: · host模式,使用--net=h

  • Docker 网络模式及配置方式

    一.Docker网络模式 docker run 创建 Docker 容器时,可以用 –net 选项指定容器的网络模式,Docker 有以下 4 种网络模式: host 模式,使用 –net=host 指定. container 模式,使用 –net=container:NAME_or_ID 指定. none 模式,使用 –net=none 指定. bridge 模式,使用 –net=bridge 指定,默认设置. host 模式 如果启动容器的时候使用 host 模式,那么这个容器将不会获得一个

  • 轻松安装docker并运行docker swarm模式

    概要 docker 1.12版本最大的改变在于集成了docker swarm,在docker engine下提供了 swarm 模式,这里主要说一下docker swarm. docker engine本身只提供了容器技术,没有解决集群环境下的容器编排和通信.docker swarm是一个容器编排管理工具,docker-engine在1.12版本之后集成了docker swarm,不需要再单独安装. docker swarm的功能,举个例子,有3台机器都安装了docker环境,称为3台docke

  • Docker的安装方法及运行Docker Swarm模式的使用

    Docker简介 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化.容器是完全使用沙箱机制,相互之间不会有任何接口. 概要 docker就给简单介绍这么多,这里主要说说docker swarm. docker engine本身只提供了容器技术,没有解决集群环境下的容器编排和通信.docker swarm是一个容器编排管理工具,docker-engine在1.12版本之后集成了docker

  • Docker开启远程安全访问的图文教程详解

    一.编辑docker.service文件 vi /usr/lib/systemd/system/docker.service 找到 [Service] 节点,修改 ExecStart 属性,增加 -H tcp://0.0.0.0:2375 ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -H tcp://0.0.0.0:2375 这样相当于对外开放的是 2375 端口,当然也可以根据

  • Docker工作模式及原理详解

    如下图所示: 我们在使用虚拟机和docker的时候,就会出现这样一个疑问:Docker为什么比VM虚拟机快呢? 上面这张图就很客观的说明了这个问题 1.Docker有着比虚拟机更少的抽象层. 2.Docker利用的是宿主机的内核,VM需要的是Guest os. 所以说,新建一个容器的时候,docker不需要像虚拟机一样重新加载一个操作系统.虚拟机是加载Guest os(花费时间分钟级别),而docker利用的是宿主机的操作系统,省略了这个复杂的过程(花费时间秒级别). 搞清楚这些,我们再来看看对

随机推荐