01 - The Driver for Change
The first thing we are going to do is run and examine a simple application. You are not expected to write any code, but we will be looking at Dockerfiles and Docker-Compose files.
The purpose of the exercise is to help you understand the structure of the application, capture it using C4, and ask architecturally significant questions.
01 The Monolith Application
Docker is an ideal tool for understanding the nature of monolithic applications without the need to have numerous physical nodes (a node is a piece of hardware)
Recap on the advantages of using Docker
Containers can be considered lightweight VMs
They are self-contained
Hermetically sealed
They expose their services through ports
They can share a common network and volume
02 Running the Monolith
Using the Gitbash terminal, navigate to
/c/work
Clone down the following projects
Start Docker
Open Windows' terminal in Admin mode (right-click on Windows Start, and select Terminal (Admin)
Navigate to
c:\work\vat_calculator_service
Enter the command
mvn package
, this will build the binary for the calculator service. A number of files will have been created in thetarget
folder. You will need the file calledvat_calculator_service-0.0.1-SNAPSHOT-spring-boot.jar
Navigate to
c:\work\react_app-vat_calculator
Create a folder called
target
Copy the file
vat_calculator_service-0.0.1-SNAPSHOT-spring-boot.jar
into thetarget
folderRun the command
docker build --tag=vat_calculator_service:latest .
the full stop is important
Run the command
docker run -p 3000:3000 -p 8080:8080 --name vatc_fe --rm vat_calculator_service
this will create a single docker container containing the 3 applications that are all wired together
03 Understanding the Monolith
Run the following commands
Use
docker ps -a
you should see the container calledvatc_fe
, and the exposed ports.Open the frontend application from the browser using the URL
localhost:3000
Select Sales, you should see some sales data
Attach to the application service from the browser using the URL
http://localhost:8080/api/v1/vatentries
. You should see some JSON data. It should be the same data that you saw when you selected theSales
menu item on the frontend app.
Before you run the next set of commands be sure that you have run the commands above 1, 2, and 3, you need to make notes of the observable results.
Run the following commands
Run
docker stop vatc_fe
Run
docker ps -a
The container should have stopped and have been removed as a container, rerun the commands 2 and 3 above
What are the observable results?
You are going to make a change to the backend (observe and make notes about the process you are about to follow)
Using the terminal navigate to c:\work\vat_calculator_service (unless you are already there)
Type code .
the full stop is important
Locate the file VATEntry.java (it’s in the folder
src/main/java/com/celestial/vatcsl/model
Replace line 37 so it looks like this
this.description = ">>>" + description + "<<<";
Save the file, and close VSC
Run
mvn package
Navigate to
c:\work\react_app_calculator
.Copy the file
vat_calculator_service-0.0.1-SNAPSHOT-spring-boot.jar
into thetarget
folderRun the command
docker build --tag=vat_calculator_service:latest .
Run the command
docker run -p 3000:3000 -p 8080:8080 --name vatc_fe --rm vat_calculator_service
this will create a single docker container containing the 3 applications that are all wired togetherUse
docker ps -a
; you should see the container called vatc_fe and the exposed ports.Open the frontend application from the browser using the URL
localhost:3000
Select Sales, you should see some sales data. The description of each sales item should be surrounded with >>> and <<<
Model what you have learnt using C4.
So what are the things that you notice and architecturally what are the PROs and CONs?
04 Monolith Breakdown
05 Monolith to Docker
06 PROs and CONs of the Monolith
07 Breaking up the Monolith
We are now going to run each component of the system as separate services
Before we run the separate components we need to clean up the previous images. Run the following commands
Run
docker images
, look for vat_calculator_service. When you find it, make a note of the first three characters of the image IDRun
docker rmi
<the three digits of the image ID>
The system should display a long number, the SHA. This indicates that the images have been removed. You are now ready to start the separate services.
Run the following commands
Make sure you are in the folder
c:\work\react_app_calculator
Run
docker-compose up
Wait until no more messages are being sent to the screen
Open another terminal window (the plus symbol next to the title of the current terminal window)
Run
docker ps -a
, look at the services that are running. You should notice that there are two services; one is calledvatc-fe
, and the other is calledvatc-service
Examine the other fields that are displayed from the
docker ps -a
commandIn your browser enter the URL
localhost:3001
, when the app is running select the Sales menu option, and you should see some dataIn your browser enter the URL
localhost:8080/api/v1/vatentries
, you should see the same data from when you select the Sales optionFrom the terminal run
docker stop vatc-service
In your browser enter the URL
localhost:8080/api/v1/vatentries
, you should see no data, this is because we have stopped the backend serverIn your browser enter the URL
localhost:3001
, when the app is running select the Sales menu option, and you should see no data, this is because the frontend runs as a separate service to the backend, we have isolated each service from the other.From the terminal run docker start vatc-service
In your browser enter the URL
localhost:8080/api/v1/vatentries
, you should see the same data from when you select the Sales optionFrom the terminal run
docker stop vatc-fe
In your browser enter the URL
localhost:3001
, it should fail to connect to the applicationIn your browser enter the URL
localhost:8080/api/v1/vatentries
, you should see the same data from when you select the Sales option, so you can still access the data even though the frontend has been stopped
Stop and start each service, examining the results in the browser. Make sure you understand what’s happening here
Services are all about the separation of concerns
Domain Driven Design is all about the separation of concerns.
08 Cloud Computing Architecture
09 AWS Example with Docker Containers
We could use a computer engine, but this would require us to select the OS (infrastructure platform) and then install all the necessary applications and libraries to run our container on that compute engine
A better approach would be to use
A container-configured environment. Point the service at the registry where the Dockerfile is located, and let it do all the heavy lifting for you.
We’ve also highlighted Red Hat OpenShift as an alternative approach. OpenShift® gives a one-stop shop to access the services of any number of cloud providers, it’s a unified platform to build, modernize, and deploy applications at scale
10 Quality of Service Attributes Gained
10-01 Scaleability
When you ran the monolith VAT application one of the main issues was its inability to scale. Whether we wanted to scale it horizontally or vertically was an issue
Vertical Scaling
Modify the Node by adding more RAM, Upgrading the CPU, and adding more Disk space. All of these options require the system to be shut down, the hardware to be installed and the system to be rebooted. After this, you could have too much capacity or too little capacity.
Horizontal Scaling
Replicate a service, and distribute the workload amongst the distributed services You would make use of something like a load balancer to ensure that traffic is evenly sent to all replicated nodes/services (the cluster).
10-01 Demo Time
The trainer will demonstrate a Docker Image being deployed onto an AWS container service. They will also show horizontal scaling at work.
10-02 Less Brittle Architecture
10-03 Maintainability
How much effort is required to maintain the system, modify it, and integrate it with other systems?
If it’s difficult to make changes then it’s not maintainable
If it’s not clear what the effect is of changing the code (the outcomes become guesswork), then it’s not maintainable
If you have to butcher the code to make it realize new scenarios whilst continuing to be what it was intended for, then it’s not maintainable
10-04 Security
A system is the sum of its parts. If each service can have its level of security (different set of security constraints), it becomes easier to secure the whole. But if the whole is a monolith, inevitably it becomes more difficult to apply security constraints around the parts.
10-05 Performance
You tune the whole by tuning the parts. That’s a basic engineering principle.
Formula 1 teams spend vast amounts of money capturing data from all the components of the car, as well as the performance of the driver. The car and driver only hit optimal performance when everything is functioning in harmony.
10-06 Cost Efficiency
The problem with the monolithic approach is that you have to tune the whole even though your intention may be to only effect a part. It then becomes very difficult to target the tuning for a single part without affecting the whole. So you end up spending money where it’s not needed. The tuning and cost management becomes much easier by componentising the system and using a micro-service architecture.
10-07 More fault-tolerant
The requirement is to make the whole fault-tolerant, but each component has different requirements for achieving fault tolerance. By tackling each part, you are tackling the whole.
10-08 Higher availability
The requirement to make the entire system highly available can only be achieved by tuning thr parts and making them highly available. If you’re dealing with a monolith, then if one part fails, then the whole fails. But if we compartmentalise the system, and reduce the coupling, then if one part fails, strategies can be put in place to ensure that the whole is not compromised.
10-09 More extensible
A system is only extensible if it is designed to be extensible. If you have a monolithic piece of code, then by it’s very nature it is not extensible. Likewise if you have a system that is comprised of many parts but the coupling between those parts is tight, then a change in one component will impact on other components. Testing one component would require testing of adjacent components etc. This is a bad design.