eShopOnContainers - Part 1 (Docker Compose)
eShopOnContainers is a reference application for .NET Core, developed by Microsoft, that utilizes a simplified microservices architecture and Docker containers. In this write-up, I aim to fill in some information gaps in their documentation. Among the repository's contents are two frontend web applications, webmvc and webspa, and I will provide a comprehensive overview of the webmvc end-to-end process.
The below wiki link of eShopOnContainers repo covers the setup steps on Docker Desktop on windows.
If you, like me, have become disconnected from MVC, these four videos (each 20-30 minutes in length) can help you review fundamental MVC concepts such as RenderBody, Layout, Partial View, RenderPartial, and more.
ViewStart in MVC
Layout View in MVC
Partial Views in MVC
HTML Render and Render Partial in MVC
Additionally, the following video provides an explanation of how Envoy Proxy operates. While Envoy is commonly associated with Istio's service mesh, in this instance, it is employed as a standalone service rather than a sidecar.
It's important to note another significant point before we begin debugging the application: the container exposes external and internal ports, which are specified as (external:internal).
External port is useful for accessing outside of Docker compose for testing service individually. Services within Docker compose never use the external port for communication, instead, it uses the internal port.
Similarly, localhost is never used within the docker-compose as a network address. This might confuse you with logic - if the container can be accessed using localhost on an external port then why can't the other container within the docker network can access other services using localhost on the external port? So, stressing again, if you want to connect from one service to other services within docker-compose then use the container/service name. Docker network has the great capability to map container/service names with the correct IP address.
The network named bridge is a special network. Unless you tell it otherwise, Docker always launches your containers in this network. And if you want to know Which network is your application running under? Inspect the application to verify that it is running in the default bridge network.
$ docker inspect --format='{{json .NetworkSettings.Networks}}' <container>
Example:
You can also get these details in the visual studio console.
Run eShopOnContainers locally (Development Environment)
docker-compose.yml: This file contains the definition of all images needed for running eShopOnContainers.
docker-compose.override.yml: This file contains the base configuration for all images of the previous file
The standard way to start eShopOnContainers from CLI is:
docker-compose -f docker-compose.yml -f docker-compose.override.yml
This will start eShopOnContainers with all containers running locally, and it is the default development environment.
Debugging and Code Walkthrough
Open eShopOnContainers-ServicesAndWebApps.sln in Visual Studio. Ensure Docker Compose is startup project and then start debugging. This will open webmvc app in browser(localhost:5100).
I am keeping break points at multiple lines across the solution. The below line of code indicates MVC default route is the Catalog controller of MVC app.
So, it's hitting the Index of Catalog controller and calling Catalog Service to get the data.
Now comes the interesting point, it shows MVC is trying to connect webshoppingapigw for data. If you browse the given URL in your local machine it won't work, however, if you use localhost and webshoppingapigw external port this will return the date.
The second important point in the above screenshot is, from where PurchaseUrl is coming, the reason being it's not available in appsetting.json.
The answer is PurchaseUrl is being passed to webmvc as an environment variable.
Now, you might be thinking there is no such app as webshoppingapigw. Then what is this URL? The answer is it's container running envoy proxy -
Below you can see port "5202:80", this is the listner configuration. You can use 5202 to test on localhost but the container will use port 80 to connect.
If you know envoy, you can understand we are defining \c\ as the route to the catalog cluster.
And the cluster is defined to use catalog-api:80 as a socket-address.
Fare enough, it's now hitting CatalogController of Catalog.API -
And api is returning the below data to webMVC -
And receiving the same in webMVC -
Now the data is available for the MVC view. We have the following screenshots which is used to return HTML to render in the browser.
The following cshtml files are used for html rendering -
The RenderBody is defined in Index.cshtml.
The _viewStart.cshtml page is a special view page containing the statement declaration to include the Layout page. Instead of declaring the Layout page in every view page, we can use the _ViewStart page.
RenderBody is where the index.cshtml content is placed.
Below is an example of a Partial view.