This module uses docker-compose to build and run an application that exposes a MySql database through a Python API.
.
├── app
│ ├── app.py
│ ├── Dockerfile
│ └── requirements.txt
├── db
│ └── init.sql
├── build.sh
├── docker-compose.yml
└── README.md
- What Defines an API.
- Why To interact with a database.
- How Docker-compose to connect a Flask API to a MySql DB, each running in its own container.
- Make sure you have
docker
anddocker-compose
installed on the machine running the build.- link for docker
- link for docker-compose
To start the database and run the API, run the following commands:
- Build the application:
(sudo) docker-compose build
- Run the build:
docker-compose up
In some cases, this may raise errors, f.e., because the image is not being rebuilt, or an previous underlying process is using the configured port.
-
To simplify this, force a clean build and run the application:
./build.sh
The API
- The API uses two different containers:
- the app and,
- the db.
Database
-
The db directory has a
init.sql
script that:- initiates the database,
- creates a table and,
- inserts some data into it.
-
This script is executed when running
docker-compose up
.
APP
-
The app directory has:
- app.py - the application logic,
- Dockerfile - how to build the application,
- requirements - the dependencies.
-
The Dockerfile
- defines the base image (Python3.6)
FROM python:3.7-alpine
- exposes a PORT (to communicate with exterior world)
EXPOSE 5000
- creates working directory and copies target files
WORKDIR /app COPY app.py /app COPY requirements.txt /app
- installs dependencies
RUN pip install -r requirements.txt
- runs the app
CMD ["python", "app.py"]
- defines the base image (Python3.6)
-
The app
- sets an http listener (port 5000)
if __name__ == '__main__': app.run(host='0.0.0.0')
- configures the database access details
config = { 'user': 'root', 'password': 'root', 'host': 'db', 'port': '3306', 'database': 'people' }
- defines a route and returns the corresponding resource
@app.route('/') def index(): #get user data payload = get_payload() return json.dumps(payload)
- interacts with the database according to the selected route
def get_payload(): # Establish connection to DB connection = mysql.connector.connect(**config) cursor = connection.cursor() # Get data get = 'SELECT * FROM developers' cursor.execute(get) # Construct response response = [{ "user": { "name": name, "age": age } } for (user_id, name, age) in cursor] # Close connection cursor.close() connection.close() # Respond return results
- sets an http listener (port 5000)
docker-compose.yml
- The docker-compose creates two services:
- the app - build from custom image, link to database, and maps containers ports to host ports.
app: build: ./app links: - db ports: - "5000:5000"
- the db - build from dockerhub image, maps ports, defines db password using environmental variables, and exposes a vaolume (not sure why this last is necessary).
db: image: mysql:5.7 ports: - "32000:3306" environment: MYSQL_ROOT_PASSWORD: root volumes: - ./db:/docker-entrypoint-initdb.d/:ro
- the app - build from custom image, link to database, and maps containers ports to host ports.
- tutorial that was followed during the development of this project.
- docker stuff
- install docker-compose)
- docker cmd vs run
- force docker-compose rebuild