Summary
Microservices are becoming increasingly popular in web development due to their flexibility and scalability. In this article, we’ll show you how to create a product service using Python and Docker, two essential tools in the microservices architecture.
Understanding Microservices and Docker
In the first video of our series, we learned that an image is a template for the environment that you want to run, and when you run an image, you get a container. We used a PHP image to run a simple application, but for a more complicated one, we need to use microservices.
Traditionally, a big website like an online store would be one big application, but a newer trend is to split these big applications up into smaller microservices. A microservice architecture allows for more flexibility and scalability, making it easier to add new features and improve performance.
Creating a Product Service
In this tutorial, we’ll build a simple ecommerce website, but we’ll put the codes that provide the product and product information in their own microservice. The website will then use an API on the product service to request the list of products to show to the customer.
To begin, we’ll create a new directory for the product service called product
. We’ll write a simple Python script that will serve as the API for the service. We’ll call it api.py
.
from flask import Flask
from flask_restful import Resource, Api
app = Flask(__name__)
api = Api(app)
class Product(Resource):
def get(self):
return {
'products': [
'ice cream',
'chocolates',
'fruit'
]
}
api.add_resource(Product, '/')
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=80)
We want this to be a simple RESTful API, so we imported Flask and Flask-RESTful and instantiated these objects. We created a Product
class which extends Resource
and has a get
method that returns some JSON data. In this case, we’re returning a list of products - ice cream, chocolates, and fruit.
Running the Product Service in Docker
Now that we’ve created the product service, we can run it in Docker. First, we’ll create a <a class="wiki-link" href="/blog/en/kubernetes/docker/docker-compose-vs-dockerfile">Dockerfile</a>
:
FROM python:3-onbuild
COPY . /usr/src/app
CMD ["python", "api.py"]
The first line specifies the base image that we’ll build on top of. We’re using the official Python image and the onbuild
tag, which will automatically install any dependencies listed in the requirements.txt
file. The next line copies our source code into the image, and the last line specifies the command to run when the container starts.
To build the Docker image, we’ll run the following command:
docker build -t product-service .
This will create an image with the tag product-service
.
To run the container, we’ll use the following command:
docker run -d -p 80:80 product-service
This will start a container and map port 80 in the container to port 80 on our machine.
Using Docker Compose
As we add more services, building and running each one separately can become tedious. This is where Docker Compose comes in. Docker Compose lets us define all of our services in a configuration file, and with one command, it’ll spin up all the containers that we need.
We’ll create a <a class="wiki-link" href="/blog/en/restart-docker-daemon-a-comprehensive-guide">docker</a>-compose.yml
file in the parent directory:
version: '3'
services:
product:
build:
ChatGPT
Defining the Website Service
Now, let’s define the website
service in our <a class="wiki-link" href="/blog/en/kubernetes/docker/docker-exec-bash-example">docker</a>-compose.yml
file.
services:
product:
build: ./product
ports:
- "5001:80"
website:
build: ./website
ports:
- "5000:80"
depends_on:
- product
Similar to the product
service, we first specify the build context for the website
service. In this case, it’s the ./website
directory.
Next, we specify the ports to expose. We want to expose port 80
inside the container, so we map it to port 5000
on the host machine.
Finally, we specify that the website
service depends on the product
service. This means that docker-compose
will start the product
service before starting the website
service.
Writing the Website Code
Let’s create a new directory called website
and create a file called app.py
inside it. Here’s the code for the app.py
file:
from flask import Flask, jsonify
import requests
app = Flask(__name__)
@app.route('/')
def index():
products = requests.get('http://product:80/products').json()
return jsonify(products)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=80)
This code is very similar to the product
service code. We create a Flask app and define a route for the root URL. When a user visits the root URL, the index()
function is called.
Inside the index()
function, we make a request to the product
service using the requests
library. We then return the JSON response from the product
service.
Building and Running the Website Service
Now that we have written the code for the website
service, let’s build and run the service.
First, let’s create a Dockerfile
for the website
service. Here’s what the Dockerfile
should look like:
FROM python:3
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD [ "python", "app.py" ]
This Dockerfile
is very similar to the product
service Dockerfile
. We start with the official Python 3 image, set the working directory to /app
, and copy the requirements.txt
file into the container. We then install the Python dependencies using pip
.
Next, we copy the entire website
directory into the container and set the command to run python app.py
.
To build the website
service, run the following command in the root directory of the project:
docker-compose build website
This will build the website
service and create a Docker image.
To run the website
service, run the following command:
docker-compose up
This will start both the product
and website
services. You should now be able to visit http://localhost:5000/ in your web browser and see a JSON response with the list of products.
Conclusion
In this tutorial, we learned how to build a simple e-commerce website using microservices and Docker. We split our application into two services: a product
service and a website
service. We then used docker-compose
to define and run both services.
Microservices can help make your applications more scalable and easier to maintain. By splitting your application into smaller services, you can make changes to one service