Home

Awesome

Microservices oriented application example

Intro

This project contains several implementation examples of habitual patterns to build a microservices oriented application with ASP.NET core, Docker and Angular. I took much inspiration from the .Net Microservices Architecture eBook. Contains examples about Domain-Driven-Design, S.O.L.I.D. and CQRS patterns.

alt text

Requirements:

Build/publish the NET projects:

$ dotnet publish

You have to generate the certificates, the system needs the certificates in the following positions:

Use the environment variables in the docker configurations file to edit the certificates file name

See this link for more info about certificates generation.

See this link for more info about the .pfx format.

Install this certificates in your dev computer or allow them on demand.

Setup AWS credentials into a file \aws.dev\credentials for all the orders, catalog and basket projects.

See the AWS Docs.

How to build and run the solution:

With docker-compose, build and run:

$ ENV=prod docker-compose -f <dockerstack-to-build>/<docker-compose-file-name>.yml up --build

The ENV variable is set to build the angular project correctly:

Then customize your system hosts file to setup the DNS resolution or edit the source files

Using Docker swarm. Deploy all services to a docker swarm with a logs analyzer stack (Important: Deploy the system stack first):

$ docker stack deploy -c dockerstack-system/docker-stack.yml <stack-name>
$ docker stack deploy -c dockerstack-application/docker-stack.yml <stack-name>

Navigate to https://your-docker-host-name-or-ip/

Authentication:

I used Json Web Token with public/private key signature (RSA256) to keep the users authenticated RFC doc.

First, SPA retrieve from the authentication service an access token. It'll be expire in one week (7 days). Every hour and every time the user open the web application a new token will be retrieved from the token renew endpoint. This strategy seems acceptable for a web application.

Initial incpit from this discussion.

Databases:

I'm using Ms SQL with a mapping volume on the host machine. "dotnet ef migrations" for the database versioning.

To store basket and integration event instance and handlers processing status informations I'm using a redis docker image.

Dev notes about the frontend:

The frontend is a single page application built by angular-cli, I changed the ng serve command in the package.json file to accept two configuration:

.1 Run the webpack-dev-server with a local backend services (ex. if you want to debug a service locally with the frontend as client). Configure the proxy with the desired redirects for the routes, for example I want to debug the login page using the authorization service run locally:

  {
    "/api/token": {
        "target": "https://localhost:443",
        "secure": false,
        "changeOrigin": true,
        "logLevel": "debug"
    }
  }

(proxy.config.local.json)

$ npm run start

.2 Or run the webpack-dev-server with the backend run on the docker host

$ npm run start-docker

(see proxy.config.docker.json)

Others options are the same from angular-cli docs

How to debug a remote container:

For example, to debug the auth_service: look at the Dockerfile.debug version. I added the sshd support. Then you can attach remotely over a ssh tunnel with your ide. Notes the port mapping '2222:22' to avoid conflicts with the host's ssh server.

Use the correct version of docker-compose file to overwrite the configurations, like:

$ docker-compose -f docker-compose.dev.yml -f docker-compose.debug.yml up --build -d

Execute, on the docker host the ssh server of the container

$ docker exec -it <container-id> "/usr/sbin/sshd"  

Copy the ssh key to the docker container, look into the 'scripts' folder. Remember that you can reach the ssh server of the container through the docker-host port mapped (2222 in this case).

$ ssh-copy-id -p 2222 -i your_public_key.pub -o "UserKnownHostsFile=/dev/null" -o "StrictHostKeyChecking=no" root@<docker-host-ip>

If you are using vs code, you can now use the launch.json settings to attach to the remote container and select the correct process (example configuration).

{
    "version": "0.2.0",
    "configurations": [  
    {
        "name": ".NET Core Remote Attach",
        "type": "coreclr",
        "request": "attach",
        "processId": "${command:pickRemoteProcess}",
        "pipeTransport": {
            "pipeCwd": "${workspaceRoot}",
            "pipeProgram": "ssh",
            "pipeArgs": ["-p", "2222", "-i", "<your-.ssh-path>/id_rsa_clrdbg", "-T", "root@<docker-host-ip>"],
            "debuggerPath": "/root/vsdbg/vsdbg",
            "quoteArgs": true
        },
        "sourceFileMap": {
                "<your-solution-folder>": "${workspaceRoot}"
        }
    }]
}