Donc, afin de développer une application web, je voudrais construire un environnement de développement de masse ** Django + MySQL + nginx ** avec Docker.
La structure initiale des répertoires est la suivante.
app
├── docker-compose.yml
├── mysql
│ ├── Dockerfile
│ └── init.d
│ └── init.sql
├── nginx
│ ├── conf
│ │ └── app_nginx.conf
│ └── uwsgi_params
└── python
├── .dockerignore
├── Dockerfile
└── requirements.txt
De cet état
En passant, voici un exemple de création d'une application appelée "app" avec Django. Remplacez-le par le nom de l'application que vous souhaitez créer.
Écrivons d'abord le résultat. Par essais et erreurs tout en recherchant et en lisant des livres sur Google et en combattant des messages d'erreur impitoyables, je suis finalement arrivé à docker-compose.yml comme ça. En regardant en arrière sur le long voyage, le coin intérieur de mes yeux devient chaud.
docker-compose.yml
version: '3.7'
services:
python:
build:
context: ./python
dockerfile: Dockerfile
command: uwsgi --socket :8001 --module app.wsgi --py-autoreload 1 --logto /tmp/uwsgi.log
restart: unless-stopped
container_name: Django
networks:
- django_net
volumes:
- ./src:/code
- ./static:/static
expose:
- "8001"
depends_on:
- db
db:
build:
context: ./mysql
dockerfile: Dockerfile
restart: unless-stopped
container_name: MySQL
networks:
- django_net
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: "*******"
TZ: "Asia/Tokyo"
volumes:
- app.db.volume:/var/lib/mysql
- ./mysql/init.d:/docker-entrypont-initdb.d
nginx:
image: nginx:1.17
restart: unless-stopped
container_name: nginx
networks:
- django_net
ports:
- "80:80"
volumes:
- ./nginx/conf:/etc/nginx/conf.d
- ./nginx/uwsgi_params:/etc/nginx/uwsgi_params
- ./static:/static
depends_on:
- python
networks:
django_net:
driver: bridge
volumes:
app.db.volume:
name: app.db.volume
Si vous abrégez la composition de manière appropriée, cela ressemble à ceci.
Quoi qu'il en soit, à partir des paramètres Django.
Modifiez
Dockerfile``` directement sous le répertoire "python" comme suit.
./python/Dockerfile
FROM python:3.8.5
WORKDIR /code
ADD requirements.txt /code/
RUN pip install --upgrade pip && pip install -r requirements.txt
ADD . /code/
Tout d'abord, créez un répertoire de travail nommé code '' et accédez-y. Après avoir ajouté
requirements.txt``` à ce répertoire, installez les packages requis avec
pip``` et enfin ajoutez
`` code``` au conteneur.
Ainsi, les packages à installer avec
pip sont répertoriés dans` `` requirements.txt
comme suit. Cette fois, vous avez besoin de trois choses: Django lui-même, uWSGI pour la communication socket avec nginx et mysqlclient pour la connexion à MySQL.
:./python/requirements.txt
Django==2.2.12
uwsgi==2.0.18
mysqlclient==1.4.6
Au fait, éditons également `` .dockerignore```. Ce serait un problème si des fichiers supplémentaires étaient placés dans le conteneur.
:./python/.dockerignore
**/__pycache__
**/.DS_Store
**/.Thumbs.db
**/.git
**/.gitignore
Sur la base des paramètres jusqu'à présent, si vous définissez Django dans
docker-compose.yml```, ce sera comme suit.
docker-compose.yml (extrait)
python:
build:
context: ./python # docker-compose.Chemin relatif vers Dockerfile depuis yml
dockerfile: Dockerfile #Spécification explicite que le paramètre est écrit dans "Dockerfile"
command: uwsgi --socket :8001 --module app.wsgi --py-autoreload 1 --logto /tmp/uwsgi.log
restart: unless-stopped #Si le conteneur s'arrête anormalement, redémarrez-le
container_name: Django #Définir le nom du conteneur
networks:
- django_net #Nom de réseau "django_Spécifiez "net"
volumes:
- ./src:/code # ./Dans src/Code de montage
- ./static:/static # ./À statique/Monter statique
expose:
- "8001" #Ouvrez le port 8001 pour uwsgi au socket communiquer avec nginx
depends_on:
- db
Les paramètres uWSGI sont déroutants, mais si vous gardez la partie
app.wsgi comme `` `` [nom du projet Django] .wsgi
, le reste est magique.
Pour être honnête, je ne suis pas sûr des paramètres MySQL. Surtout, je déteste RDB à un niveau où je ne peux pas écrire de requêtes de manière satisfaisante.
À la suite de l'examen de divers manuels, il semble que ce soit la meilleure pratique. Je ne sais pas.
./mysql/Dockerfile
FROM mysql:5.7
COPY init.d/* /docker-entrypoint-initdb.d/
sql:./mysql/init.d/init.sql
CREATE DATABASE IF NOT EXISTS app_db CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
CREATE USER IF NOT EXISTS 'app_user'@'%' IDENTIFIED BY '[mot de passe]';
GRANT ALL PRIVILEGES ON app_db.* TO 'app_user'@'%';
FLUSH PRIVILEGES;
À propos, le
app.db (nom de la base de données) créé par le `` `` init.sql
ci-dessus est requis pour le réglage de `` settings.py``` décrit plus tard. , Donc je n'oublierai pas.
Sur la base de ce paramètre, si vous configurez MySQL avec
docker-compose.yml```, cela ressemblera à ceci:
docker-compose.yml (extrait)
db:
build:
context: ./mysql # docker-compose.Chemin relatif vers Dockerfile depuis yml
dockerfile: Dockerfile #Spécification explicite que le paramètre est écrit dans "Dockerfile"
restart: unless-stopped #Si le conteneur s'arrête anormalement, redémarrez-le
container_name: MySQL #Définir le nom du conteneur
networks:
- django_net #Nom de réseau "django_Spécifiez "net"
ports:
- "3306:3306" #Spécifiez le numéro de port pour communiquer
environment:
MYSQL_ROOT_PASSWORD: "*******" #Définir le mot de passe root avec la variable d'environnement
TZ: "Asia/Tokyo" #Définir le fuseau horaire avec la variable d'environnement
volumes:
- app.db.volume:/var/lib/mysql #Volume de l'application "base de données".db.Enregistrer dans "volume"
- ./mysql/init.d:/docker-entrypont-initdb.d
Nous avons décidé de sauvegarder la base de données sur un volume nommé "app.db.volume", alors définissez "volumes".
docker-compose.yml (extrait)
volumes:
app.db.volume:
name: app.db.volume
Je ne suis pas sûr non plus des paramètres uWSGI. Pour être honnête, je n'avais pas envie d'enquêter sur uWSGI. Pardon.
Il semble que vous devez définir les paramètres de manière appropriée comme suit. Je ne sais pas.
./nginx/uwsgi_params
uwsgi_param QUERY_STRING $query_string;
uwsgi_param REQUEST_METHOD $request_method;
uwsgi_param CONTENT_TYPE $content_type;
uwsgi_param CONTENT_LENGTH $content_length;
uwsgi_param REQUEST_URI $request_uri;
uwsgi_param PATH_INFO $document_uri;
uwsgi_param DOCUMENT_ROOT $document_root;
uwsgi_param SERVER_PROTOCOL $server_protocol;
uwsgi_param REQUEST_SCHEME $scheme;
uwsgi_param HTTPS $https if_not_empty;
uwsgi_param REMOTE_ADDR $remote_addr;
uwsgi_param REMOTE_PORT $remote_port;
uwsgi_param SERVER_PORT $server_port;
uwsgi_param SERVER_NAME $server_name;
Donc, c'est le réglage de nginx, mais vous devez d'abord ouvrir le port 8001 pour la communication de socket avec uWSGI.
Il définit également le port d'écoute pour nginx. Mon paramètre est le numéro 80, mais il s'agit du paramètre de la machine virtuelle qui exécute le conteneur, et Définissez les données passant par le numéro 80 de l'invité (machine virtuelle) pour qu'elles passent au numéro 8081 de l'hôte. Est.
Maintenant, si vous accédez à "127.0.0.1:8081" avec le navigateur hôte, vous pouvez voir l'application Web qui s'exécute en tant qu'invité.
conf:./nginx/conf/app_nginx.conf
upstream django {
ip_hash;
server python:8001; #Port pour la communication entre Django et nginx sur uWSGI
}
server {
listen 80; #Port de veille
server_name 127.0.0.1;
charset utf-8;
location /static {
alias /static;
}
client_max_body_size 75M;
location / {
uwsgi_pass django;
include /etc/nginx/uwsgi_params;
}
}
server_tokens off;
Sur la base de ce paramètre, définir nginx dans
docker-compose.yml donne: Semblable aux paramètres de Django, `` ``. / Static
est monté sur` `` / static```, donc le contenu statique que Django ne traite pas peut être retourné avec nginx.
docker-compose.yml (extrait)
nginx:
image: nginx:1.17 #Obtenez l'image de nginx correctement
restart: unless-stopped #Si le conteneur s'arrête anormalement, redémarrez-le
container_name: nginx #Définir le nom du conteneur
networks:
- django_net #Nom de réseau "django_Spécifiez "net"
ports:
- "80:80" #Spécifiez le numéro de port pour communiquer
volumes:
- ./nginx/conf:/etc/nginx/conf.d
- ./nginx/uwsgi_params:/etc/nginx/uwsgi_params
- ./static:/static # ./À statique/Monter statique
depends_on:
- python
Aussi, j'ai dit que j'utiliserais "django_net" jusqu'à présent, mais je ne l'ai pas du tout défini, alors n'oubliez pas de définir l'élément "réseaux" également.
docker-compose.yml (extrait)
networks:
django_net:
driver: bridge
À propos, tous les paramètres de Docker sont terminés. Tout ce que vous avez à faire est de laisser les paramètres de Django lui-même.
Commençons par lancer le projet.
$ docker-compose run python django-admin.py startproject app .
Si vous regardez à l'intérieur de src '' et de
static '' après avoir appuyé sur cette commande, vous devriez voir divers fichiers pour Django.
Puis éditez ``. / Src / app / settings.py ''.
python:./src/app/settings.py
DATABASES = {
'default': {
# 'ENGINE': 'django.db.backends.sqlite3', #Commenter
'ENGINE': 'django.db.backends.mysql', #ajouter à
# 'NAME': os.path.join(BASE_DIR, 'app_db'), #Commenter
'NAME': 'app_db', # init.Assurez-vous qu'il est le même que le nom de la base de données qui a été CREATE dans sql
'USER': 'app_user', #ajouter à
'PASSWORD': '*****', #Ajouter (identique au mot de passe spécifié dans la variable d'environnement)
'PORT': '3306', #ajouter à
'HOST': 'db', #ajouter à
}
}
STATIC_URL = '/static/' #ajouter à
STATIC_ROOT = '/static/' #ajouter à
...(Omis)
LANGUAGE_CODE = 'ja' #Éditer
TIME_ZONE = 'Asia/Tokyo' #Éditer
Tout ce que vous avez à faire est d'appuyer sur la commande familière de Django avec docker-compose.
$ docker-compose run python ./manage.py migrate #Migration de base de données
$ docker-compose run python ./manage.py createsuperuser #Paramètres administrateur
$ docker-compose run python ./manage.py collectstatic #Copier le fichier statique
Maintenant, déplaçons le conteneur. Allez, Django!
$ docker-compose up -d
Et quand j'accède à 127.0.0.1:8081 depuis le navigateur hôte ... Je l'ai fait! !! **Bonjour! Docker! salut! Django! ** **
Pour arrêter le conteneur, faites `` stop ''.
$ docker-compose stop
En passant, si vous le mettez ensemble dans un article comme celui-ci, il semble être mal compris comme si je le définissais comme croustillant, alors j'écrirai combien de rebondissements j'ai traversés.
D'abord ce message d'erreur.
ERROR: The Compose file './docker-compose.yml' is invalid because:
services.pithon.volumes contains an invalid type, it should be an array
J'étais en colère et en colère contre ce qui n'allait pas, mais je n'ai pas pu trouver de solution directe.
Soudain, j'ai remarqué que "ça devrait être un tableau" (ça devrait être un tableau, mais ça ne devrait pas être) est le point, et quand j'ai examiné la syntaxe de YAML ... ["En YAML, ajoutez" - "au début de la ligne. Exprimez le tableau par. Veuillez mettre un espace demi-largeur après "-" "](https://magazine.rubyist.net/articles/0009/0009-YAML.html#%E9%85%8D % E5% 88% 97) est indiqué.
Si vous regardez de près, ici,
volumes:
- ./src:/code
Mais,
volumes:
-./src:/code # 「-Il n'y a pas d'espace demi-largeur après
C'était comme ça. ** Il m'a fallu 2 heures pour remarquer cela **.
** Cette putain de calculatrice! !! Êtes-vous l'homme ennuyeux d'un parent! !! ** ** Ce traitement est effectué car il n'y avait qu'un seul espace demi-largeur. Je ne peux plus le faire. En premier lieu, je n'aime pas le nom "Yamuru". Est-ce de la nourriture coréenne (c'est Namuru)?
Puis ce message d'erreur.
Unsupported config option for services.nginx: 'deponds_on'
Comme vous pouvez le voir en regardant de plus près,
depend_on est correct, pas `` `` deponds_on
. C'est une faute d'orthographe stupide, mais ** il m'a fallu deux heures pour le remarquer **.
** Cette putain de calculatrice! !! Rends mon temps précieux dans la vie! !! ** ** Je ne me soucie pas vraiment de la reconnaissance faciale avec apprentissage en profondeur, et je veux un ordinateur astucieux qui corrige doucement ce genre d'erreur humaine.
Oui, ce message d'erreur également.
ERROR: Service 'nginx' depends on service 'python' which is undefined.
La raison pour laquelle j'ai eu cette erreur est que j'ai mal tapé
python comme `` pithon
(voir le premier message d'erreur). ** Il m'a fallu une heure pour remarquer cela **.
** Cette putain de calculatrice! !! Votre tête est un ensemble heureux! !! ** ** Je suis surpris du développement comme un dessin animé à deux images, mais la cause est dans le tableau Dvorak, y et moi sont côte à côte. Il semble.
Maintenant, comprenez-vous à quel point je déteste les ordinateurs, pourquoi j'ai décidé de me spécialiser en apprentissage automatique à l'école doctorale, et pourquoi les chercheurs et les ingénieurs ont arrêté (une histoire complètement différente de l'objectif de cet article).
** C'est juste de jouer comme un jouet, mais je n'ai pas envie de le faire comme un travail **. En bref, il est incompétent par tous les moyens. Je vous en suis vraiment reconnaissant.
À la fin, c'était une ligne de frappe très réconfortante, mais la prochaine fois, j'aimerais créer un environnement de production sur AWS. Restez à l'écoute.