在docker-compose服务中没有互联网

时间:2016-10-05 07:13:39

标签: docker docker-compose docker-networking

我无法通过docker-compose容器访问外部网络。

考虑以下docker-compose文件:

#!/bin/bash
for x in `ps -ef | awk '{ print $2 }' | grep -v PID`
do
    #----- do something -----
    echo $x
done

使用简单的version: '2' services: nginx: image: nginx 我设法访问外部IP或Internet IP(docker run -it nginx bash)。

另一方面,如果我使用docker-compose并附加到容器,我无法访问外部IP地址/ DNS。

码头信息:

ping www.google.com

docker-compose 1.8.1,build 878cff1

daemon.json文件:

Containers: 0
 Running: 0
 Paused: 0
 Stopped: 0
Images: 1
Server Version: 1.12.1
Storage Driver: aufs
 Root Dir: /var/lib/docker/aufs
 Backing Filesystem: extfs
 Dirs: 7
 Dirperm1 Supported: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
 Volume: local
 Network: bridge null host overlay
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Security Options: apparmor seccomp
Kernel Version: 4.4.0-38-generic
Operating System: Ubuntu 16.04.1 LTS
OSType: linux
Architecture: x86_64
CPUs: 2
Total Memory: 3.859 GiB
Name: ***
ID: ****
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Registry: https://index.docker.io/v1/
WARNING: No swap limit support
WARNING: bridge-nf-call-iptables is disabled
WARNING: bridge-nf-call-ip6tables is disabled
Insecure Registries:
 127.0.0.0/8

6 个答案:

答案 0 :(得分:5)

上次我遇到这样的问题时,我解决了这个问题:

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

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

它将强制docker重新创建网桥并重新启动所有网络规则。

至于为什么会发生这种情况的原因,我没有很好的答案。但我最近将问题追溯到journald。当我重新启动journald时(例如因为我更改了它的配置),docker-compose容器内的DNS解析一致/可重复地中断。我不知道为什么,我只能说这是一种可靠的方式让我在RHEL上重现它。

编辑 docker -d命令可能不适用于你所使用的docker版本,但不用担心,你可以省略该命令。

答案 1 :(得分:3)

检查/etc/default/docker以确保它没有以下行:

DOCKER_OPTS="--iptables=false"

同时检查/etc/docker/daemon.json以确保它没有以下密钥:

{
"iptables":false
}

我们在一台服务器上添加了这个以使UFW与docker一起工作。然后我们改为外部防火墙。花了很长时间寻找外部网络无法正常工作的原因,因为它已从我们的部署指南中删除。希望这有助于其他人。

答案 2 :(得分:1)

您提取的图片nginx默认情况下未安装ping。因此,如果您确实使用ping来测试连接,则必须先安装它。

我创建了一个自定义Dockerfile来安装它:

FROM nginx:latest
RUN apt update && apt -y install iputils-ping

然后我在本地构建并标记为mynginx

然后我更改了docker-compose.yml以使用自定义图片mynginx

version: '2'
services:
  nginx:
    image: mynginx

最后,我解雇了docker-compose up,并在其中做了一个docker exec,并测试了ping。一切都很好。我也做了docker run -ti ...并且它有效。

我的问题是,docker run如何为您提供与docker-compose up创建的行为不同的容器。

更清楚地了解如何检查互联网访问将会有所帮助。

答案 3 :(得分:0)

我刚遇到这个。使用 docker run -it <image> bash 运行任何容器,我可以执行任何我需要的与网络相关的操作,但是附加到通过 docker-compose 启动的容器并使用 docker exec -it <conatiner> bash 无法运行。甚至 apt-get 也会因“名称解析错误暂时失败”而失败。

我发现向每个服务添加 network_mode: "bridge" 会在每个容器中启用外部网络,代价是将所有内容附加到默认的 docker 网络。不过,我想保持堆栈隔离,因此着手寻找替代解决方案。

我运行 docker inspect network bridge 来查看默认网络,我的堆栈网络也是如此。我发现的唯一显着差异是子网/网关的差异(我认为这是意料之中的,但是列出的 IP 显着,192.* 与 172.*),以及默认网络有几个堆栈网络中不存在的选项:

"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"

我能够将它隔离到 "com.docker.network.bridge.default_bridge": "true",但是这破坏了堆栈外容器的网络,以至于我最终不得不完全删除并重新安装 docker。我假设 docker 守护进程与标记为默认的两个网络混淆,并且即使删除堆栈网络后也无法解决它。

这样做后我注意到的一件事是子网和 getway 与默认适配器仅相差一个。我确认删除上述选项会将子网和网关恢复到我最初看到的样子,它确实做到了。然后我在我的撰写文件中使用了这个网络配置:

networks:
  default:
    driver: "bridge"
    ipam:
      driver: default
      config:
        - subnet: X.X.0.0/16

其中子网的第一个值与默认网桥适配器相同,第二个值加一。这至少让一切正常,没有默认适配器仍然损坏。

有趣的是,当我去重新安装 docker 尝试修复默认网络时,我在查看 docker compose network documentation for external networking 后基本上运行了以下内容。

sudo snap remove docker
sudo sysctl net.ipv4.conf.all.forwarding=1
sudo iptables -P FORWARD ACCEPT
sudo snap install docker

随后删除了网络设置的 docker-compose up -d 会生成我之前定义的相同子网 IP,而没有为其提供配置。我认为潜在的问题很简单,因为某些东西阻止了 docker 守护进程正确找到可用的有效子网,一旦解决,一切都应该重新开箱即用。

答案 4 :(得分:0)

就我而言,我通过 snap 安装了 docker,按照 official website 中的说明将其删除并安装后,它开始正常工作。

答案 5 :(得分:-1)

Docker容器默认具有访问互联网的能力。 以下是我上周解决问题的方法:docker container can only access internet with net host

或者您只是让容器处于主机模式:

version: '2'
service:
  nginx:
    image: nginx
    network_mode: host

但正如@peedee在评论中指出的那样,这个解决方案将失去主机和容器之间的网络分离。