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.