Docker and OpenShift from First Principles
As the microservice story continues to take hold, I thought it was time for me to learn a bit more about it and how the tools all fit together from a developer perspective. One of my main goals here was to use OCaml, my favourite programming language, to write a “Hello World” microservice. My reasoning behind this decision was, not only because I like OCaml, that I needed to work from first principles without any of the hand-holding that other languages have. This worked perfectly as it forced me to deal with many of the things that would have been done for me in a vanilla OpenShift setup.
So, from the OCaml side, as I already had many of the basic services installed via opam, the OCaml package manager, it was simple issue to get started. The basic way to write a REST API in OCaml is to use the Opium package. This takes inspiration from the Sinatra library from Ruby but adds all the strictly-typed goodness of OCaml. Thus, it was a fairly easy task to write up a very easy “/hello” endpoint that returned a JSON response. I assume here that you know how to compile OCaml projects because this is rather secondary to getting Docker and OpenShift to talk to one another.
As OpenShift uses Docker, you need to have a local Docker registry. This is where many of the OpenShift tutorials differ as they assume you are using a public repository and a public Docker registry. So, you need to write a Docker file for your microservice. Thankfully, as OCaml is a compiled language, I can compile my service locally, test it, then build the Docker file by copying the executable instead of having to install a huge runtime system. Although, I would caution that you ensure that you are compiling against the right thing because if the Docker container that you are building uses musl, for instance, Alpine Linux, you will need to ensure that you compile in an Alpine Linux docker container. I decided to use Ubuntu for my microservice, but I would think that you may want to use Alpine because of its small footprint. Thus, my Docker file looked like this:
RUN useradd -m — uid 1001 — gid 0 ocamlshift-user
COPY src/_build/default/ocamlshift.exe /usr/bin/ocamlshift.exe
RUN chmod g+x /usr/bin/ocamlshift.exe
CMD /usr/bin/ocamlshift.exe -p 8080 -d
Once you have built your docker image, you can run it locally to ensure that you have a working image. Then you can tag the image with your docker registry URL then push the image to the Docker registry. If you have a private Docker registry, just talk to your relevant DevOps person and they should have some advice for you. Also, I found (and YMMV) that Docker does not automatically tag images if you re-build your image with a new executable service so you will need to do that manually.
One thing you must keep in mind when doing this is that you will need to have an OpenShift project. I called mine “ocamlshift” then you must give it a pull specification for OpenShift to pull the docker image into the project. You can do this a number of ways but I found that, for very simple projects like mine, you can use the OpenShift website to give it the same URL as your Docker image in the registry.
In the OpenShift world, you use service JSON or YAML files to define services and pods. This is particularly useful if you have a number of services that are complex. In my case, I only had one service and I could copy and paste the Docker registry URL under the “Deploy Image” -> “Image Name” search box when creating a new OpenShift project. However, as noted above, this is not recommended for complex setups.
Once this is done, you should be able to spin up your new pod. The URL is assigned based on your namespace and pod name (in my case, I ended up with two of the same as I am not very imaginative).
The advantages of this approach are clear. Even with a programming language like OCaml which does not have wide adoption, it is easy to write and deploy REST web services. While more complex systems will, of course, need more work but you can now create services in the language that most complements the problem at hand rather than having to build things in one single programming language. The OpenShift system gives you the tools to allow developers to flexibly solve problems.