如何在宿主机上ping我的docker容器

56

我已经在我的Mac上创建了一个Ubuntu Docker容器。

CONTAINER ID  IMAGE   COMMAND      CREATED         STATUS         PORTS                 NAMES
5d993a622d23  ubuntu  "/bin/bash"  42 minutes ago  Up 42 minutes  0.0.0.0:123->123/tcp  kickass_ptolemy

我将端口设置为123。

我的容器IP是172.17.0.2

docker inspect 5d993a622d23 | grep IP
"LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "IPAddress": "172.17.0.2",
            "IPPrefixLen": 16,
            "IPv6Gateway": "",
                    "IPAMConfig": null,
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,

在我的Mac上,我尝试ping我的容器,

Ping 172.17.0.2,我得到了“Request timeout for icmp_seq 0”的错误信息……

我该怎么办?让我的本地机器能够ping通我安装的容器。我是否错过了容器中某些应用程序的安装,因为它只是一个裸的Ubuntu系统?


Docker for Mac 还是 Docker Toolbox? - Matt
你应该提及你正在使用的Ubuntu版本和Docker版本。此外,你是否查看了适用于你的Docker版本的Docker网络文档? - Mark Stosberg
Docker for Mac,Docker 1.12.1,Ubuntu 11.10 - Neil
6个回答

41

在Docker for Mac中,您无法直接ping或访问容器接口

目前最佳解决方案是从另一个容器连接到您的容器。目前,由于苹果尚未解决的OSX问题,我们无法为这些容器提供路由。我们正在跟踪这个需求,但目前我们无法做任何事情。

lima

Lima可以通过socket_vmnet在虚拟机上添加主机可访问的接口(现在是2023年,lima在rancher/podman桌面中使用)

# Install
brew install lima socket_vmnet

# Customise the `shared` network if required. 
vi ~/.lima/_config/networks.yaml

# Set up the sudoers file for launching `socket_vmnet` from Lima
limactl sudoers >etc_sudoers.d_lima
sudo install -o root etc_sudoers.d_lima /etc/sudoers.d/lima

# Create a containerd VM on the `shared` network
echo | limactl start \
  --network lima:shared \
  --vm-type vz \
  --mount-type virtiofs \
  --set '.containerd.system = true | .containerd.user = false' \
  template://debian-12

# You may want to add this ip/mac address to /etc/bootptab
# so the IP address remains consistent on this VM. 
lima ip -j address show lima0 \
 | jq -r '.[0] as $if
    | "lima  1  \($if.address)  \($if.addr_info[] |select(.family == "inet") |.local)"'

# Setup network and route
lima sudo nerdctl network create ctr01 --subnet 10.2.3.0/24
sudo /sbin/route add 10.2.3.0/24 192.168.105.3 # or configured networks.yaml

# Test
lima sudo nerdctl run --detach --net ctr01 --ip 10.2.3.3 nginx
ping -c 2 10.2.3.3
curl http://10.2.3.3

Docker Toolbox/VirtualBox

在运行Docker Toolbox时,通过VirtualBox或任何VirtualBox虚拟机(如Vagrant定义)运行Docker Machine,您可以设置一个"Host-Only Network"并通过它访问Docker虚拟机的网络。

如果您正在使用default的boot2docker虚拟机,请不要更改现有的接口,因为这将导致许多Docker实用程序停止工作,请添加一个新的接口。

您还需要设置从您的Mac到容器网络的路由,通过您的虚拟机的新IP地址。在我的情况下,Docker网络范围是172.22.0.0/16,虚拟机上的Host Only适配器IP是192.168.99.100

sudo route add 172.22.0.0/16 192.168.99.100

添加一个永久路由到osx有点复杂
然后你就可以从你的Mac访问容器了
machost:~ ping -c 1 172.22.0.2
PING 172.22.0.2 (172.22.0.2): 56 data bytes
64 bytes from 172.22.0.2: icmp_seq=0 ttl=63 time=0.364 ms

--- 172.22.0.2 ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.364/0.364/0.364/0.000 ms

Vagrant + Ansible 设置

这是我的运行配置...

Vagrant.configure("2") do |config|
  config.vm.box = "debian/contrib-buster64"
  config.vm.hostname = "docker"
  config.vm.network "private_network", ip: "10.7.7.7", hostname: true
  config.vm.provider "virtualbox" do |vb|
    vb.gui = false
    vb.memory = "4000"
    vb.cpus = "4"
  end
  config.vm.provision "ansible" do |ansible|
    ansible.verbose = "v"
    ansible.playbook = "tasks.yaml"
  end
end

ansible的tasks.yaml用于配置固定网络。
- hosts: all
  become: yes
  vars:
    ansible_python_interpreter: auto_silent
    docker_config:
      bip: 10.7.2.1/23
      host: ["tcp://10.7.7.7:2375"]
      userland-proxy: false
  tasks:

  - ansible.builtin.apt:
      update_cache: yes
      force_apt_get: yes
      pkg:
      - bridge-utils
      - docker.io
      - python3-docker
      - python-docker
      - iptables-persistent

  - ansible.builtin.hostname:
      name: docker

  - ansible.builtin.copy:
      content: "{{ docker_config | to_json }}"
      dest: /etc/docker/daemon.json

  - ansible.builtin.lineinfile:
      line: 'DOCKER_OPTS="{% for host in docker_config.host %} -H {{ host }} {% endfor %}"'
      regexp: '^DOCKER_OPTS='
      path: /etc/default/docker

  - ansible.builtin.systemd:
      name: docker.service
      state: restarted
  
  - ansible.builtin.iptables:
      action: insert
      chain: DOCKER-USER
      destination: 10.7.2.0/23
      in_interface: eth1
      out_interface: docker0
      jump: ACCEPT
  - ansible.builtin.shell: iptables-save > /etc/iptables/rules.v4

将docker桥接网络的路由添加到虚拟机上,以便通过mac进行通信。
$ sudo /sbin/route -n -v add -net 10.7.2.0/23 10.7.7.7

然后在环境中设置DOCKER_HOST=10.7.7.7以使用新的虚拟机。
$ export DOCKER_HOST=10.7.7.7 
$ docker run --name route_test --rm -d node:14-slim node -e "require('http').createServer((req, res) => {
 res.writeHead(200, {'Content-Type':'text/plain'})
 res.end('hello')
}).listen(3000)"
$ docker container inspect route_test -f '{{ .NetworkSettings.Networks.bridge.IPAddress }}'
$ curl http://10.7.2.3:3000
hello
$ docker rm -f route_test

你不会得到从主机映射到虚拟机的卷,但作为一个额外的好处,它使用的CPU比Docker 2.5.x版本少得多。

我如何在我的机器上找到Docker网络范围172.22.0.0/16?我如何在我的机器上找到VM 192.168.99.100的Host Only适配器IP?在提问中,他使用了172.17.0.2,这有什么关系?损坏的链接... - powder366
@powder366 Docker网络范围位于虚拟机上。无论是在Docker for Mac的moby VM上还是其他任何VM平台上运行,都可以在VM终端上使用“ip ad sh”命令列出IP地址。 - Matt
这个说法“在Docker for Mac中无法直接ping或访问容器接口”仍然正确吗?如果不是,我该如何获取我的Docker容器的外部IP(我正在使用docker compose)? - BonisTech
@BonisTech 这是 Docker 使用的 Mac 虚拟化框架的限制,我相信现在仍然存在。解决方法是在 Mac 和虚拟机上添加一个隧道设备,例如 WireGuard 连接,以弥补差距。 - Matt

6
作为替代方案,如果您的容器已经集成了bash shell,您可以通过以下方式访问它:docker exec -it <CONTAINER ID> bash,然后您就可以ping您的虚拟IP。

5

在这种情况下它可以工作:

  1. Windows主机
  2. 安装在Windows主机上的Linux VM
  3. 安装在Linux VM主机上的Docker容器

现在你必须注意这一点。容器处于隔离网络中,但通过Docker容器主机适配器连接到互联网。因此,您需要告诉Linux内核在您的网络中可用,然后在您的Linux VM中进行设置:

# sysctl net.ipv4.conf.all.forwarding=1
# sudo iptables -P FORWARD ACCEPT

现在,在您的Windows主机上,您需要为我们的容器网络添加一条路由:

例如:route add "Docker container network" "Linux VM IP"

这样可以帮助您更好地使用IT技术。

# route add 172.17.0.0/16 192.168.1.20

这正是我的设置,这个答案对我有用。在iptables中的关键更改是将FORWARD链中的(policy DROP)更改为(policy ACCEPT) - Pickett
现在在你的Windows主机上,你需要添加一条路由... -> 这个路由应该添加到哪里? - undefined

0

设置:

PC-A 是 Docker 主机,PC-B 是网络中的另一台计算机。要从 PC-B 访问 Docker 容器,请在主机上运行以下 iptables 规则。

iptables -A FORWARD -i docker0 -o eth0 -j ACCEPT

iptables -A FORWARD -i eth0 -o docker0 -j ACCEPT

注意: eth0 是主机的接口,docker0 是 Docker 的虚拟默认桥接。

现在在 PC-B 中添加路由。

route add -net <dockerip> netmask <net mask> gw <docker's host>

直接ping/access容器服务。


0

可以在一个附加的OpenVPN服务器容器中运行感兴趣的容器,以便您可以通过VPN连接从主机上看到容器:

  • 使用docker network create --subnet=172.19.0.0/24 my-net创建一个网络,容器将在其中相互通信。
  • 使用--net my-net参数为docker run附加容器。
  • 在同一网络中运行一个带有OpenVPN的附加容器。这次您需要为VPN连接进行端口映射-p 1194:1194/udp
  • 在主机上使用OpenVPN客户端连接到此网络以ping它们。

此外,您可能需要在OpenVPN客户端配置文件中注释掉redirect-gateway指令,并在服务器配置文件中添加push "route 172.19.0.0 255.255.255.0"(并删除其他推送)。


0
假设您有一台W-> Windows机器,L-Linux Vbox VM(eth0,eth1)和在此L-Linux Vbox VM上运行的使用端口8989的docker应用程序。提供者不必以任何方式使用Vbox或W-> win。您想在浏览器上键入{{link1:http://app:8989}}。据我所知,有两种方法;自动运行vagrant的简单方法,或手动通过“Host-only Adapter”配置Vbox VM进行端口转发,该适配器实际上是eth1;通常情况下,eth0是Vbox的默认保留10.0.2.15 IP分配。或者,在win / lin / mac的命令提示符上,通过“VBoxManage”命令设置网络或通过脚本自动化。
webtier.vm.network "forwarded_port", guest: 8989, host: 8989

运行Docker应用程序
sudo docker run -p 8989:8989 ...

在Windows资源管理器中(W -> Windows机器),浏览您的应用程序

http://app:8989

你从Windows机器仍然无法ping通在这种情况下的docker容器IP"172.17.0.2"。这可能是跨平台的,可以在Windows、Linux和Mac上运行。你可能需要查阅VirtualBox手册和Vagrant手册,尤其是网络相关的部分。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接