Docker 容器内没有互联网连接

Sas*_*nko 33 networking ubuntu docker

我无法在任何 Docker 容器内执行任何需要互联网连接的命令。

作品:

docker run ubuntu /bin/echo 'Hello world'
Run Code Online (Sandbox Code Playgroud)

不起作用:

docker run ubuntu apt-get update

Err:1 http://archive.ubuntu.com/ubuntu xenial InRelease
  Temporary failure resolving 'archive.ubuntu.com'
Err:2 http://archive.ubuntu.com/ubuntu xenial-updates InRelease
  Temporary failure resolving 'archive.ubuntu.com'
Err:3 http://archive.ubuntu.com/ubuntu xenial-security InRelease
  Temporary failure resolving 'archive.ubuntu.com'
Reading package lists...
W: Failed to fetch http://archive.ubuntu.com/ubuntu/dists/xenial/InRelease  Temporary failure resolving 'archive.ubuntu.com'
W: Failed to fetch http://archive.ubuntu.com/ubuntu/dists/xenial-updates/InRelease  Temporary failure resolving 'archive.ubuntu.com'
W: Failed to fetch http://archive.ubuntu.com/ubuntu/dists/xenial-security/InRelease  Temporary failure resolving 'archive.ubuntu.com'
Run Code Online (Sandbox Code Playgroud)

pip和类似ping

我在 Ubuntu 16.04 上,没有使用防火墙或公司代理服务器,并试图重新启动 Docker。

更新:

交互模式下的更新以同样的方式失败。

docker exec -ti angry_goodall /bin/bash
apt-get update
#fails
ping google.com
#fails with "unknown host" message
ping 8.8.8.8 
# shows PING 8.8.8.8 (8.8.8.8): 56 data bytes
# and than hangs indefinetly
Run Code Online (Sandbox Code Playgroud)

sudo apt-get update 在主机上成功运行,即在 docker 之外的我的计算机上。

更新Docker 版本 1.12.1,构建 23cf638

cod*_*mok 23

正如GitHub issue #866 for Docker 上creack所建议的:

pkill docker
iptables -t nat -F
ifconfig docker0 down
brctl delbr docker0
docker -d
Run Code Online (Sandbox Code Playgroud)

“它将强制 docker 重新创建网桥并重新初始化所有网络规则”

  • `-d` 标志不会退出。 (18认同)
  • 而不是只复制/过去命令,你可以解释这些是什么意思:) (9认同)
  • 嗨@LuísdeSousa 很遗憾你拒绝了这一点,但请考虑在较新版本中可能删除或更改某些开关的可能性。特别是因为这是一年多以前。 (3认同)
  • 我试过了,这会杀死我整个计算机上的网络。 (2认同)

Luí*_*usa 12

StackOverflow 上有一个类似的问题,在 Ubuntu 16.04 上,Docker 17.09使用不同的解决方案解决了这个问题:

检查内容resolv.conf

$ cat /etc/resolv.conf
Run Code Online (Sandbox Code Playgroud)

如果它包含类似的行,nameserver 127.0.1.1则表示容器正在获取不正确的名称服务器。要解决此问题,请编辑NetworkManager.conf文件:

$ sudo pico /etc/NetworkManager/NetworkManager.conf
Run Code Online (Sandbox Code Playgroud)

并用dns=dnsmasq;注释掉该行 该文件应如下所示:

[main]
plugins=ifupdown,keyfile,ofono
#dns=dnsmasq

[ifupdown]
managed=false
Run Code Online (Sandbox Code Playgroud)

最后,重启网络管理器:

$ sudo systemctl restart network-manager
Run Code Online (Sandbox Code Playgroud)

再次测试容器:

$ docker run ubuntu:16.04 apt-get update
Get:1 http://archive.ubuntu.com/ubuntu xenial InRelease [247 kB]
Get:2 http://archive.ubuntu.com/ubuntu xenial-updates InRelease [102 kB]
Run Code Online (Sandbox Code Playgroud)


wis*_*cky 8

我已经在这里回答了:https : //stackoverflow.com/a/45644890/

我复制下面的答案:

首先要检查的是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"]
     }  * Restart the docker daemon for those changes to take effect:      `sudo systemctl restart docker`
    
    Run Code Online (Sandbox Code Playgroud)
  • 现在,当您运行/启动容器时,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.confsudo 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 复制到容器中。


tos*_*osh 6

当您使用docker run未明确指定其网络 ( --network foo)创建容器时,docker 会将其连接到默认bridge网络。

默认bridge网络已被弃用(无法找到信息,来自哪个版本的 Docker Engine),应视为实现细节,不应使用。

但是,更重要的是,任何连接到默认bridge网络的容器都被禁止与外界联网 - 请参阅“用户定义的网桥和默认网桥之间的区别”

您可以向外界启用此类网络,但我不建议这样做。它要求您保留建议的主机配置更改,这可能不是您想要的。

解决方案很简单:只需创建您自己的(用户定义的)桥接网络,将其命名为,例如common,并在每个一次性容器中明确使用它docker run

$ docker network create --driver bridge common
$ docker run -it --network common ubuntu:latest bash
Run Code Online (Sandbox Code Playgroud)

  • 今天这就是答案 (2认同)
  • 我不敢相信 docker 将这个秘密隐藏得如此之好!人们不应该为了一个简单的问题(比如“在容器中获取互联网访问权限”)去挖掘谷歌结果第五页上的第四个SO答案。链接的文档“用户定义的网桥和默认网桥之间的差异”实际上并没有说明有关外部网络访问的任何内容。不过,该解决方案确实有效;这应该是公认的答案。有更好的参考吗? (2认同)