Avoiding manual microservices management in development



Piotr Limanowski

A señor code arsonist based in Gdansk, PL. Been doing scalable web products, with variety of languages (see above for the most recent), since early 2000s. Constatly working on simplyfing things. I write, talk and ship code. Aside from that I'm el modo evil brujito and a future hoverboard owner.


Avoiding manual microservices management in development

Posted by Piotr Limanowski on .

The Issue

So you've done hunderds of #microservices, you're running them in #docker and development, testing (don't even get me started on deployment) have just got infinitely more sophisticated. You're keeping all those shiny docker containers in docker-compose so you can run them locally, building with your favourite build tool that spits the containers all over the place. And you either are in a dev mode or production mode. Either all in docker or all in local. Or you do all that manually. Or start a service in docker to get the dependencies started and then kill the top-level one. However here's a quick fix to the cumbersome process…

The Solution

All you need to do is fetch dependencies for given service and start them and run the service(s) under development with incremental build tool with local-dev config. I'm using Makefile for most of the cumbersome automation around projects and interacting with bash environment rather than pushing all too much project unrelated stuff into sbt/lein/mix. Here's a sample task that does what's described above:

.PHONY: run $(R)
run: $(R)
    @docker-compose kill $(@) || true
    @docker-compose up -d $(filter-out $(R),$(shell dcdeps $(@)))
    @sbt "project $(@)" "~re-start --- -Dconfig.resource=dev.conf"

The task simply issues docker-compose and sbt commands for any given project, therfore you can run it as follows:

make -j2 run R="first-service second-service"

Which will execute the command for both first-service and second-service in two separate threads allowing the whole thing to work independently. That's why the whole .PHONY magic is being used rather than simple variables. I'm also using a simple utility I have put together in a couple of minutes - dcdeps (as in: docker-compose dependencies). The utility simply looks into given compose.yml and prints dependencies for given service, hance docker-compose uses that for running all the listed services in the background with filtering out the services that are about to be ran. The thing is though, that the approach enables you to simply change the tags of containers and run mocks (prism, json-placeholder, wiremock anyone?) instead of the real thing.