Auparavant, j'ai construit un environnement de NGINX + NGINX Unit + Flask.
Exécutez des applications Web Python avec NGINX + NGINX Unit + Flask
La dernière fois, je l'ai construit avec Vagrant et VirtualBox, mais cette fois je vais le construire avec Docker.
Comme précédemment, utilisez NGINX
pour le serveur Web, NGINX Unit
pour le serveur AP et Flask
pour le framework.
De plus, cette fois, nous ajouterons MySQL
comme base de données et créerons un environnement pour WEB <-> AP <-> DB
.
L'image est comme indiqué dans la figure ci-dessous. (À l'origine, le conteneur commence dans l'hôte, mais il est séparé pour plus de clarté)
Nous allons le construire étape par étape, donc si vous voulez voir ce que vous avez fait, veuillez le vérifier sur GitHub.
https://github.com/txkxyx/docker-web
Nous allons construire dans l'environnement suivant.
--Hôte - OS : macOS Catalina 10.15.3 - Docker : 19.03.5 --Récipient - Python : 3.7.3 - Flask : 1.1.1 - NGINX : 1.17.7 - NGINX Unit : 1.14.0 - MySQL : 8.0.18 - Flask SQLAclchemy : 2.4.1
La structure des répertoires est la suivante.
./web
|- db //Pour DB
|- nginx //Pour NGINX
|- python //Unité NGINX pour les fichiers source
| |- src
|- docker-compose.yml
Commençons.
Voici un bref résumé des paramètres utilisés dans Dokerfile et docker-compose.
Consultez la référence officielle de Dockerfile pour plus d'informations.
https://docs.docker.com/engine/reference/builder/
Définir la valeur | Aperçu |
---|---|
FROM | Spécifiez l'image à utiliser. |
WORKDIR | Spécifiez le répertoire de travail. Après cette déclaration, le travail est effectué avec le chemin spécifié dans le conteneur. |
COPY | Copiez le répertoire ou le fichier spécifié de l'hôte vers le conteneur.Conteneur hôte Précisez dans l'ordre de..dockerignore Le fichier spécifié dans est exclu. |
RUN | Exécute la commande spécifiée dans le conteneur actuel. (Commande à exécuter au moment de la construction) |
CMD | Spécifiez la commande à exécuter au démarrage du conteneur. (Commande à exécuter au démarrage) |
Voir la référence officielle pour plus de détails.
https://docs.docker.com/compose/compose-file/
Définir la valeur | Aperçu |
---|---|
version | Version du format de fichier pris en charge par Docker Engine |
services | Chaque élément qui compose l'application |
build | Du container pour commencerDockerfile Spécifiez le répertoire où se trouve. Un élément enfant, contexte(Répertoire avec Dockerfile ou URL Github)args(Arguments à transmettre à Dockerfile)Etc. peut être spécifié. |
image | Spécifiez l'image utilisée par le conteneur à démarrer. |
command | docker-Commande exécutée lorsque la composition est exécutée |
ports | Spécifie le port que le conteneur expose.Hôte: Container Ou spécifiez uniquement le port du conteneur. |
expose | Spécifiez le port du conteneur qui est exposé uniquement au conteneur à lier. Il ne sera pas publié sur l'hôte. |
environment | Spécifiez les variables d'environnement du conteneur à démarrer. |
volumes | Spécifie le répertoire de l'hôte à monter sur le conteneur.hôte:récipient Spécifiez le chemin au format. |
container_name | Spécifiez le nom du conteneur à démarrer. |
depends_on | Spécifie les dépendances entre les services. Le nom de service spécifié démarre en premier. |
Tout d'abord, nous allons construire un conteneur MySQL. L'image ressemble à ceci.
Créez docker-compose.yml
.
web/docker-compose.yml
version: "3"
services:
db:
image: mysql
command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
ports:
- "33306:3306"
expose:
- "3306"
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_USER: test
MYSQL_PASSWORD: test
volumes:
- ./db/init:/docker-entrypoint-initdb.d
container_name: app_db
Créez un répertoire ʻinitdans le répertoire
db` et créez createdatabase.sql, comme vous le feriez au démarrage initial du conteneur.
web/db/init/createdatabase.sql
CREATE DATABASE app;
USE app;
CREATE TABLE users(
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255),
email VARCHAR(255)
);
INSERT INTO users(name,email) VALUES('sample','[email protected]');
INSERT INTO users(name,email) VALUES('test','[email protected]');
INSERT INTO users(name,email) VALUES('app','[email protected]');
GRANT ALL ON app.* TO test;
Avec les paramètres ci-dessus, démarrez le conteneur MySQL avec docker-compose.
$ docker-compose up
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bef9a864276c mysql "docker-entrypoint.s…" 4 minutes ago Up 4 minutes 33060/tcp, 0.0.0.0:33306->3306/tcp app_db
Si ʻapp_db est affiché dans le résultat de
docker ps`, le conteneur a été démarré.
Une fois à l'intérieur du conteneur, vérifiez si la base de données a été créée.
$ docker exec -it app_db bash
root@00000000000:/# mysql -u test -p
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| app |
| information_schema |
+--------------------+
2 rows in set (0.00 sec)
mysql> use app;
mysql> select * from users;
+----+--------+-------------------+
| id | name | email |
+----+--------+-------------------+
| 1 | sample | [email protected] |
| 2 | test | [email protected] |
| 3 | app | [email protected] |
+----+--------+-------------------+
3 rows in set (0.01 sec)
Vous pouvez voir qu'une base de données appelée ʻappa été créée. De plus, vous pouvez voir que la table et les données de
createdatabase.sql` ont été créées.
C'est tout pour construire MySQL.
Construisez un conteneur en utilisant NGINX Unit
comme serveur AP, Python3
comme environnement d'exécution et Flask
comme framework.
Nous le construirons en nous référant au Document officiel de l'unité NGINX.
L'image ressemble à ceci.
Tout d'abord, construisez l'environnement de Python3 et Flask à partir de l'image de NGINX Unit. Cela peut être la plus petite unité de l'environnement de développement.
Ajoutez Dockerfile
au répertoire web / python
.
web/python/Dorckerfile
FROM nginx/unit:1.14.0-python3.7
WORKDIR /usr/src/app
COPY src .
RUN apt update && apt install -y python3-pip \
&& pip3 install --no-cache-dir -r ./requirements.txt \
&& rm -rf /var/lib/apt/lists/*
CMD ["sleep","infinity"]
À partir du Docker Hub nginx / unit site, utilisez l'image NGINX Unit pour Python 3.7.
Ensuite, créez requirements.txt
dans le répertoire web / python / src
pour pouvoir installer les bibliothèques en bloc avec pip
.
web/python/src/requirements.txt
Flask == 1.1.1
flask-sqlalchemy == 2.4.1
PyMySQL == 0.9.3
Ajoutez les paramètres du conteneur de l'unité NGINX à docker-compose.yml
.
docker-compose.yml
version: "3"
services:
db:
image: mysql
ports:
- "33306:3306"
expose:
- "3306"
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_USER: test
MYSQL_PASSWORD: test
volumes:
- ./db/init:/docker-entrypoint-initdb.d
container_name: app_db
#↓ ↓ Addendum
ap:
build: ./python
ports:
- "8080:8080"
environment:
TZ: "Asia/Tokyo"
container_name: app_ap
depends_on:
- db
Le "Dockerfile" créé existe dans le répertoire web / python
, spécifiez donc l'emplacement avec build.
Le port du serveur doit exposer «8080» à l'hôte.
Arrêtez le conteneur Docker en cours d'exécution, puis compilez avec docker-compose build
, puis démarrez le conteneur.
$ docker-compose down
$ docker-compose build --no-cache
$ docker-compose up
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
daf4ddc7c11a web_ap "sleep infinity" 41 seconds ago Up 40 seconds 0.0.0.0:8080->8080/tcp app_ap
565eb32e6a39 mysql "docker-entrypoint.s…" 43 seconds ago Up 41 seconds 33060/tcp, 0.0.0.0:33306->3306/tcp app_db
Vous pouvez voir que ʻapp_db du conteneur MySQL et ʻapp_ap
du conteneur NGINX Unit sont en cours d'exécution.
Allez dans le conteneur NGINX Unit et vérifiez si la bibliothèque requirements.txt
est installée.
$ docker exec -it app_ap bash
root@00000000000:/# python3 -V
Python 3.7.3
root@00000000000:/# pip3 freeze
Flask==1.1.1
Flask-SQLAlchemy==2.4.1
PyMySQL==0.9.3
En plus des bibliothèques ci-dessus, «SQL Alchemy» et «Jinja2» sont installés. Ceci termine le démarrage du conteneur NGINX Unit. Ensuite, nous allons implémenter Flask.
Implémentez l'application Flask. Les fichiers et répertoires à créer sont les suivants.
./web
|- db
| |- init
| |- createdatabase.sql
|- nginx
|- python
| |- src
| | |- app.py ← ajouté
| | |- config.json ← ajouté
| | |- config.py ← ajouté
| | |- run.py ← ajouté
| | |- users.py ← ajouté
| | |- requirements.txt
| | |-modèles ← ajoutés
| | |- list.html ← ajouté
| |-Dockerfile ← Mise à jour
|- docker-compose.yml
Chaque fichier est implémenté comme suit.
config.py
Le premier est «config.py», qui implémente la classe de configuration telle que la destination de la connexion DB. La destination de l'hôte est spécifiée par le nom du conteneur ʻapp_db` du conteneur DB.
web/python/src/config.py
class Config(object):
'''
Config Class
'''
# DB URL
SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://test:test@app_db:3306/app?charset=utf8'
app.py
Vient ensuite ʻapp.py, qui lance l'application Flask. Utilisez
config.from_object ()pour appeler la classe de configuration de l'application, et utilisez
SQLAlchemy ()` pour initialiser l'application Flask afin que SQLAchemy puisse être utilisé.
web/python/src/app.py
from config import Config
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
# Create Flask Application
application = Flask(__name__)
# Set Config Class
application.config.from_object(Config)
# Set DB
db = SQLAlchemy(application)
users.py
Ensuite, créez la classe Model pour la table users.
Créez une classe Users qui hérite de la classe db.Model
.
web/python/src/users.py
from app import db
class Users(db.Model):
'''
Users Table Model
'''
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(255))
email = db.Column(db.String(255))
def __init__(self,name,email):
self.name = name
self.email = email
run.py
Vient ensuite le module de lancement et de routage de l'application Flask run.py
.
Puisque le fichier modèle est utilisé pour la réponse, spécifiez le fichier modèle et l'objet avec render_template ()
.
web/python/src/run.py
from app import application
from users import Users
from flask import render_template
@application.route('/list')
def index():
users = Users.query.order_by(Users.id).all()
return render_template('list.html', users=users)
if __name__ == '__main__':
application.run(host='0.0.0.0', port='8080')
list.html
Ensuite, créez un fichier modèle, list.html
.
Le render_template ()
passe l'objet ʻusers, donc implémentez-le en utilisant le moteur de template
Jinja2`.
web/python/src/templates/list.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Flask Sample</title>
</head>
<body>
<h1>Flask Sample</h1>
<table border="1" style="border-collapse: collapse">
<thead>
<tr>
<th >Id</th>
<th >Name</th>
<th >EMail</th>
</tr>
</thead>
<tbody>
{% for user in users %}
<tr>
<td>{{user.id}}</td>
<td>{{user.name}}</td>
<td>{{user.email}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>
Dockerfile
Mettez à jour Dockerfile
.
web/python/Dorckerfile
FROM nginx/unit:1.14.0-python3.7
WORKDIR /usr/src/app
COPY src .
RUN apt update && apt install -y python3-pip \
&& pip3 install --no-cache-dir -r ./requirements.txt \
&& rm -rf /var/lib/apt/lists/*
#↓ ↓ Supprimer
config.json
Enfin, ajoutez le fichier de configuration de l'unité NGINX config.json
.
web/python/src/config.json
{
"listeners": {
"*:8080": {
"pass": "applications/app"
}
},
"applications": {
"app": {
"type": "python",
"processes": 2,
"path": "/usr/src/app/",
"module": "run"
}
}
}
C'est tout pour la mise en œuvre.
Construisons puis démarrons le conteneur.
$ docker-compose down
$ docker-compose build --no-cache
$ docker-compose up
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
daf4ddc7c11a web_ap "sleep infinity" 41 seconds ago Up 40 seconds 0.0.0.0:8080->8080/tcp app_ap
565eb32e6a39 mysql "docker-entrypoint.s…" 43 seconds ago Up 41 seconds 33060/tcp, 0.0.0.0:33306->3306/tcp app_db
Après avoir démarré le conteneur ʻapp_ap`, accédez au conteneur et définissez le fichier de configuration de l'unité NGINX.
$ docker exec -it app_ap bash
root@00000000000:/# curl -X PUT --data-binary @config.json --unix-socket /var/run/control.unit.sock http://localhost/config
{
"success": "Reconfiguration done."
}
Dans votre navigateur, allez sur http: // localhost: 8080 / list
et l'écran apparaîtra.
Ceci termine la construction du conteneur AP.
Enfin, nous allons construire le conteneur NGINX pour le serveur WEB.
Cela configurera NGINX <-> NGINX Unit <-> Flask <-> MySQL
.
Les fichiers à ajouter ou à mettre à jour sont les suivants.
./web
|- db
| |- init
| |- createdatabase.sql
|- nginx
| |-Dockerfile ← ajouté
| |- index.html ← ajouté
| |- nginx.conf ← ajouté
|- python
| |- src
| | |- __init__.py
| | |- app.py
| | |- config.json
| | |- config.py
| | |- run.py
| | |- users.py
| | |- requirements.txt
| | |- templates
| | |- index.html
| |- Dockerfile
|- docker-compose.yml ← mise à jour
Commencez par créer la page principale ʻindex.html`.
web/nginx/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Index</title>
</head>
<body>
<h1>Index</h1>
<a href="/list">List</a>
</body>
</html>
Ensuite, créez un Dockerfile
pour NGINX
.
FROM nginx
WORKDIR /var/www/html
COPY ./index.html ./
CMD ["nginx", "-g", "daemon off;","-c","/etc/nginx/nginx.conf"]
Ensuite, créez un fichier de configuration NGINX. À partir du fichier de configuration présenté dans l'article précédent, modifiez l'hôte du serveur AP pour Docker.
nginx.conf
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
server_tokens off;
keepalive_timeout 65;
#gzip on;
upstream unit-python {
server app_ap:8080; # container_Spécifié par son nom
}
server {
listen 80;
server_name localhost;
#Afficher la première page
location / {
root /var/www/html;
}
# /lister les routes vers le conteneur AP
location /list {
proxy_pass http://unit-python;
proxy_set_header Host $host;
}
}
}
Enfin, mettez à jour docker-compose.
docker-compose.yml
version: "3"
services:
db:
image: mysql
ports:
- "33306:3306"
expose:
- "3306"
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_USER: test
MYSQL_PASSWORD: test
volumes:
- ./db/init:/docker-entrypoint-initdb.d
container_name: app_db
ap:
build:
context: ./python
args:
project_directory: "/src/"
#↓ ↓ mise à jour
expose:
- "8080"
volumes:
- "./python/src:/projects"
environment:
TZ: "Asia/Tokyo"
container_name: app_ap
depends_on:
- db
#↓ ↓ ajouté
web:
build: ./nginx
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
ports:
- "80:80"
environment:
TZ: "Asia/Tokyo"
container_name: "app_web"
depends_on:
- ap
Construisons puis démarrons le conteneur.
$ docker-compose down
$ docker-compose build --no-cache
$ docker-compose up
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5b0f06b89db4 web_web "nginx -g 'daemon of…" 2 minutes ago Up 23 seconds 0.0.0.0:80->80/tcp app_web
625f3c025a82 web_ap "/usr/local/bin/dock…" 2 minutes ago Up 2 minutes 8080/tcp app_ap
fe5bf54411a2 mysql "docker-entrypoint.s…" 2 minutes ago Up 2 minutes 33060/tcp, 0.0.0.0:33306->3306/tcp app_db
Après avoir démarré le conteneur app_ap, accédez au conteneur et définissez le fichier de configuration de l'unité NGINX.
$ docker exec -it app_ap bash
root@00000000000:/# curl -X PUT --data-binary @config.json --unix-socket /var/run/control.unit.sock http://localhost/config
{
"success": "Reconfiguration done."
}
Si vous accédez à http: // localhost: 80
avec un navigateur, la page principale ʻindex.html` sera affichée. (Non accessible sur le port 8080)
Si vous appuyez sur la Liste
liée, la liste.html` de l'application Flask s'affichera.
C'est la fin de la construction de NGINX.
J'ai pu créer un environnement de NGINX + NGINX Unit + MySQL avec Docker. Tout ce que vous avez à faire est de créer l'application.
Recommended Posts