Class: Docker::Compose::NetInfo

Inherits:
Object
  • Object
show all
Defined in:
lib/docker/compose/net_info.rb

Overview

Utility that gathers information about the relationship between the host on which the Ruby VM is running and the docker host, then makes an guess about the mutually routable IP addresses of each.

This information can be used to tell containers how to connect to ports on the local host, or conversely to tell the local host how to connect to ports published by containers running on the docker host.

The heuristic works for most cases encountered in the wild, including:

- DOCKER_HOST is unset (assume daemon listening on 127.0.0.1)
- DOCKER_HOST points to a socket (assume 127.0.0.1)
- DOCKER_HOST points to a tcp, http or https address

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(docker_host = ENV['DOCKER_HOST'], my_ips = self.class.ipv4_interfaces) ⇒ NetInfo

Create a new instance of this class.



27
28
29
30
31
32
# File 'lib/docker/compose/net_info.rb', line 27

def initialize(docker_host = ENV['DOCKER_HOST'],
               my_ips = self.class.ipv4_interfaces)
  docker_host ||= 'unix:/var/run/docker.sock'
  @docker_url = URI.parse(docker_host)
  @my_ips = my_ips
end

Class Method Details

.ipv4_interfacesArray

Determine IP addresses of the local host’s network interfaces.



19
20
21
22
# File 'lib/docker/compose/net_info.rb', line 19

def self.ipv4_interfaces
  Socket.getifaddrs
    .map { |i| i.addr.ip_address if i.addr && i.addr.ipv4? }.compact
end

Instance Method Details

#docker_routable_ipString

Figure out the likely IP address of the host pointed to by self.docker_url.



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/docker/compose/net_info.rb', line 70

def docker_routable_ip
  case @docker_url.scheme
  when 'tcp', 'http', 'https'
    docker_dns = @docker_url.host
    docker_port = @docker_url.port || 2376
  else
    # Cheap trick: for unix, file or other protocols, assume docker ports
    # are proxied to localhost in addition to other interfaces
    docker_dns = 'localhost'
    docker_port = 2376
  end

  addr = Addrinfo.getaddrinfo(
    docker_dns, docker_port,
    Socket::AF_INET, Socket::SOCK_STREAM).first

  addr && addr.ip_address
end

#host_routable_ip(target_ip = docker_routable_ip) ⇒ String

Examine local host’s network interfaces; figure out which one is most likely to share a route with the given IP address. If no IP address is specified, figure out which IP the Docker daemon is reachable on and use that as the target IP.



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/docker/compose/net_info.rb', line 43

def host_routable_ip(target_ip = docker_routable_ip)
  best_match  = ''
  best_prefix = 0

  target_cps = target_ip.codepoints

  @my_ips.each do |my_ip|
    ip_cps = my_ip.codepoints
    prefix = 0
    ip_cps.each_with_index do |cp, i|
      break unless target_cps[i] == cp
      prefix = i
    end

    if prefix > best_prefix
      best_match = my_ip
      best_prefix = prefix
    end
  end

  best_match
end