Richard Bucker

deploy fossil-scm in a docker container on OSX with boot2docker

Posted at — Feb 12, 2015

The title says it all. In this experiment I wanted to create a docker container that had a running fossil-scm instance and the docker container should be as small as possible and therefore should be running from a scratch docker image.(a trusted scratch image is about as small as an image can get. It’s essentially turns a docker run command into an application.)NOTE: setup boot2docker:boot2docker initboot2docker upboot2docker shellinit | source(There are a few other versions of the shellinit command such as back ticks or $(cmd), however, this version is the most compatible and works with fishshell which the others do not.)First and foremost I am using OSX version 10.10. Mavericks is nothing special in the equation but I’m just mentioning it. Next I’ve installed boot2docker 1.5.0 from the distributed binary release for OSX. (I’m not going to show you how to do that here. Some things ya just gotta know.)Make a working folder for the project and make it the current foldermkdir ${HOME}/fossil_projcd ${HOME}/fossil_projDownload the fossil project zip file and unzip it.wget http://www.fossil-scm.org/download/fossil-linux-x86-20150119112900.zipunzip fossil-linux-x86-20150119112900.zipMISTAKE #1: when I downloaded and built my first container everything looked ok until I tried to run it. Then I kept getting “exec format error” messages from docker. I cannot begin to tell you the number of times I tried to build and rebuild my images and containers… subtly tweaking this param and that. I even tried to build the image directly on the boot2docker host. Finally I realized that  I had downloaded the OSX version of fossil. Once I downloaded the linux version I was golden.Create a Dockerfile. (in the 1.50 release of docker you can name your docker file, however, I’m going with the default for now) Here is my file:FROM scratchMAINTAINER Richard Bucker <richard@bucker.net>EXPOSE 8080ADD fossil /fossilVOLUME ["/data”]CMD []ENTRYPOINT ["/fossil”, “server”, “/data/fossil/repos”, “–port”, “8080”]built on the SCRATCH base image (no need for phusion here)I’m making myself the maintainer of this projectI want to expose the default port 8080 to the hostADD will copy the file from the same folder as the Dockerfile to the designated TO locationbind the /data folder from the host to the containerIf there was a CMD then docker would try to run /bin/sh, however, the sh command is not availableThe entrypoint tells docker to run the fossil as a server and where the fossil repositories are locatedI created a small Makefile. It’s common for me to build this sort of thing because (a) it’s idiomatic for most programming languages to have some sort of element and (b) I use it to store information like dependencies and commands in one location so that I’m not hunting around.all: del clean buildbuild: docker build -rm -t fossil .run: docker run –privileged –rm -p 8081:8080 -v /data:/data –name fossil fossildel: docker rm fossilclean: docker ps -a -f status=exited -q | xargs docker rm  docker images -a -q | xargs docker rmiIt’s pretty self explanatory what’s going on here. The build command will create the image which I’ve tagged “fossil”. It might be confusing to name the container the same name as the application but for the purpose of the example it will do. The ‘rm’ option will delete the intermediate layers as the image is composed.When you run the image (turn it into a container and execute) ‘rm’ deleting the intermediate layers if there are any, giving privileges to the container(probably unnecessary), linking the host’s port 8081 to the container’s port 8080, mounting the host’s /data folder to the container’s folder /data, and naming the container instance “fossil”. Again I’ve named the container the same as the application and the image. This is less than ideal… I’m certain of it.MISTAKE #2: when I started running the application I had created a repos folder: mkdir -p ${HOME}/data/fossil/repos; only to realize that the folder I was creating was on the OSX host and not the boot2docker host. So the next step was to ssh into the boot2docker host and create the missing folder.boot2docker sshsudo mkdir -p /data/fossil/repossudo chown -R docker /dataThat was pretty simple… but still not enough. The run command would not execute because I did not have a repo in the repos folder.boot2docker sshwget http://www.fossil-scm.org/download/fossil-linux-x86-20150119112900.zipunzip fossil-linux-x86-20150119112900.zip./fossil new /data/fossil/repos/first.fossilNow that I had my first repo I could run the container and launch my browser. But first I needed to know my IP address:boot2docker iphttp://192.168.59.103:8081/firstI don’t have much else to report. I have a working docker/fossil. I suppose there are a few things I could do.choose better names instead of naming the image and container “fossil"the name should be registry friendlyand I should publish my container (interesting to note that two other versions of the same idea used ubuntu… so lesson learned use scratch when you canGood luck!UPDATE: One thing that I think I missed…. when running the container one should either detach it with the ‘-d’ option or force it to be interactive with the ‘-ti’ options. Using daemon mode means that the –name option makes it easier to address the instance. Using the -ti option means it’s easier to kill the daemon from the command line with a ctrl+C.