Home > IT > A bit of Windows Docker bash-fu

A bit of Windows Docker bash-fu

Monday, April 20th, 2015

In my last post I’ve mentionned that Microsoft has helped Docker deliver a native Docker client for Windows (yay!).

I’ve also promised to share the little bits that I’ve added to my Windows bash profile to make my life easier. As I’ve said, I’m a huge fan of MSYS and msysGit and I use my Git Bash shell all day long, so here comes a bit of Windows bash-fu.

For those wondering, I prefer Linux and I would use it as my main OS (did so in the past) if I didn’t also like gaming. I can’t stand fiddling around config files to get my games running (hey Wine) and I can’t stand losing n FPS just to stay on the free side. Finally I am not too fond of putting multiple OSes on my main machine just for the sake of being able to play. The least painful solution for me is simply to use Windows and remain almost sane by using Bash.

One thing to note is that my bash profile as well as all the tools that I use are synchronized between my computers in order to allow me to have a consistent environment; I’m done raging because I’m in the train and some tool I’ve installed on my desktop isn’t available on my laptop.. I’ll describe that setup.. another day :)

So first things first, I’ve installed Docker v1.6.0 on my machine without adding it to the path or creating any shortcuts (since I’m not going to use that install at all); you can get it from https://github.com/boot2docker/windows-installer/releases/latest.

Once installed, I’ve copied the docker client (docker.exe) to the folder I use to store my shared tools (in this case c:\CloudStation\programs\dev\docker). I have the Docker machine in the same folder (downloaded from here).

append_to_path(){ # dumb append to path
    PATH=$1":"$PATH
}
...
# Docker
export DOCKER_HOME=$DEV_SOFT_HOME/Docker
append_to_path $DOCKER_HOME

alias docker='docker.exe'

alias docker-machine='docker-machine.exe'
alias dockermachine='docker-machine'
alias dm='docker-machine'

export DOCKER_LOCAL_VM_NAME='docker-local'

In the snippet above I simply ensure that the docker client is on my path and that I can invoke it simply using ‘docker’. Same for docker-machine, along with a nice shortcut ‘dm’.

Note that I also set a name for the local Docker VM that I want to manage; you’ll see below why that’s useful.

docker-config-client()
{
	echo "Configuring the Docker client to point towards the local Docker VM ($DOCKER_LOCAL_VM_NAME)..."
	eval "$(docker-machine env $DOCKER_LOCAL_VM_NAME)"
	if [ $? -eq 0 ]; then
		echo "Docker client configured successfully!"
	else
		echo "Failed to configure the Docker client!"
		return;
	fi
}
alias dockerconfig='docker-config-client'
alias configdocker='docker-config-client'

The ‘docker-config-client’ function allows me to easily configure my Docker client to point towards my local Docker VM. I’ve added some aliases because I’ve got a pretty bad memory :)

This function assumes that the local Docker VM already exists and is up an running. This is not always the case, hence the additional functions below.

docker-check-local-vm() # check docker-machine status and clean up if necessary
{
	echo "Verifying the status of the local Docker VM ($DOCKER_LOCAL_VM_NAME)"
	dmCheckResult=$(docker-machine ls)
	#echo $dmCheckResult
	if [[ $dmCheckResult == *"error getting state for host $DOCKER_LOCAL_VM_NAME: machine does not exist"* ]]
	then
		echo "The local Docker VM ($DOCKER_LOCAL_VM_NAME) is known by docker-machine but does not exist anymore."
		echo "Cleaning docker-machine."
		dmCleanupResult=$(docker-machine rm $DOCKER_LOCAL_VM_NAME)
		
		if [[ $dmCleanupResult == *"successfully removed"* ]]
		then
			echo "docker-machine cleanup successful! Run 'docker-init' to create the local Docker VM."
		fi
		return
	fi
	echo "No problem with the local Docker VM ($DOCKER_LOCAL_VM_NAME) and docker-machine. If the machine does not exist yet you can create it using 'docker-init'"
}
alias dockercheck='docker-check-local-vm'
alias checkdocker='docker-check-local-vm'

The ‘docker-check-local-vm’ simply lists the docker engines known by docker-machine in order to see if there’s a problem with the local Docker VM. Such a problem can occur when docker-machine knows about a given Docker engine and you delete it (e.g., if you remove the Virtualbox VM then invoke ‘docker-machine ls’, then you’ll get the error).

docker-start()
{
	echo "Trying to start the local Docker VM ($DOCKER_LOCAL_VM_NAME)"
	dmStartResult=$(docker-machine start $DOCKER_LOCAL_VM_NAME)
	#echo $dmStartResult
	if [[ $dmStartResult == *"machine does not exist"* ]]
	then
		echo "The local Docker VM ($DOCKER_LOCAL_VM_NAME) does not seem to exist."
		docker-check-local-vm
		return
	fi
	
	if [[ $dmStartResult == *"VM not in restartable state"* ]]
	then
		echo "The local Docker VM ($DOCKER_LOCAL_VM_NAME) is probably already running."
		docker-config-client
		return
	fi
	
	if [[ $dmStartResult == *"Waiting for VM to start..."* ]]
	then
		echo "The local Docker VM ($DOCKER_LOCAL_VM_NAME) was successfully started!"
		docker-config-client
		return
	fi
	
	if [[ $dmStartResult == *"Host does not exist"* ]]
	then
		echo "The local Docker VM ($DOCKER_LOCAL_VM_NAME) does not exist. Run 'docker-init' first!"
		return
	fi
}
alias dockerstart='docker-start'
alias startdocker='docker-start'

The ‘docker-start’ function above tries to start my local Docker VM. It first assumes that the machine does exist (because I’m an optimist after all).

Since the docker-machine executable doesn’t return useful values, I have to resort to string matching; I know that this sucks but don’t forget we’re on Windows.. There’s probably a way to handle this better, but it’s enough for me now.

If the VM does not exist, the docker-machine check function is called.

If the VM cannot be started, it might be that the machine is already running; in that case the docker client gets configured (same if the start succeeds).

If the VM clearly doesn’t exist then the function stops there and points towards ‘docker-init’ explained afterwards.

docker-stop()
{
	echo "Trying to stop the local Docker VM ($DOCKER_LOCAL_VM_NAME)"
	dmStopResult=$(docker-machine stop $DOCKER_LOCAL_VM_NAME)
	#echo $dmStopResult
	if [[ $dmStopResult == *"Host does not exist"* ]]
	then
		echo "The local Docker VM ($DOCKER_LOCAL_VM_NAME) does not seem to exist."
		docker-check-local-vm
		return
	fi
	
	if [[ $dmStopResult == *"exit status 1"* ]]
	then
		echo "The local Docker VM ($DOCKER_LOCAL_VM_NAME) is already stopped (or doesn't exist anymore)."
		docker-check-local-vm
		return
	fi
	
	echo "The local Docker VM ($DOCKER_LOCAL_VM_NAME) was stopped successfully."
}
alias dockerstop='docker-stop'
alias stopdocker='docker-stop'

The ‘docker-stop’ function stops the local Docker VM if it’s running (pretty obvious eh ^^). In case of error, the docker-machine check function is called (docker-check-local-vm).

docker-init()
{
	echo "Trying to create a local Docker VM called $DOCKER_LOCAL_VM_NAME"
	dmCreateResult=$(docker-machine create --driver virtualbox $DOCKER_LOCAL_VM_NAME)
	#echo $dmCreateResult
	
	if [[ $dmCreateResult == *"has been created and is now the active machine."* ]]
	then
		echo "Local Docker VM ($DOCKER_LOCAL_VM_NAME) created successfully!"
		docker-config-client
		return
	fi
	
	if [[ $dmCreateResult == *"already exists"* ]]
	then
		echo "The local Docker VM ($DOCKER_LOCAL_VM_NAME) already exists!"
		dockerstart
		return
	fi
}
alias dockerinit='docker-init'
alias initdocker='docker-init'

This last function, ‘docker-init’ helps me provision my local Docker VM and configure my Docker client to point towards it.

With these few commands, I’m able to quickly configure/start/use a local Docker VM in a way that works nicely on all my machines (remember that I share my bash profile & tools across all my computers).

Voilà! :)

If you enjoyed this post, make sure you subscribe to my RSS feed!

1 Comment »

  1. […] my last post, I’ve given you a few use­ful func­tions for mak­ing your life with Docker eas­ier on […]



    Pingback by A bit more Windows Docker bash-fu | Midnight Light — 2015-04-22 @ 16:16

RSS feed for comments on this post. TrackBack URL

Leave a comment