Reputation: 33823
For a long time I only had one Docker VM on my laptop (first via boot2docker, then via docker-machine).
In this case it was easy, the Docker VM always had the same IP address and I could manually edit my /etc/hosts
file to add a name like mysite.local
pointing to the docker IP.
But recently I had to set up a second docker-machine VM. Now, I guess depending which order I start them up, my containers may be on one of two IP addresses. So my hand-made /etc/hosts
entries don't always work.
I don't want to have to edit this file by hand every time. I'm looking for a way to automate it.
Upvotes: 2
Views: 2028
Reputation: 33823
One useful tool is dnsmasq
, which can be installed with Homebrew. Following the example here I set up two new 'top level domains' in my resolv.conf, one for each docker machine, by doing e.g.:
sudo tee /etc/resolver/dev >/dev/null <<EOF
nameserver 127.0.0.1
EOF
In other words: requests for any .dev
hostnames will be resolved by my local dnsmasq instance (at 127.0.0.1).
I am using dnsmasq so I don't have to define specific hostnames, it can be set up to resolve wildcard i.e. all *.dev
names to a given IP address (which will be the IP of one of my docker machines).
But I still need a way to update the dnsmasq config based on the current IP of my docker machine.
There is an open issue to formalise a way to achieve this in docker-machine:
https://github.com/docker/machine/issues/1792
In the meantime I have ended up with a bunch of aliases and utility functions in my .bashrc
alias dc='docker-compose'
alias dm='docker-machine'
dcexec() {
# (for docker-compose containers)
# because it's tedious having to type
# `docker exec -it myproject_myservice_1 bash`
# every time I want a shell into a running container
if [ "$#" -gt 1 ]; then
arg="$@"
else
arg="bash"
fi
docker exec -it "${PWD##*/}_$1_1" $arg
}
# eg `dcexec myservice`
dnsmasq-restart(){
echo "Restarting dnsmasq..."
sudo launchctl stop homebrew.mxcl.dnsmasq
sudo launchctl start homebrew.mxcl.dnsmasq
}
docker-machine-env() {
eval $(docker-machine env $1)
}
alias dme='docker-machine-env'
docker-machine-dns() {
dmip=$(dm ip $1)
dnsconf=/usr/local/etc/dnsmasq.conf
if [ ! -e /etc/resolver/$1 ]; then
echo "adding $1 entry to resolvers"
sudo tee /etc/resolver/$1 >/dev/null <<EOF
nameserver 127.0.0.1
EOF
fi
if grep -q /$1/$dmip $dnsconf; then
echo "correct dnsmasq entry already exists"
elif grep -q ^address=/$1/ $dnsconf; then
echo "hostname $1 already present in dnsmasq - updating"
# remove line if ip already present for different hostname
sed -i '' -E "\%^address=/[[:alnum:]_.-]+/$dmip%d" $dnsconf
# update existing hostname with new ip
sed -i '' -E "s%^(address=/$1)/([[:digit:].]+)$%\1/$dmip%g" $dnsconf
dnsmasq-restart
else
# neither hostname nor ip are present
echo "adding $1/$dmip entry to dnsmasq"
echo "address=/$1/$dmip" >> /usr/local/etc/dnsmasq.conf
dnsmasq-restart
fi
}
docker-machine-use() {
docker-machine start $1
docker-machine-dns $1
docker-machine-env $1
}
alias dmuse='docker-machine-use'
Now I can just type dmuse dev
to start working on a project and it will ensure the docker-machine vm is running, dns entries ready and environment set (so the docker
command works).
I'll note for anyone finding this: the stuff above is of course pretty specific to the use-case of developing with docker-machine local VMs on OSX.
Upvotes: 4