title: Java application cannot get IP address of the host in docker container with static IP
body: <p>I use OpenStack for a while to manage my applications. Now I want to transfer them to docker as container per app because docker is more lightweight and efficient.</p>
  
  <p>The problem is almost every thing related to networking went wrong in runtime. </p>
  
  <p>In my design, every application container should have a static IP address and I can use hosts file to locate the container network.</p>
  
  <p>Here is my implementation. (the bash filename is docker_addnet.sh)</p>
  
  <pre><code># Useages
  # docker_addnet.sh container_name IP
  # interface name: veth_(containername)
  # gateway 172.17.42.1
  
  if [ $# != 2 ]; then
      echo -e "ERROR! Wrong args"
      exit 1
  fi
  
  container_netmask=16
  container_gw=172.17.42.1
  
  container_name=$1
  bridge_if=veth_`echo ${container_name} | cut -c 1-10`
  container_ip=$2/${container_netmask}
  container_id=`docker ps | grep $1 | awk '{print \$1}'`
  pid=`docker inspect -f '{{.State.Pid}}' ${container_name}`
  
  echo "Contaner: " $container_name "pid: " $pid
  
  mkdir -p /var/run/netns
  ln -s /proc/$pid/ns/net /var/run/netns/$pid
  
  brctl delif docker0 $bridge_if
  
  ip link add A type veth peer name B
  ip link set A name $bridge_if
  brctl addif docker0 $bridge_if
  ip link set $bridge_if up
  ip link set B netns $pid
  ip netns exec $pid ip link set dev B name eth0
  ip netns exec $pid ip link set eth0 up
  ip netns exec $pid ip addr add $container_ip dev eth0
  ip netns exec $pid ip route add default via $container_gw
  </code></pre>
  
  <p>The script is use to set the static ip address of the container, then you run the container, you must append <code>--net=none</code> to manually setup the network</p>
  
  <p>You can now start a container by</p>
  
  <pre><code>sudo docker run --rm -it --name repl --dns=8.8.8.8 --net=none clojure bash
  </code></pre>
  
  <p>and set the network by </p>
  
  <pre><code>sudo zsh docker_addnet.sh repl 172.17.15.1
  </code></pre>
  
  <p>In the container bash, you can see the IP address by <code>ip addr</code>, the output is something like </p>
  
  <pre><code>1: lo: &lt;LOOPBACK,UP,LOWER_UP&gt; mtu 65536 qdisc noqueue state UNKNOWN group default 
      link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
      inet 127.0.0.1/8 scope host lo
         valid_lft forever preferred_lft forever
      inet6 ::1/128 scope host 
         valid_lft forever preferred_lft forever
  67: eth0: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
      link/ether 2e:7b:7e:5a:b5:d6 brd ff:ff:ff:ff:ff:ff
      inet 172.17.15.1/16 scope global eth0
         valid_lft forever preferred_lft forever
      inet6 fe80::2c7b:7eff:fe5a:b5d6/64 scope link 
         valid_lft forever preferred_lft forever
  </code></pre>
  
  <p>So far so good.</p>
  
  <p>Let's try to get the container host ip address by using clojure repl. First the repl by:</p>
  
  <pre><code>lein repl
  </code></pre>
  
  <p>next eval the code below </p>
  
  <pre><code>(. java.net.InetAddress getLocalHost)
  </code></pre>
  
  <p>The clojure code is equals to </p>
  
  <pre><code>System.out.println(Inet4Address.getLocalHost());
  </code></pre>
  
  <p>What you get is an exception </p>
  
  <blockquote>
    <p>UnknownHostException 5a8efbf89c79: Name or service not known 
    java.net.Inet6AddressImpl.lookupAllHostAddr (Inet6AddressImpl.java:-2)</p>
  </blockquote>
  
  <p>Other things going weird is the RMI server cannot get client IP address by <code>RemoteServer.getClientHost();</code>.</p>
  
  <p>So what may cause this issue? I remember that java sometimes get the wrong network configures, but I don't know the reason.</p>