I want to create an API. I want to make it with Flask + MySQL. And I want to make it Docker. Make a note of this procedure. I personally don't know how to make it Docker, so I will concentrate on this.
First, create a simple API because anything is fine. This time, I decided to make a list that returns only the data that meets the conditions from the member list (provisional).
From the file below, create a feature where prefecture returns a list of mail_addresses that match the parameters of the request.
{personal_info.csv}
mail_address,sex,age,name,prefecture
[email protected],male,18,itirou,tokyo
[email protected],male,23,zirou,osaka
[email protected],male,31,saburou,tokyo
[email protected],female,29,itiko,tokyo
[email protected],mail,11,shirou,osaka
[email protected],female,42,fumiko,tokyo
The code using Flask is here.
It's super easy, run app.py, add? Pref = xxx to http://127.0.0.1:5000/
, and mail_address matching pref = xxx will be returned in the list.
Next, make this API Docker.
"Making Docker" aims to create a Docker file, docker build to create a Docker image, and execute app.py in the container with docker run to create a state where API requests are thrown.
A Dockerfile describes the operation of "specifying the base image, describing the settings of the container to be created, and executing the command in the container" for the container you want to create.
I just want to be able to run flask in python, so I'll base it on a python image.
To run the flask code, you need the following:
--Place local source code and data in a container. --Install the required libraries.
Execute the created app.py.
The Dockerfile created with these 2-1 to 2-3 in mind is as follows.
# 2-1 Specify the base image
FROM python:3.6
# 2-2 Describe the container settings
ARG work_dir=/work #Creating variables to handle in Dockerfile
ADD pure_flask $work_dir/pure_flask #the code/work/Copy to(Note that when copying a directory, you must write the directory name on the right side.)
WORKDIR $work_dir/pure_flask # cd work_directory image
RUN pip install -r requirements.txt # requirements.Install the required libraries with txt
# 2-3 Execute the command in the container
CMD ["python", "/work/pure_flask/app.py"] #There is basically only one CMD in the Dockerfile.
requirements.txt is super easy to describe only flask.
{requirements.txt}
flask
Execute docker build -t flask: ver1 .
in the directory containing the Dockerfile in this state.
The above command. Refers to building an image using the Dockerfile in the current directory.
Then run docker run -it -d -p 5000: 5000 flask: ver1
.
-d points to background execution, -p 5000: 5000 points to local port 5000 and port forwarding on container port 5000.
In this state, if you check with a browser at localhost: 5000 on the local machine, you can check the return of the API.
By the way, in this state, docker ps
and docker images
are as follows.
If nothing is displayed with docker ps, it may be an error, so you may understand the reason by doing docker logs [container ID]
using the container ID displayed with docker ps -a. ..
$ docker ps
> CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
> dc371c597cef flask:ver1 "python /work/pure_f…" 9 minutes ago Up 9 minutes 0.0.0.0:5000->5000/tcp quizzical_margulis
$ docker images
> REPOSITORY TAG IMAGE ID CREATED SIZE
> flask ver1 b4cda0e56563 9 minutes ago 923MB
> python 3.6 138869855e44 5 days ago 913MB
Safely, 1. I was able to confirm the same operation on Docker as I made a simple API with Flask alone.
Next, get ready to use MySQL.
MySQL is also prepared with Docker. This time, I will also use Docker-compose.yaml at the same time.
Docker-compose.yaml is similar to Dockerfile, but for describing the linkage of multiple containers. Since DB is supposed to be connected, I think it is natural to write it in Docker-compose.
I want to use MySQL, so I will base it on the image of MySQL.
Initialize the MySQL configuration file and database.
Start a MySQL process.
The Dockerfile is below.
# 3-1 Specifying the base image
FROM mysql:5.7
# 3-2 Describe the container settings
COPY conf.d/mysql.cnf /etc/mysql/conf.d/mysql.cnf #Set of character code settings
COPY initdb.d/init.sql /docker-entrypoint-initdb.d/init.sql #Set of SQL files for initialization
The config file and init.sql copied in the Dockerfile are as follows.
{mysql.cnf}
[mysqld]
character-set-server=utf8
[mysql]
default-character-set=utf8
[client]
default-character-set=utf8
{init.sql}
CREATE TABLE `personal_info` (
mail_address VARCHAR(100) NOT NULL,
sex VARCHAR(6) NOT NULL,
age INT NOT NULL,
name VARCHAR(50) NOT NULL,
prefecture VARCHAR(50) NOT NULL,
createdAt DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updatedAt DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (mail_address)
);
INSERT INTO `personal_info` (mail_address, sex, age, name, prefecture, createdAt, updatedAt)
VALUES
('[email protected]', 'male', 18, 'ichirou1' , 'tokyo', current_timestamp(), current_timestamp()),
('[email protected]', 'male', 23, 'zirou2', 'osaka', current_timestamp(), current_timestamp()),
('[email protected]', 'male', 31, 'saburou', 'tokyo', current_timestamp(), current_timestamp()),
('[email protected]', 'female', 29, 'itiko', 'tokyo', current_timestamp(), current_timestamp()),
('[email protected]', 'mail', 11, 'shirou', 'osaka', current_timestamp(), current_timestamp()),
('[email protected]', 'female', 42, 'fumiko', 'tokyo', current_timestamp(), current_timestamp());
docker-compose.yaml is below.
version: '3' # docker-compose.Description version of yaml
services:
db:
build: mysql #Specify Dockerfile under mysql directory
container_name: db_server #The name of the Docker container
ports:
- '3306:3306' #Specify port forwarding
environment: #Setting environment variables
MYSQL_ROOT_PASSWORD: pass #MySQL root user password
MYSQL_DATABASE: testdb #MySQL schema
TZ: Asia/Tokyo #Specifying the time zone
volumes: #Volume mount for persisting MySQL data
- db-data/:/var/lib/mysql
# 3-3 Execute the command in the container
command: mysqld #Executing the mysqld command
volumes:
db-data:
Once you have done the above, start the db container with docker-compose up -d
.
After that, log in with docker exec -it [container ID] / bin / bash
, enter the password from mysql -u root -p
to check the table, and if the contents of init.sql are included, it's OK. ..
If the data is not saved in the volume for persisting the MySQL data, check the volume with docker volume ls on the Docker host, delete it, and then docker-compose up -d.
Copy init.sql to /docker-entrypoint-initdb.d/.
Next, connect flask and MySQL.
Combine the two Docker containers created in 2 and 4. All you need to do to combine them is:
--Flask is also included in docker-compose.yaml. --Allow a connection from flask to MySQL (network). --Allows a connection from flask to MySQL (code).
Below is the flask container added to MySQL docker-compose.yaml.
version: '3'
services:
api:
build: python
container_name: api_server
ports:
- "5000:5000"
tty: yes
environment:
TZ: Asia/Tokyo
FLASK_APP: app.py
depends_on: #The api server starts after the db server is up and running
- db
networks: #Common network specification for connecting api and db
- app_net
db:
build: mysql
container_name: db_server
ports:
- '3306:3306'
environment:
MYSQL_ROOT_PASSWORD: pass
MYSQL_DATABASE: testdb
TZ: Asia/Tokyo
volumes:
- ./db-data:/var/lib/mysql
command: mysqld
networks:
- app_net
volumes:
db-data:
networks:
app_net:
driver: bridge
Describe api as the same hierarchy as db in the hierarchy directly under services.
When starting two containers and connecting between them, it is necessary to handle the two containers on the same network. Add the following to each service in docker-compose.yaml of 4-1.
networks:
- app_net
This allows you to specify which network each container will use. It means that the two are on the same network. Then, write the following in the top level hierarchy of docker-compose.yaml.
networks:
app_net:
driver: bridge
This means creating a docker network, and specifying to create a driver with the bridge specification. Now that the api and db containers are on the same network, you can connect from the api to the db.
Fix code and module on flask side. There seem to be various ways to connect to MySQL from python, but this time I used mysqlclient.
Install mysqlclient with pip install mysqlclient
and connect with the following code to use it.
import MySQLdb
conn = MySQLdb.connect(user='root', passwd='pass', host='db_server', db='testdb')
cur = conn.cursor()
sql = "select * from personal_info;"
cur.execute(sql)
rows = cur.fetchall()
Tuples are returned to these rows, and tuples with the length of the number of records can be obtained.
{Image of rows.}
(
(Value in the first column of the first record,Value in the second column of the first record, ...),
(Value in the first column of the second record,Value in the second column of the second record, ...),
(Value in the first column of the third record,Value in the second column of the third record, ...)
)
An image that receives this with python, stores it in a list, and returns it with json.
The modified source is here. Please refer to this for the directory structure and the location of the Dockerfile.
After that, since the number of modules I want to handle with python has increased, add mysqlclient to requirements.txt.
That's it.
After starting everything with docker-compose up -d
, you can check the result by entering http://0.0.0.0:5000/?pref=osaka
etc. locally.
that's all.
Recommended Posts