Build two more services and wire all three together with Docker Compose so they talk to each other as a network. I am building a miniature version of microservices architecture.
Moving back into the directory I previously created via Powershell to continue the project:
cd ~\Desktop\autopilot-sre\phase1-containersI am going to create a new sub-directory within my project directory called auth-service. This is going to contain the code for the authentication service.
The application is going be flask (like the one in my previous blog) so for that I will create a file, app.py:
The file maps URLs to functions. For example, there is a health check endpoint at /health and a verification endpoint at /verify which is there to verify whether a user is who they claim to be (in other words, we are authenticating users).
Right now the /verify endpoint will always return true and it is not checking for any token or password. The point of this is to simulate a service that other services also depend on.
So as I build out the homelab, my api-gateway (created in the previous blog) will receive a request and call the auth-service/verify before doing anything else. If auth-service goes down, api-gateway breaks.
The auth-service runs on port 5001. The api-gateway i created in my previous blog post is running at Port 5000 so I am making sure there isn’t a clash.
from flask import Flask
app = Flask(__name__)@app.route("/")
def home():
return "auth-service is alive"
@app.route("/health")
def health():
return {"status": "ok"}
@app.route("/verify")
def verify():
return {"authenticated": True, "user": "kevin"}
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5001)
Then a requirements.txt file:
flaskAnd finally, a Dockerfile:
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "app.py"]The 3 files are ready to deploy the auth-service!
Press enter or click to view image in full size
Everything with the data-service is the same i.e. the 3 files required including app.py, requirements.txt and a Dockerfile. Except the actually app.py code is different, it has a URL /records that is mapped to a function returning some data records.
from flask import Flask
app = Flask(__name__)@app.route("/")
def home():
return "data-service is alive"
@app.route("/health")
def health():
return {"status": "ok"}
@app.route("/records")
def records():
return {
"records": [
{"id": 1, "value": "record-alpha"},
{"id": 2, "value": "record-beta"},
{"id": 3, "value": "record-gamma"}
]
}
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5002)
This app will run on Port 5002.
I decided to clean up my phase1-containers directory so that it shows clearly that I have 3 micro-services running:
Now that I have 3 micro-services ready, I will create a docker-compose.yml in my main project directory.
Join Medium for free to get updates from this writer.
This will be my configuration file. It will define all 3 of the services I have created.
Each service runs on a separate port.
Each service runs on the same network: sre-network
Each service has its own image, which will be built in the specified directories. Docker Compose will go into each of those directories to find the relevant Dockerfile needed to build the image.
Bridge is a network type in Docker that acts as a private switch inside my machine. The three containers can talk to each other through it.
version: "3.8"services:
api-gateway:
build: ./api-gateway
ports:
- "5000:5000"
networks:
- sre-network
auth-service:
build: ./auth-service
ports:
- "5001:5001"
networks:
- sre-network
data-service:
build: ./data-service
ports:
- "5002:5002"
networks:
- sre-network
networks:
sre-network:
driver: bridge
Since all three services are going to be on the same network, they will talk to each other by service name (rather than IP address) e.g.:
api-gateway can reach auth-service by calling:
http://auth-service:5001/verifyAfter running docker-compose, we can see that all three services are running:
docker-compose up --buildPress enter or click to view image in full size
Breaking down what happened. First, each of the three images were built:
Then, a private network was built.
Finally, the three containers were spun up simultaneously.
If I browse to each of the endpoints I will see that they are running with whatever message was included in the respective app.py files.
On the Docker Engine app I can see the three containers running:
Press enter or click to view image in full size
If I run the following command:
docker psThen I can see all three containers, along with status info, network info and their names:
docker-compose file was executed to build all three images and spin up all three containers.Next, I will set up Prometheus in order to scrape my services on a schedule. It will collect metrics and store them so I can query and visualize what’s happening in real time.