Skip to content

Instantly share code, notes, and snippets.

@lentschi
Created November 5, 2016 16:17
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lentschi/63d073467a7c59c1c0dac8c1951341f0 to your computer and use it in GitHub Desktop.
Save lentschi/63d073467a7c59c1c0dac8c1951341f0 to your computer and use it in GitHub Desktop.
alias a docker container's ip to /ect/hosts
#!/usr/bin/env python
# Script to alias a docker container's primary IPv4 address
# with the desired host_name in /ect/hosts
#
# Usage: add_container_to_hosts <container_name> <host_name>
#
# CAVEAT: Currently won't work for IPv6 addresses and will only work
# on platforms, where the hosts file can be found under /etc/hosts
#
#
# Note: Could easily be replaced by https://github.com/gliderlabs/resolvable
# but that won't work, when one container requires being addressed using
# more than two domain names
#
# Author: Florian Lentsch <office@florian-lentsch.at>
import sys, re, os
from subprocess import Popen, PIPE, call
from os.path import isfile
HOSTS_FILE = '/etc/hosts'
def die(msg):
sys.stderr.write("Error: " + msg + "\n")
exit(1)
def cmd(cmd_arr):
p = Popen(cmd_arr, stdout=PIPE)
out, err = p.communicate()
if err:
return None
return out
class HostsFileModifier:
def __init__(self, container_name, host_name):
self.host_name = host_name
self.container_name = container_name
def get_container_ip(self):
ip = cmd(["docker", "inspect", "-f", "{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}", self.container_name])
if isinstance(ip, basestring) and re.match(r"^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$", ip.strip()):
return ip.strip()
ip = cmd(["docker", "inspect", "--format", "{{ .NetworkSettings.IPAddress }}", self.container_name])
if isinstance(ip, basestring) and re.match(r"^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$", ip.strip()):
return ip.strip()
die("Could not determine container IPv4 address of container id/name " + self.container_name)
def read_hosts_file(self):
if not isfile(HOSTS_FILE):
die(HOSTS_FILE + " not found")
try:
self.hosts_file = open(HOSTS_FILE, 'r')
return self.hosts_file.read()
except IOError:
die("Could not read from " + HOSTS_FILE)
def replace_or_add_domain_ip(self, hosts_str, new_ip):
correct_content = new_ip + "\t" + self.host_name
regex = re.compile("^((?:[0-9]{1,3}\.){3}[0-9]{1,3})\s+(" + re.escape(self.host_name) + ")$", flags=re.MULTILINE)
md = regex.search(hosts_str)
if md:
if md.group(1) == new_ip:
return hosts_str
if os.getuid() == 0:
print "Changing '%s' into '%s'" % (md.group(0), correct_content)
return regex.sub(correct_content, hosts_str)
else:
# in case the host is present in a line with many other hosts
# just remove it from there before adding it back in at the bottom:
hosts_str = re.sub("\s+" + re.escape(self.host_name), '', hosts_str)
if os.getuid() == 0:
print "Appending '%s'" % correct_content
return hosts_str + "\n" + correct_content + "\n"
def change_hosts_file(self, content):
self.hosts_file.close
if os.getuid() != 0:
print "re-running as root (required to change hosts file)... "
call(['sudo', sys.argv[0], sys.argv[1], sys.argv[2] ])
exit(0)
try:
with open(HOSTS_FILE, 'w') as self.hosts_file:
self.hosts_file.write(content)
except IOError:
die("Change required, but could not write " + HOSTS_FILE + ". Did you forget to use sudo?")
def set_domain_ip(self,ip):
hosts_str = self.read_hosts_file()
modified_hosts_str = self.replace_or_add_domain_ip(hosts_str, ip)
if not modified_hosts_str:
die("Error parsing hosts file")
if hosts_str == modified_hosts_str:
print "Hosts file does not need changing"
exit(0)
self.change_hosts_file(modified_hosts_str)
exit(0)
if len(sys.argv) != 3:
die('Usage: ' + sys.argv[0] + ' <container_name> <host_name>')
modifier = HostsFileModifier(sys.argv[1], sys.argv[2])
ip = modifier.get_container_ip()
modifier.set_domain_ip(ip)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment