Page 36 - MSDN Magazine, April 2017
P. 36
Also in version 2 there’s a shared messaging project that abstracts the details of the message queue, and a console application that listens for the event published by the Web app and saves the user’s data to the database. The persistence code in the console app is directly lifted from the version 1 code in the Web app, so the implementation is the same but the design of the feature has been modernized.
The new version of the application is a distributed solution with many working parts, as shown in Figure 2.
The Docker platform treats distributed applications as first- class citizens.
There are dependencies between the components, and they need to be started in the correct order for the solution to work properly. This is one of the problems of orchestrating an application running acrossmanycontainers,buttheDockerplatformdealswiththatby treating distributed applications as first-class citizens.
Orchestrating Applications with Docker Compose
Docker Compose is the part of the Docker platform that focuses on distributed applications. You define all the parts of your appli- cation as services in a simple text file, including the dependencies between them and any configuration values they need. This is part of the Docker Compose file for version 2, showing just the configuration for the Web app:
product-launch-web:
image: sixeyed/msdn-web-app:v2 ports:
- "80:80" depends_on:
- sql-server
- message-queue networks:
- app-net
Here, I’m specifying the version of the image to use for my Web application. I publish port 80 and then I explicitly state that the Web app depends on the SQL Server and message queue containers. To reach these containers, the Web container needs to be in the same virtual Docker network, so all the containers in the Docker Compose file are joined to the same virtual network, called app-net.
Elsewhere in the Docker Compose file I define a service for SQL Server, using the Microsoft image on Docker Hub, and I’m using the NATS messaging system for my message queue service, which is a high-performance open source message queue. NATS is avail- able as an official image on Docker Hub. The final service is for the message handler, which is a .NET console application packaged as a Docker image, using a simple Dockerfile.
Now I can run the application using the Docker Compose command line:
docker-compose up -d
Then Docker Compose will start containers for each of the components in the right order, giving me a working solution from a single command. Anyone with access to the Docker images and the Docker Compose file can run the application and it will behave
in the same way—on a Windows 10 laptop, or on a Windows Server 2016 machine running in the datacenter or on Azure.
For version 2, I made a small change to the application code to move a feature implementation from one component to another. The end-user behavior is the same, but now the solution is easily scalable, because the Web tier is decoupled from the data tier, and the message queue takes care of any spikes in traffic. The new design is easy to extend, as well, as I’ve introduced an event-driven architecture, so I can trigger new behavior by plugging in to the existing event messages.
Adding Self-Service Analytics
For my sample app, I’m going to make one more change to show how much you can do with the Docker platform, with very little effort. The app currently uses SQL Server as a transactional database, and I’m going to add a second data store as a reporting database. This will let me keep reporting concerns separate from transactional concerns, and also gives me free choice of the technology stack.
In version 3 of the sample code, I’ve added a new .NET console app thatlistensforthesameeventmessagespublishedbytheWebapplica- tion. When both console apps are running, the NATS message queue will ensure they both get a copy of all events. The new console app receives the events and saves the user data in Elasticsearch, an open source document store you can run in a Windows Docker container. Elasticsearch is a good choice here because it scales well, so I can clus- ter it across multiple containers for redundancy, and because it has an excellent user-facing front end available called Kibana.
I haven’t made any changes to the Web application or the SQL Server message handler from version 2, so in my Docker Com- pose file I just add new services for Elasticsearch and Kibana, and for the new message handler that writes documents to the Elasticsearch index:
index-prospect-handler:
image: sixeyed/msdn-index-handler:v3 depends_on:
- elasticsearch
- message-queue networks:
- app-net
Docker Compose can make incremental upgrades to an appli- cation, and it won’t replace running containers if their definition matches the service in the Docker Compose file. In version 3 of the sample application, there are new services but no changes to the existing services, so when I run docker-compose up –d, Docker will run new containers for Elasticsearch, Kibana and the index message handler, but leave the others running as is—which makes for a very safe upgrade process where you can add features without taking the application offline.
This application prefers convention over configuration, so the host names for dependencies like Elasticsearch are set as defaults in the app, and I just need to make sure the container names match in the Docker Compose setup.
When the new containers have started, I can use “docker inspect” to get the IP address of the Kibana container, and browse to port 5601 on that address. Kibana has a very simple interface and in a few minutes I can build a dashboard that shows the key metrics for people signing up with their details, as shown in Figure 3.
24 msdn magazine
Containers