L'autre jour, j'ai créé une application Flask en utilisant docker-compose
et l'ai présentée sur Qiita.
■ J'ai créé une WebApp de jeu avec Flask + Docker + Vue.js + AWS ...
■ Le code source et les règles du jeu sont disponibles sur Github
Cette fois, j'ai fouillé dans la configuration docker-compose
dans le développement de l'application Flask.
J'espère que cela sera utile pour ceux qui envisagent de développer des applications Web avec plusieurs conteneurs: détendu:
Technologie de conteneurisation difficile à obtenir au début. Mais une fois que vous vous y êtes habitué, vous ne pouvez plus lâcher prise.
--Reproduire l'environnement avec une seule ligne de commande --Facile à créer un environnement Récupérez simplement l'image correspondante depuis Docker-Hub
--Plusieurs conteneurs peuvent être gérés les uns avec les autres.
Pourquoi ne pas l'emballer dans un seul contenant? Ce n'est pas une mauvaise chose, et en fonction de l'échelle et du contenu, un conteneur peut suffire.
Il y a de nombreux avantages à le diviser simplement en plusieurs conteneurs. Nous allons diviser les rôles en tâches de base ** 1 conteneur 1 **.
--Facile à identifier les erreurs --La charge peut être distribuée
Même une exportation rapide présente de tels avantages. Au contraire, je pense qu'il existe de nombreux cas où plusieurs conteneurs fonctionnent ensemble lors de la construction d'un système avec Docker.
Exécutez la commande dans le même répertoire que le fichier docker-compose.yml
.
Créez et contrôlez le conteneur Docker en fonction du fichier yaml.
up
Créer / démarrer plusieurs conteneurs
docker-compose up -d
-d
Démarrer en arrière-plan en mode détaché
Si vous prenez un nom de conteneur comme argument, seul ce conteneur démarrera.
docker-compose up -d hoge
#Démarrer uniquement le conteneur Hoge
kill
Arrêter de force le conteneur en cours d'exécution
docker-compose kill
down
Arrêtez le conteneur et supprimez le réseau de conteneurs créé.
docker-compose down
build
Construisez le service.
En termes simples, construisez ʻimage.
docker-compose build`
Attacher au conteneur démarré
docker exec -it ID_OR_NAME bash
La partie ʻID_OR_NAMEpeut être attachée simplement en entrant le
container_name` défini dans yaml.
Il est souvent utilisé pour l'initialisation de la base de données, la confirmation du contenu de sortie, la simple confirmation de fichier, etc. dans le conteneur.
docker-compose.yml
De là, nous aborderons le paramètre docker-compose
dans l'application Flask du sujet principal.
docker-compose.yml
version: "3"
services:
nginx:
build: nginx
container_name: nginx
ports:
- "80:80"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./docker_data/log/nginx:/var/log/nginx
depends_on:
- flask
networks:
- front
flask:
build: .
container_name: flask
environment:
# PROD, DEV, TEST
FLASK_ENV: PROD
volumes:
- .:/introdon
- ./docker_data/log/flask/gunicorn_access.log:/var/log/gunicorn_access.log
- ./docker_data/log/flask/gunicorn_error.log:/var/log/gunicorn_error.log
depends_on:
- db
- db_test
networks:
- front
- back
- test
expose:
- 5000
db:
build: db
container_name: mariadb
ports:
- "53306:3306"
volumes:
- ./db/my.conf:/etc/mysql/conf.d/my.cnf
- ./docker_data/mysql:/var/lib/mysql
- ./docker_data/log/mysql:/var/log/mysql
networks:
- back
environment:
MYSQL_DATABASE: introdon
env_file: ./db/envfile #ignorer en raison de la description du mot de passe
db_test:
build: db
container_name: mariadb_test
ports:
- "63306:3306"
volumes:
- ./db/my.conf:/etc/mysql/conf.d/my.cnf
networks:
- test
environment:
MYSQL_DATABASE: introdon_test
env_file: ./db/envfile #ignorer en raison de la description du mot de passe
networks:
front:
driver: bridge
back:
driver: bridge
test:
driver: bridge
Ce qui suit est un bref aperçu des bases.
services: Écrivez le conteneur à lancer avec un nom arbitraire. Cette fois, il y a quatre conteneurs: nginx, flask, db et db_test.
build: Écrivez la source de construction de l'image.
build: .
Construisez en fonction du Dockerfile dans le répertoire correspondant.
Dans ce cas, ce sera un Dockerfile dans le même répertoire que le fichier .
yml.
ports: Cartographie des ports avec local. Le côté gauche est local et le côté droit est le port dans le conteneur.
ports:
- "63306:3306"
Dans le cas ci-dessus, si vous vous connectez au numéro local 63306, vous serez connecté au numéro 3306 dans le conteneur.
Entrez le mappage de port sous forme de chaîne de caractères. La spécification yml reconnaît le format xx: yy comme un nombre 60-aire, et il peut être reconnu comme une heure, alors faites-en une chaîne de caractères.
Si vous devez utiliser un port qui n'est pas utilisé localement et qu'il est déjà utilisé, vous obtiendrez une erreur avec ʻup`. Si vous obtenez une erreur, vérifiez le port d'écoute.
sudo lsof -i -P | grep "LISTEN"
volumes: Liez le fichier local et le fichier dans le conteneur.
depends_on: Spécifiez le conteneur dépendant. En d'autres termes, Cela signifie "Veuillez démarrer ce conteneur après le démarrage du conteneur spécifié".
networks: Créez un réseau. Si vous spécifiez un réseau avec n'importe quel nom, vous pouvez vous connecter à un conteneur qui définit le même réseau.
networks driver: Le paramètre par défaut est «bridge». Le pilote est le suivant.
--bridge
: utilisé pour la communication sur le même hôte
Ensuite, je vais expliquer chaque conteneur individuellement. : flèche vers le bas:
Paramètres de conteneur Flask responsables du rôle de serveur d'applications.
#Extrait
flask:
build: .
container_name: flask
environment:
# PROD, DEV, TEST
FLASK_ENV: PROD
volumes:
- .:/introdon
- ./docker_data/log/flask/gunicorn_access.log:/var/log/gunicorn_access.log
- ./docker_data/log/flask/gunicorn_error.log:/var/log/gunicorn_error.log
depends_on:
- db
- db_test
networks:
- front
- back
- test
expose:
- 5000
Le conteneur est construit à partir du Dockerfile dans le même répertoire. Le nom du conteneur est flask.
Le mode de l'application est modifié par la variable d'environnement FLASK_ENV
.
--PROD: Mode environnement de production, utilisant Gunicorn avec WSGI --DEV: mode de développement. Les erreurs et le contenu de débogage sont affichés, et le rechargement automatique est également effectué. --TEST: pytest est exécuté. Utiliser un conteneur DB pour les tests
volumes:
--flask Volume le code de l'application dans un conteneur. --Créez un répertoire docker_data sur votre hôte pour conserver les journaux d'accès et les journaux d'erreurs de Gunicorn.
depends_on Démarrez le conteneur d'application après le démarrage des conteneurs db et db_test. Il démarre uniquement le conteneur et ne surveille pas le démarrage interne. Il est courant d'exécuter des tests et d'obtenir des erreurs avant que la base de données du conteneur dépendant ne soit active. Dans ce cas, attendez quelques secondes, puis démarrez-le et il sera testé avec succès.
networks --front: Connexion avec Nginx, qui est responsable du serveur Web --back: il sera connecté au conteneur DB de production. --test: Ce sera une connexion avec le conteneur DB pour le test.
expose Exposez le port uniquement au service lié. Dans ce cas, seuls le serveur Web avant, le serveur DB arrière et le serveur de test DB de test sont accessibles avec PORT: 5000. Il n'est pas accessible depuis l'environnement hôte avec PORT: 5000.
Dockerfile Un Dockerfile pour le conteneur Flask qui exécute le serveur d'applications.
FROM python:3.8
WORKDIR /introdon
COPY Pipfile ./
COPY Pipfile.lock ./
RUN pip install pipenv && \
pipenv install --system
ENV PYTHONPATH /introdon
CMD ["./flask_env.sh"]
FROM python:3.8 Construire en utilisant l'image spécifiée officielle de la version 3.8 de python
Utilisez Pipfile pour installer le package python avec pipenv.
pipenv install --system
Installez directement sur le système avec --system
sans utiliser l'environnement virtuel python.
Au moment de la construction, un avertissement s'affiche indiquant "Il n'y a pas d'environnement virtuel", mais il n'y a pas de problème car il est installé directement.
Si vous êtes curieux, vous pouvez créer requirements.txt et l'installer avec pip.
En utilisant pipenv, vous pouvez gérer et reproduire strictement les packages dépendants et leurs versions.
CMD ["./flask_env.sh"]
Lorsque le conteneur est en place, j'exécute flask_env.sh
.
Dans ce fichier shell, le mode "production, mode développement, test" est séparé en fonction de la variable d'environnement et l'application est lancée.
Un conteneur qui joue le rôle d'un serveur Web.
#Extrait
nginx:
build: nginx
container_name: nginx
ports:
- "80:80"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./docker_data/log/nginx:/var/log/nginx
depends_on:
- flask
networks:
- front
ports: Il est défini sur 80:80 pour la sortie de production. Si l'environnement hôte entre en collision avec le numéro 80 au stade du développement, vous pouvez modifier le côté gauche du côté hôte pour le développement.
volumes: Le fichier de paramètres enregistré sur l'hôte est chargé côté conteneur. J'ai enregistré les données du journal Nginx sur l'hôte et je les ai rendues persistantes.
plus tard, Démarrez le conteneur nginx après le démarrage du conteneur de flacon Vous êtes dans le réseau frontal et connecté au conteneur flask.
Dockerfile C'est court, mais voici le Dockerfile.
FROM nginx:1.17.9
CMD ["nginx", "-g", "daemon off;", "-c", "/etc/nginx/nginx.conf"]
Le volume / etc / nginx / nginx.conf
est démarré en tant que fichier de configuration.
Un conteneur qui joue le rôle d'un serveur de base de données.
#Extrait
db:
build: db
container_name: mariadb
ports:
- "53306:3306"
volumes:
- ./db/my.conf:/etc/mysql/conf.d/my.cnf
- ./docker_data/mysql:/var/lib/mysql
- ./docker_data/log/mysql:/var/log/mysql
networks:
- back
environment:
MYSQL_DATABASE: introdon
env_file: ./db/envfile #ignorer en raison de la description du mot de passe
Mappage de PORT avec 53306: 3306.
volumes: Le fichier de paramètres enregistré sur l'hôte est en cours de lecture. De plus, les données mysql sont conservées en les enregistrant du côté hôte. Le journal est également séparé en répertoires et enregistré du côté hôte.
networks: Je suis connecté au conteneur flask via un réseau «back».
environment:
Le nom de la base de données et d'autres choses que tout le monde peut voir sont décrits dans yaml tels quels.
Les éléments que vous souhaitez garder secrets, tels que les noms d'utilisateur et les mots de passe, sont lus comme des fichiers séparés.
env_file: ./db/envfile
Dockerfile Vous trouverez ci-dessous le Dockerfile.
FROM mariadb
RUN apt-get update && \
apt-get install -y locales && \
rm -rf /var/lib/apt/lists/* && \
echo "ja_JP.UTF-8 UTF-8" > /etc/locale.gen && \
locale-gen ja_JP.UTF-8
ENV LC_ALL ja_JP.UTF-8
Je veux utiliser le japonais pour DB, donc installez locale
sur le système d'exploitation du conteneur et
Je change les paramètres régionaux en ja_JP.UTF-8
.
my.conf Il s'agit d'un fichier de paramètres à charger dans le conteneur.
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci
general_log_file=/var/log/mysql/mysql.log
general_log=1
[client]
default-character-set=utf8mb4
[mysqld]
C'est le réglage du côté de mysql deamon.
Réglez sur UTF8.
Définissez également la destination de sortie du journal.
Définissez general_log
sur 1 ou ON
pour activer la sortie du journal du SQL exécuté.
S'il n'est pas spécifié, ou s'il vaut 0 ou «OFF», la sortie du journal sera désactivée.
[client] Il s'agit du paramètre côté client de la source de connexion. Ici aussi, le code de caractère est défini sur UTF8.
envfile Il s'agit d'un fichier séparé pour les paramètres spécifiés par ʻenv_file` dans le fichier yml.
MYSQL_ROOT_PASSWORD=XXXXXXXXX
MYSQL_USER=XXXXXXXXX
MYSQL_PASSWORD=XXXXXXXXX
Vous pouvez l'ignorer de la gestion des versions en le séparant en fichiers.
Je voulais combiner les fichiers référencés par le mot de passe en un seul, donc Ce fichier d'environnement est utilisé non seulement pour créer le conteneur DB, mais également pour définir la connexion DB dans le conteneur flask.
J'ai utilisé le package python-dotenv
pour lire du côté flask.
introdon/config_flask.py
import os
from dotenv import load_dotenv
load_dotenv('db/envfile')
MYSQL_USER = os.environ['MYSQL_USER']
MYSQL_PASSWORD = os.environ['MYSQL_PASSWORD']
(1) Utilisez la méthode dotenv load_dotenv pour importer le contenu du fichier env dans la variable d'environnement. (2) Depuis os.environ, spécifiez avec la clé et obtenez la variable d'environnement correspondante ③ Connectez-vous au conteneur DB avec SQL Alchemy en utilisant l'utilisateur et le mot de passe obtenus.
Il existe des opportunités inattendues de connexion au conteneur DB démarré, telles que l'acquisition et la confirmation de données. Il existe plusieurs façons de connecter un conteneur DB.
CLI Il existe deux types de connexions avec des commandes.
① Attachez-vous au conteneur et connectez-vous à la base de données
#Attacher au conteneur
docker exec -it mariadb bash
#Après la connexion, connectez-vous à la base de données
mysql -uXXXXX -pXXXXX
② Connectez-vous directement à la base de données
mysql -h 127.0.0.1 -uXXXXX -pXXXXX -P 53306
127.0.0.1 est l'adresse de bouclage locale. C'est un soi-disant hôte local.
Utilisez PORT: 53306 avec -P 53306
.
53306 est le port côté hôte spécifié pour être mappé au conteneur de base de données dans le fichier yml.
Après ①②, vous pouvez parcourir et acquérir des données en opérant dans mysql.
Intellij C'est ennuyeux de le saisir à chaque fois avec CLI, je veux le parcourir dans un tableau comme Excel. ..
Avec Intellij (Jetbrains IDE), il est facile à configurer, et une fois configuré, la navigation et l'édition sont aussi faciles que de toucher Excel. (Peut-être que Visual Studio a une fonctionnalité similaire)
Il a été traité dans des articles précédents, veuillez donc vous y référer. [Résumé de la méthode de configuration pour faire fonctionner AWS à partir d'IntelliJ (Jetbrains). Connexion facile avec #DB](https://qiita.com/akinko/items/d7001a8fe3ac87e1790c#db%E3%81%A8%E3%81%AE%E7%B0%A1%E5%8D%98%E6% 8E% A5% E7% B6% 9A) Dans l'article AWS, pas local MongoDB, pas MariaDB Il y a une différence, mais vous pouvez vous connecter au conteneur DB simplement en changeant la partie marquée en rouge. Le contenu d'entrée utilise (2) une boucle ou un port local.
Le conteneur DB sur AWS a la même méthode de connexion que local. Cependant, il est beaucoup plus facile de connecter AWS à Intellij (IDE).
Avec la CLI, après la connexion ssh à AWS, vous pouvez enfin accéder aux données de base de données en effectuant des opérations SQL avec mysql. Comme vous le savez, il est acquis dans la notation difficile à lire de mysql.
Ceci est également [Ancien article](https://qiita.com/akinko/items/d7001a8fe3ac87e1790c#db%E3%81%A8%E3%81%AE%E7%B0%A1%E5%8D%98%E6%8E Si vous le définissez en référence à% A5% E7% B6% 9A), vous pourrez le gérer facilement en un clic, comme en ouvrant Excel.
En passant, je vais brièvement aborder le conteneur DB pour le test. C'est presque le même que le serveur DB.
#Extrait
db_test:
build: db
container_name: mariadb_test
ports:
- "63306:3306"
volumes:
- ./db/my.conf:/etc/mysql/conf.d/my.cnf
networks:
- test
environment:
MYSQL_DATABASE: introdon_test
env_file: ./db/envfile #ignorer en raison de la description du mot de passe
Il n'est pas nécessaire de conserver les données, il suffit de lire le fichier de configuration. Pour éviter les accidents, le nom DATABASE a été changé en introdon_test, qui est différent du nom réel.
Intellij (utilisant IDE) est recommandé non seulement pour connecter le conteneur de base de données, mais également pour exploiter et gérer Docker.
Vous pourrez l'utiliser avec la souris depuis la barre latérale d'IntelliJ. Vous pouvez également vérifier l'état du conteneur en temps réel.
--Log: sortie standard du conteneur --Properties: Parcourir l'ID de conteneur, l'imageID, etc.
C'est tellement pratique que je n'ai pas envie d'utiliser des commandes honnêtes. .. : dancer_tone1:
Vous pouvez développer des applications avec Docker.
En d'autres termes, cela ne pollue pas du tout les locaux, bien au contraire ** Vous pouvez développer sans utiliser de langage de programmation installé localement **.
La méthode de réglage est expliquée étape par étape ci-dessous. : flèche vers le bas:
C'est un paramètre pour le développement avec python dans le conteneur Docker.
Définissez le SDK (dans ce cas, le langage de programmation et la version) utilisé dans le projet.
Structure du projet> SDK du projet:> Modifier
Normalement, je pense que le python local par défaut ou l'environnement virtuel python tel que pyenv est sélectionné, mais contrairement à d'habitude, procédez comme suit.
Sélectionnez Docker Compose
et
--Serveur: Docker --Fichier de configuration: fichier docker-compose.yml --Service: Le nom du conteneur qui contient python
python
est OKSi vous enregistrez avec les paramètres ci-dessus, vous pouvez poursuivre le développement en fonction du conteneur Docker pour le débogage et les tests. : lift_hands_tone2:
Vous pouvez déjà le faire avec les paramètres ci-dessus, mais rendons les choses encore plus faciles.
Cette application Flask est conçue pour basculer entre les modes de production, de développement et de test en fonction de la valeur de la variable d'environnement du conteneur de flask. Chaque fois que je teste Réécrivez la variable d'environnement de docker-compose.yml, téléchargez-la et renvoyez-la une fois le test terminé. .. C'est gênant. Je veux vivre le plus confortablement possible.
Dans les paramètres d'exécution / débogage, j'entre des variables d'environnement pour les éléments suivants: Maintenant, si vous testez à partir du fichier de configuration, il écrasera les variables d'environnement, puis l'exécutera. Vous n'avez même pas besoin de le réécrire après le test.
En passant, comme vous pouvez le voir dans Docker Compose> Commande et options
, si vous essayez d'exécuter manuellement cela à partir de la CLI, il y aura beaucoup d'entrées et ce sera ennuyeux à chaque fois.
Une fois défini avec Intllij, c'est juste un clic à partir de la deuxième fois.
docker-compose était difficile à obtenir au début. Cependant, une fois que vous vous y serez habitué, le développement d'applications Web s'accélérera considérablement: avion: c'est assez réutilisable: recycler: Puissiez-vous tous commencer à vous développer rapidement et devenir un monde où vous pouvez vous déployer rapidement: wave: