MEAN stack web app architecture with Github & Dockerhub

Hi all,

I’m relatively new to docker and am struggling to get my head around how it is supposed to be implemented.

I’ve been doing a course on Pluralsight and it’s confused me a little. When I downloaded the source files for the course, all the code for the Database, Web API and Web App were part of the same folder structure.

I’ve been under the impression that Docker helps to decouple your architecture. Taking the MEAN stack as an example I would expect this to translate into 3 services (images):

  • A service for the database
  • A service for the Node API
  • A service for the Angular App and Web Server

Logically (at least to me) that would translate to 3 separate repos on Github. I’ve drawn what I think this should look like. The flow is:

  • Developer pushes changes to GitHub
  • CI process checks that tests pass etc…
  • CI process triggers build on DockerHub
  • CI process pushes image changes to Dev Environment

I’ve read up a bit on docker compose and have seen how this can help speed up deployment of a micro service architecture in non-prod environments. But if the project structure is as defined above, where abouts would the docker-compose.yml file sit?

Apologies for the length of the post, just trying to sort out the fundamentals in my head. To sum up I’m asking:

  1. Does the flow / architecture I’ve drawn in the diagram make sense for a MEAN stack web app?
  2. What should the folder structure look like for the micro service architecture? Should all the services be separated into their own git repos? If so, where does the docker-compose.yml file sit?

Appreciate all / any help you can give.

Your proposed architecture looks fine. Probably the reason that the tutorial built a monolith is because it’s easier to teach concepts that way without introducing distributed architecture into the mix, but you are correct in breaking these out into web ui, back end, and database services.

One of the goals of moving to a microservice architecture is that the services are loosely coupled. So they should definitely be in their own git repo as you have suggested. The lifecycle of each microservice is independent of the application itself. For example: You want to be able to make changes to the Node.js back-end without having to redeploy the web ui or database. This implies that each one should have their own CI/CD pipeline. When a push is made to one, it should redeploy (once all the tests pass) only that one service without affecting the others. That is one of the benefits of breaking up the monolith into microservices… you only deploy what changes (which is what I think your diagram is showing).

Where to put the docker-compose file is a great question! There is no one answer but let me give you my perspective on it. What is the application? When you have a monolith the answer is pretty simple… the whole thing is the application. But what about when you have microservices? Are all three the application? Is the web ui the application and the others are just supporting services? What if the application architecture was a bit more complex and there were other services that were also used in other applications? Now the definition of “the application” is more fuzzy.

I like to think of the application as a collection of microservices and therefore you need something to represent the collection. What I would do is create a fourth git repo to represent the application. That’s where I would place the docker-compose.yml file. Then I would use git submodule add ... to add the other git repos to the application repo as submodules. I think this is a good use of submodules. This keeps everything clean and separate. It also gives you a place to track Issues about the overall application that aren’t particular to any one microservice. You could then use ZenHub to link all of the kanban boards together but that’s another topic. :wink: Your docker-compose file would build from the folders that represent the submodules.

You would do something like this:

    $ mkdir myapp && cd myapp
    $ git init
    $ git submodule add web-ui
    $ git submodule add backend
    $ git submodule add database

This will create a web-ui, backend, and database folder under the root of your project. Now you can create a docker-compose.yml file to built from the respective Dockerfiles. Your docker-compose file would look something like this:

  build: web-ui
    - "80:80"
    - backend

  build: backend
    - "8080:8080"
    - db

  build: database
    - "5000:5000"

You get the idea. This assumes that each folder has a Dockerfile at it’s root. If not, just point to the relative location of the Dockerfile in the build statement. Hope that helps.