我的Docker容器没有互联网


139

我的工作正常,但现在停止了。我尝试了以下命令,但无济于事:

docker run -dns 8.8.8.8 base ping google.com

docker run base ping google.com

sysctl -w net.ipv4.ip_forward=1 -在主机和容器上

我所得到的是unknown host google.com。Docker 0.7.0版

有任何想法吗?

PS也ufw禁用


9
您的问题解决了我的问题:必须运行sysctl -w net.ipv4.ip_forward=1(在Centos 6上)
qwertzguy 2015年

因为你可能有搬运工人DNS路由问题,检查这个类似的解决方案stackoverflow.com/questions/35515203/...
阿迪亚Kresna酒店Permana

同样在这里,在我将/etc/resolv.conf固定在主机盒上之后,如果没有它,将无法正常工作sysctl -w net.ipv4.ip_forward=1
Reeebuuk

另外,还要确保你有正确的值/etc/resolv.conf主机
寒雪

为了我,sysctl -w net.ipv4.ip_forward=1我必须跑步sudo service docker restart
阿西夫·阿里

Answers:


100

首先要检查的是cat /etc/resolv.confdocker容器中运行。如果它具有无效的DNS服务器(例如)nameserver 127.0.x.x,则容器将无法将域名解析为IP地址,因此ping google.com将失败。

要检查的第二件事是cat /etc/resolv.conf主机上运行。基本上,/etc/resolv.conf每次启动容器时,Docker都会将主机的复制到容器中。因此,如果主机的/etc/resolv.conf错误,则Docker容器也会错误。

如果发现主机的/etc/resolv.conf错误,则有两种选择:

  1. 在daemon.json中将DNS服务器硬编码。这很容易,但是如果您希望更改DNS服务器,则不理想。

  2. 修复主机的/etc/resolv.conf。这有点棘手,但是它是动态生成的,并且您没有对DNS服务器进行硬编码。


1. docker daemon.json中的硬编码DNS服务器

  • 编辑 /etc/docker/daemon.json

    {
        "dns": ["10.1.2.3", "8.8.8.8"]
    }
    
  • 重新启动docker守护程序以使这些更改生效:
    sudo systemctl restart docker

  • 现在,当您运行/启动容器时,docker将/etc/resolv.conf使用中的值进行填充daemon.json


2.修复主机的 /etc/resolv.conf

A.Ubuntu 16.04和更早版本

  • 对于Ubuntu 16.04及更早版本,它/etc/resolv.conf是由NetworkManager动态生成的。

  • 注释掉行中dns=dnsmasq(带有#/etc/NetworkManager/NetworkManager.conf

  • 重新启动NetworkManager以重新生成/etc/resolv.conf
    sudo systemctl restart network-manager

  • 在主机上验证: cat /etc/resolv.conf

B.Ubuntu 18.04及更高版本

  • Ubuntu 18.04更改为用于systemd-resolved生成/etc/resolv.conf。现在默认情况下,它使用本地DNS缓存127.0.0.53。那将无法在容器内运行,因此Docker将默认使用Google的8.8.8.8 DNS服务器,这可能会使防火墙后面的人无法使用。

  • /etc/resolv.conf实际上是一个符号链接(ls -l /etc/resolv.conf),/run/systemd/resolve/stub-resolv.conf在Ubuntu 18.04中默认指向(127.0.0.53)。

  • 只需将符号链接更改为指向即可/run/systemd/resolve/resolv.conf,其中列出了真正的DNS服务器:
    sudo ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf

  • 在主机上验证: cat /etc/resolv.conf

现在您应该/etc/resolv.conf在主机上拥有一个有效的值,以便docker复制到容器中。


1
这就解决了Docker 17.09在Ubuntu 16.04上的问题。
路易·德·索萨

2
这解决了我的问题(与OP,Ubuntu 14.04 / Docker 18.01.0-ce相同)。如果您的Docker映像上没有ping命令,则此链接可用于测试Internet连接而无需ping。如果您的主机没有systemctl(Ubuntu 14.04),请尝试如何重新启动网络服务?和/或重新启动计算机。
本杰明

像魅力一样工作!
Homewrecker '18

1
这适用于Ubuntu 18.04(选项B)。但是docker并没有将现在的正确文件传输/etc/resolv.conf到构造中的容器,我不得不手动将文件复制到容器中。
glaux

1
在我的机器(RedHat 7.4)上,主机的配置文件正确,但是容器文件仍指向172.0.0.11。那么现在该怎么办?
Martin Majewski

90

遵循以下建议进行修复:

[...]您可以尝试重设所有内容吗?

pkill docker
iptables -t nat -F
ifconfig docker0 down
brctl delbr docker0
docker -d

它将迫使docker重新创建网桥并重新初始化所有网络规则

https://github.com/dotcloud/docker/issues/866#issuecomment-19218300

似乎接口以某种方式“挂起”。

更新以获取最新版本的Docker:

上面的答案可能仍然可以为您完成工作,但是距离发布此答案已经有很长的时间了,现在docker更完善了,因此请确保先尝试使用这些方法,然后再进行iptables其他操作。

sudo service docker restart 或(如果您使用的是不使用新贵的Linux发行版) sudo systemctl restart docker


31
docker -d失败。没有-d标志。
路易·德·索萨

1
对于那些仍然有问题的人,Moby的github上有一个公开的问题已经开放了一年多:github.com/moby/moby/issues/26567
Nepoxx,

1
@Pawan:ip link del docker0
drewrockshard '18年

1
或安装bridge-utils
cjdcordeiro

5
docker -d在较新版本中不存在。取而代之的是:service docker stop,然后dockerd,然后service docker start
Telmo Marques

64

重新启动docker的预期方式不是手动完成,而是使用serviceor init命令:

service docker restart

5
如果您使用的是不使用upstart的Linux发行版,那么sudo systemctl restart docker对我有用
jeffrey

重新启动工作正常。我不知道是否与“启用自动启动”有关(systemctl enable docker
Lucas Pottersky

似乎与OP的问题无关。
凯文·布克斯

之所以这样做,是因为在OP描述的情况下,重置docker会重新初始化网络接口,从而重新启用Internet访问。的确,这不能解决有时会中断的原因,但是可以解决此问题。
位掩码

但是在生产环境中,无法重新启动docker。如何解决此案的问题?
Suyanhanx

22

使用OSX的答案更新此问题(使用Docker Machine)

如果您正在使用Docker Machine在OSX上运行Docker,那么以下对我有用:

docker-machine restart

<...wait for it to restart, which takes up to a minute...>

docker-machine env
eval $(docker-machine env)

然后(至少以我的经验),如果您从容器中ping google.com,一切都会好起来的。


还可以在Windows中使用,以使网络访问再次起作用。
MikaelLepistö18年

1
那对我有用。我在顶部菜单栏中有一个docker-icon,在菜单中有一个“重新启动”选项。在那之后,网络又可以了
olidem'Oct18'18

8

我不知道自己在做什么,但对我有用:

OTHER_BRIDGE=br-xxxxx # this is the other random docker bridge (`ip addr` to find)    
service docker stop

ip link set dev $OTHER_BRIDGE down
ip link set dev docker0 down
ip link delete $OTHER_BRIDGE type bridge
ip link delete docker0 type bridge
service docker start && service docker stop

iptables -t nat -A POSTROUTING ! -o docker0 -s 172.17.0.0/16 -j MASQUERADE
iptables -t nat -A POSTROUTING ! -o docker0 -s 172.18.0.0/16 -j MASQUERADE

service docker start

2
漂亮的胶带!
dctremblay

1
您的回答有助于解决类似问题。我花了几个小时!在不完全安装Kubespray之后,Docker容器在尝试ping任何公共主机或IP时会丢失Internet,并显示消息“临时故障已解决”。所以我没有强制性的规则- iptables -t nat -A POSTROUTING ! -o docker0 -s 172.17.0.0/16 -j MASQUERADE。您可以通过iptables -t nat -L POSTROUTING
laimison '19

6

我正在使用DOCKER_OPTS="--dns 8.8.8.8",后来发现,我的容器无法直接访问Internet,但可以访问公司的Intranet。我更改DOCKER_OPTS为以下内容:

DOCKER_OPTS="--dns <internal_corporate_dns_address"

替换internal_corporate_dns_address为我们DNS的IP地址或FQDN并使用重新启动docker

sudo service docker restart

然后生成我的容器并检查它是否可以访问互联网。


5

当我的一个容器随机发生这种情况时,我感到难过,而其他容器都还好。容器已连接到至少一个非内部网络,因此Compose定义没有任何问题。重新启动VM / docker守护程序无济于事。这也不是DNS问题,因为容器甚至无法ping使用外部IP。为我解决的是重新创建docker网络。就我而言,docker-compose down && docker-compose up工作了。

撰写

这迫使重新创建所有容器的所有网络:

docker-compose down && docker-compose up

群模式

我想您只是删除并重新创建了服务,从而重新创建了服务的网络:

docker service rm some-service

docker service create ...

如果容器的网络是外部网络

只需删除并重新创建该服务的外部网络:

docker network rm some-external-network

docker network create some-external-network


4

对我来说,这是主机的防火墙。我必须允许主机防火墙上的DNS。并且还必须在更改主机防火墙设置后重新启动docker。


或者您可以通过sudo service iptables stop和禁用iptables sudo chkconfig iptables off(在CentOS / RHEL上)。
MichaelZ

4

缺少代理设置也不会导致Internet访问。在这种情况下,--network host也可能不起作用。可以通过设置环境变量http_proxy和配置代理https_proxy

docker run -e "http_proxy=YOUR-PROXY" \
           -e "https_proxy=YOUR-PROXY"\
           -e "no_proxy=localhost,127.0.0.1" ... 

不要忘记同时设置no_proxy,否则所有请求(包括对localhost的请求)都将通过代理。

详细信息:Archlinux Wiki中的代理设置


1
这是我的解决方案。不过要当心:我使用的是alpine,它具有wget的busybox实现,似乎忽略了代理设置,因此我没有看到设置环境变量的好处。
pelson

感谢您有关busybox的提示;我还不知道!
Simon A. Eugster

1
请注意,有些操作系统需要使用大写字母,例如在文档链接中
弗洛

3

对我来说,这是一个iptables转发规则。出于某种原因,以下规则与docker的iptables规则结合使用时,会导致来自容器的所有出站流量受到攻击localhost:8080

iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8080
iptables -t nat -I OUTPUT -p tcp -d 127.0.0.1 --dport 80 -j REDIRECT --to-ports 8080

3
那么...解决方案是什么?:)我有第一条规则,需要它将80上的入站流量重定向到8080。如何更改此规则以不影响出站流量?
mrooney

3

我在Ubuntu 18.04上遇到了问题。但是问题出在DNS上。我在一个拥有自己的DNS服务器并阻止其他DNS服务器的公司网络中。这是为了阻止某些网站(色情,山洪等等)

解决您的问题

  1. 在主机上找到您的DNS
  2. 按照@jobin的建议使用--dns your_dns

    docker run --dns your_dns -it --name cowsay --hostname cowsay debian bash


2

在Windows(8.1)上,我(通过taskmgr)杀死了virtualbox接口,它解决了这个问题。


2

您可能已经使用dns选项启动了docker --dns 172.x.x.x

我有同样的错误,并从中删除了选项 /etc/default/docker

这些行:

# Use DOCKER_OPTS to modify the daemon startup options.
DOCKER_OPTS="--dns 172.x.x.x"

2

对于使用针对VPN的openconnect 8.3的Ubuntu 19.04,我不得不将/etc/resolve.conf符号链接到systemd中的那个(与wisbucky对应的答案相反)

sudo ln -sf /etc/resolv.conf /run/systemd/resolve/resolv.conf

调试步骤

  1. 连接到公司VPN
  2. 在/etc/resolv.conf或/run/systemd/resolve/resolv.conf中查找正确的VPN设置
  3. 无论哪个DNS设置正确,我们都会将其符号链接到另一个文件(提示:将一个带有正确设置的文件放在任务左侧)

Docker版本:Docker版本19.03.0-rc2,内部版本f97efcc


2
谢谢。使用Ubuntu 18.04,在连接到公司VPN时,仅/etc/resolve.conf被DHCP更新,并且/ run / systemd / resolve / resolve / conf保持不变/静态。该解决方案有所帮助。现在,本地计算机中的容器已连接到VPN中的服务器(这对我来说不是很早)
dexter2305

1

如果您使用的是OSX,则在安装Docker之后可能需要重新启动计算机。有时这是一个问题。


1

最初,我的docker容器能够访问外部互联网(这是在Amazon EC2上运行的docker服务/容器)。

由于我的应用程序是API,因此我在创建容器(成功提取了所需的所有软件包)之后,更新了IP表,将所有流量从端口80路由到我的API(在docker上运行)所在的端口听着。

然后,稍后我尝试重建容器时失败了。经过艰苦的努力,我发现我的上一步(设置IPTable端口转发规则)弄乱了Docker的外部网络功能。

解决方案:停止IPTable服务:

sudo service iptables stop

重新启动Docker守护程序:

sudo service docker restart

然后,尝试重建您的容器。希望这可以帮助。


跟进

我完全忽略了我不需要弄乱IP表来将传入流量转发到80到运行docker的API运行的端口。相反,我只是将端口80别名为docker中的API运行于的端口:

docker run -d -p 80:<api_port> <image>:<tag> <command to start api>


1

如果有人在运行docker的virtualbox容器中遇到此问题,只需在此处添加即可。我将virtualbox网络重新配置为桥接而不是nat,问题消失了。


1

对我来说,我的问题是因为未安装iptables-services,这对我有用(CentOS):

sudo yum install iptables-services
sudo service docker restart

记得开始并启用iptable的服务太
周杰伦


0

在尝试在Ubuntu上使用Docker-Compose设置项目时,我也遇到了此类问题。

当我尝试ping任何IP地址或nslookup一些URL时,Docker根本无法访问互联网-它一直都失败。

我尝试了上述所有可用的DNS解析解决方案,但均无济于事。

我花了一整天的时间来弄清楚到底是怎么回事,最后才发现造成所有麻烦的原因是防病毒软件,尤其是防火墙,由于某种原因,防火墙阻止了Docker获取IP地址和端口。

当我禁用它时-一切正常。

因此,如果您安装了防病毒软件,却无助于解决问题,则可能是该防病毒软件的防火墙。


0

最近几天,我遇到了类似的问题。对我来说,原因是systemd,docker和我的托管服务提供商的结合。我正在运行最新的CentOS(7.7.1908)。

我的托管服务提供商会自动为systemd-networkd生成一个配置文件。从systemd 219(它是CentOS 7的当前版本)开始,systemd-networkd控制了与网络相关的sysctl参数。Docker似乎与此版本不兼容,并且每次启动容器时都会重置IP转发标志。

我的解决方案是IPForward=true[Network]提供程序生成的配置文件的-section中添加。该文件可能位于多个位置,最可能位于/etc/systemd/network

官方Docker文档中也描述了该过程:https : //docs.docker.com/v17.09/engine/installation/linux/linux-postinstall/#ip-forwarding-problems


您能否指定设置此参数的确切位置?我的位置与您完全相同,并且在Google Cloud Platform上运行VM,并且在服务器上找不到任何* .network文件。仅打开,/usr/lib/sysctl.d/50-default.conf但语法不同。
el.severo

我的群集是自我管理的,提供程序仅在设置时进行基本引导。网络配置/etc/systemd/network/10-mainif.network适合我。您可能要检查的其他地方是/usr/local/lib/systemd/并且/usr/lib/systemd/根据systemd联机帮助页。
BlackCetha

0

对我而言,使用centos 7.4,它不是/etc/resolve.conf、iptables、iptables nat规则或docker本身的问题。问题是主机缺少软件包bridge-utils,这是docker使用brctl命令构建桥所需要的。yum install -y bridge-utils并重新启动docker,解决问题。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.