Créer un environnement de développement pour Django + MySQL + nginx avec Docker Compose

Environnement d'exploitation et historique

Donc, afin de développer une application web, je voudrais construire un environnement de développement de masse ** Django + MySQL + nginx ** avec Docker.

Structure du répertoire

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.

docker-compose.yml ressemble enfin à ceci

É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. 図1.png

Paramètres Django

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.

Paramètres MySQL

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

paramètres nginx

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

Paramètres du projet Django

À 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

Démarrer et arrêter le conteneur

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 ... スクリーンショット 2020-10-27 21.26.10.png Je l'ai fait! !! **Bonjour! Docker! salut! Django! ** **

Pour arrêter le conteneur, faites `` stop ''.

$ docker-compose stop

Messages d'erreur impitoyables

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.

J'ai hâte à la prochaine fois

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.

Recommended Posts

Créer un environnement de développement pour Django + MySQL + nginx avec Docker Compose
Construction de l'environnement de développement Simple Docker Compose + Django
Créer un environnement de développement PureScript avec Docker
Créer un environnement de développement Wordpress avec Docker
Construction d'un environnement de développement simple Docker + Django
Construire un SPA pour Laravel 6.2 / Vue.js / Nginx / Mysql / Redis avec Docker
Procédure de création d'un environnement de développement d'applications Rails avec Docker [Rails, MySQL, Docker]
Créer un environnement de développement pour Docker + Rails6 + Postgresql
Créez rapidement un environnement de développement WordPress avec Docker
Créer un environnement de développement pour Docker, Java, vs code
[Copier et coller] Créez un environnement de développement Laravel avec Docker Compose, partie 2
Créez un environnement de développement local pour les didacticiels Rails avec Docker (Rails 6 + PostgreSQL + Webpack)
Créer un environnement Node.js avec Docker
Créez un environnement de développement d'applications Web qui utilise Java, MySQL et Redis avec Docker CE pour Windows
Créez un environnement de développement d'applications Rails avec Docker [Docker, Rails, Puma, Nginx, MySQL]
Comment quitter Docker pour Mac et créer un environnement de développement Docker avec Ubuntu + Vagrant
Construire un environnement Rails 6 + MySQL avec Docker compose
Créer un environnement Laravel / Docker avec VSCode devcontainer
[Win10] Créer un environnement de développement JSF avec NetBeans
Créer un environnement de développement Spring Boot avec docker
Créer un environnement de développement Java avec VS Code
Créer un environnement de débogage sur un conteneur - Créer un environnement de développement local pour les didacticiels Rails avec Docker -
Création d'un environnement de développement pour les applications Web Java avec Docker pour Mac Part1
Comment créer un environnement de développement Ruby on Rails avec Docker (Rails 6.x)
Créez un environnement de développement sur AWS EC2 avec CentOS7 + Nginx + pm2 + Nuxt.js
Comment créer un environnement de développement Ruby on Rails avec Docker (Rails 5.x)
Modèle: créer un environnement de développement Ruby / Rails avec un conteneur Docker (version Ubuntu)
Créer un environnement de développement d'applications Web Java avec Docker pour Mac Part2
Modèle: créer un environnement de développement Ruby / Rails avec un conteneur Docker (version Mac)
Comment créer un environnement Docker avec Gradle pour IntelliJ
[Note] Créez un environnement Python3 avec Docker dans EC2
Créer un environnement Docker avec WSL
Créez un environnement de développement pour créer des applications Ruby on Jets + React avec Docker
Environnement Build Rails (API) x MySQL x Nuxt.js avec Docker
Essayez de créer un environnement de développement Java à l'aide de Docker
[Rails] [Docker] Le copier-coller est OK! Comment créer un environnement de développement Rails avec Docker
J'ai créé un environnement de développement avec rails6 + docker + postgreSQL + Materialise.
Comment créer un environnement [TypeScript + Vue + Express + MySQL] avec Docker ~ Express ~
Créez un environnement de développement «Spring Thorough Introduction» avec IntelliJ IDEA
J'ai essayé de créer un environnement de développement padrino avec Docker
Créez un environnement Vue3 avec Docker!
Créer un environnement Node.js avec Docker Compose
Créer un environnement Tomcat 8.5 avec Pleiades 4.8
Construction d'environnement avec Docker pour les débutants