Monday 23 January 2017

Working with Docker

Docker is an interesting framework for running applications within their own configuration bubble. Docker allows you to create effectively micro-VM images that you can configure with just the minimum amount of software to run a single application. The images can be built from pre-configured templates which makes setting up the image more like just installing a single package rather than building an entire machine.

Getting Started with Docker

The best place to get started with Docker is the documentation.

There are a few interesting points to note however which is:
  • Docker runs well on Mac and some flavours of Linux but on Windows you are restricted to some versions of Windows 10. I found that using centos 6.8 required an alternative installation process (see here)
  • You can run a broad range of linux distros inside Docker but AFAI can tell it isn't possible to run Windows in a docker. Although it appears there are some custom container extensions happening to make this work. https://www.simple-talk.com/cloud/platform-as-a-service/windows-containers-and-docker/
  • Dockers are really command line VMs. Forget trying to run a GUI from a Docker although clearly you could have an application inside the docker connect out to a XWindows system (but why would you?)

Docker for Development

My interest right now is in running Dockers for development. The applications I work in during my day-job (and even some I play with out of hours) require significant configuration and being able to set this up by simply downloading a docker image is attractive.

There are a couple of interesting Docker features that make this attractive:
  • You can expose your host filesystem to the docker. This means you can have a system where the artrifacts of your development build can be run pretty much directly in the docker. Without this you end up with a system where you have to run the product installer/RPM etc to install the system, configure it and then copy over the executables with the ones you just built. Docker makes this easier as you can create a docker where the executable components are links to files on the parent filesystem
  • Often multiple VMs/machines are involved in a system. You the the DB, back end server, web front-end etc etc. These can all be run as docker containers and can even be deployed into the same machine. The docker system provides a local bridge network so then no matter what machine you deploy your system on it will all interconnect.

Creating a Docker

You create a docker by creating a text file called Dockerfile and defining the actions that will occur when the docker image is created and when it is run.

In my case I was creating a Docker for a Java/Tomcat/Spring application running on Centos (as I mostly work with Centos in my day job).

So to start with we specify centos as the base image in the Dockerfile

FROM centos

Then I will install JDK 1.8 using wget so I need wget

RUN yum -y install wget

Then the following snippet gets the JDK installer from oracle and untars it and sets up the environment to run from the JDK

RUN cd /opt/;\
    wget --no-cookies --no-check-certificate \
         --header "Cookie: gpw_e24=http%3A%2F%2Fwww.oracle.com%2F; oraclelicense=accept-securebackup-cookie"\
         "http://download.oracle.com/otn-pub/java/jdk/8u101-b13/jdk-8u101-linux-x64.tar.gz";\
    tar xzf jdk-8u101-linux-x64.tar.gz

ENV JAVA_HOME=/opt/jdk1.8.0_101/

ENV PATH=$PATH:$JAVA_HOME/bin

The next thing is to install tomcat. We wget the tar file, create a directory for it, untar it and ditch the .bat files. Finally we ditch the tar file.

ENV TOMCAT_MIRROR http://mirror.ventraip.net.au/apache
ENV TOMCAT_MAJOR 8
ENV TOMCAT_VERSION 8.0.37
ENV TOMCAT_TGZ_URL $TOMCAT_MIRROR/tomcat/tomcat-$TOMCAT_MAJOR/v$TOMCAT_VERSION/bin/apache-tomcat-$TOMCAT_VERSION.tar.gz

ENV CATALINA_HOME /usr/local/tomcat
ENV PATH $CATALINA_HOME/bin:$PATH

RUN mkdir -p "$CATALINA_HOME"
WORKDIR $CATALINA_HOME

RUN wget "$TOMCAT_TGZ_URL" && \
tar -xvf apache-tomcat-$TOMCAT_VERSION.tar.gz --strip-components=1 && \
rm bin/*.bat &&\

rm apache-tomcat-$TOMCAT_VERSION.tar.gz

Now all that's left to do is to specify port 8080 should be exposed to the host so we can access tomcat and to specify that the docker should run tomcat using the catalina.sh run when it starts

EXPOSE 8080

CMD ["catalina.sh", "run"]

Building the Docker

I have been using gradle to build my application and I found there is a cool plugin for building docker images from your build. It means that you can update the docker with your built artifact during the build.

To use the plugin I load it like this in the plugins part of my gradle build file

plugins
{
    id 'com.palantir.docker' version "0.9.0"
}

Then I create a docker task like this:

docker
{
name 'tombi/abbot'
dockerfile 'src/main/docker/abbot/Dockerfile'
dependsOn tasks.war
        files 'build/libs/Abbot3.war'
}

Then I can build the docker just by saying 'gradle docker'


Running the Docker

In my case I want to access the tomcat server running inside the docker so I have to map the port tomcat listens on to a port on the host. 

Cleaning up Dockers

After a few debug runs I found I had a load of  <none> docker images. The quick way to nuke all of these is to do this:

docker rmi -f `docker images | grep "^<none>" | awk '{ print $3 }' | xargs`



No comments:

Post a Comment