diff --git a/plugins/providers/docker/driver.rb b/plugins/providers/docker/driver.rb index 9ed009be2..41f75c8bc 100644 --- a/plugins/providers/docker/driver.rb +++ b/plugins/providers/docker/driver.rb @@ -236,9 +236,22 @@ module VagrantPlugins execute('docker', 'ps', '-a', '-q', '--no-trunc').to_s.split end + # Attempts to first use the docker-cli tool to inspect the default bridge subnet + # Falls back to using /sbin/ip if that fails + # # @return [String] IP address of the docker bridge def docker_bridge_ip - output = execute('/sbin/ip', '-4', 'addr', 'show', 'scope', 'global', 'docker0') + bridge = inspect_network("bridge")&.first + if bridge + bridge_ip = bridge.dig("IPAM", "Config", 0, "Gateway") + end + return bridge_ip if bridge_ip + @logger.debug("Failed to get bridge ip from docker, falling back to `ip`") + docker_bridge_ip_fallback + end + + def docker_bridge_ip_fallback + output = execute('ip', '-4', 'addr', 'show', 'scope', 'global', 'docker0') if output =~ /^\s+inet ([0-9.]+)\/[0-9]+\s+/ return $1.to_s else diff --git a/test/unit/plugins/providers/docker/driver_compose_test.rb b/test/unit/plugins/providers/docker/driver_compose_test.rb index 2d9aa1fdb..6d5711760 100644 --- a/test/unit/plugins/providers/docker/driver_compose_test.rb +++ b/test/unit/plugins/providers/docker/driver_compose_test.rb @@ -339,9 +339,10 @@ describe VagrantPlugins::DockerProvider::Driver::Compose do describe '#docker_bridge_ip' do let(:stdout) { " inet 123.456.789.012/16 " } - it 'returns an array of all known containers' do + it 'returns the bridge ip' do expect(subject.docker_bridge_ip).to eq('123.456.789.012') - expect(cmd_executed.first).to eq("/sbin/ip -4 addr show scope global docker0") + expect(cmd_executed.first).to eq("docker network inspect bridge") + expect(cmd_executed.last).to eq("ip -4 addr show scope global docker0") end end end diff --git a/test/unit/plugins/providers/docker/driver_test.rb b/test/unit/plugins/providers/docker/driver_test.rb index c193a21d7..8c6496ce4 100644 --- a/test/unit/plugins/providers/docker/driver_test.rb +++ b/test/unit/plugins/providers/docker/driver_test.rb @@ -552,11 +552,65 @@ describe VagrantPlugins::DockerProvider::Driver do end describe '#docker_bridge_ip' do - let(:stdout) { " inet 123.456.789.012/16 " } + context 'from docker network command' do + let(:network_struct) { + [{ + "Name": "bridge", + "Id": "ae74f6cc18bbcde86326937797070b814cc71bfc4a6d8e3e8cf3b2cc5c7f4a7d", + "Created": "2019-03-20T14:10:06.313314662-07:00", + "Scope": "local", + "Driver": "bridge", + "EnableIPv6": false, + "IPAM": { + "Driver": "default", + "Options": nil, + "Config": [ + { + "Subnet": "172.17.0.0/16", + "Gateway": "172.17.0.1" + } + ] + }, + "Internal": false, + "Attachable": false, + "Ingress": false, + "ConfigFrom": { + "Network": "" + }, + "ConfigOnly": false, + "Containers": { + "a1ee9b12bcea8268495b1f43e8d1285df1925b7174a695075f6140adb9415d87": { + "Name": "vagrant-sandbox_docker-1_1553116237", + "EndpointID": "fc1b0ed6e4f700cf88bb26a98a0722655191542e90df3e3492461f4d1f3c0cae", + "MacAddress": "02:42:ac:11:00:02", + "IPv4Address": "172.17.0.2/16", + "IPv6Address": "" + } + }, + "Options": { + "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" + }, + "Labels": {} + }].to_json + } + it "returns the bridge gateway ip" do + allow(subject).to receive(:inspect_network).and_return(JSON.load(network_struct)) + expect(subject.docker_bridge_ip).to eq('172.17.0.1') + end + end - it 'returns an array of all known containers' do - expect(subject.docker_bridge_ip).to eq('123.456.789.012') - expect(cmd_executed).to eq("/sbin/ip -4 addr show scope global docker0") + context 'when falling back to ip' do + let(:stdout) { " inet 123.456.789.012/16 " } + + it 'returns the bridge ip' do + expect(subject.docker_bridge_ip).to eq('123.456.789.012') + expect(cmd_executed).to eq("ip -4 addr show scope global docker0") + end end end