Um eine Webanwendung zu entwickeln, möchte ich mit Docker eine Mass-Docking-Entwicklungsumgebung ** Django + MySQL + nginx ** erstellen.
Die anfängliche Verzeichnisstruktur ist wie folgt.
app
├── docker-compose.yml
├── mysql
│ ├── Dockerfile
│ └── init.d
│ └── init.sql
├── nginx
│ ├── conf
│ │ └── app_nginx.conf
│ └── uwsgi_params
└── python
├── .dockerignore
├── Dockerfile
└── requirements.txt
Aus diesem Zustand
Im Folgenden finden Sie ein Beispiel für die Erstellung einer Anwendung namens "app" mit Django. Ersetzen Sie es durch den Namen der Anwendung, die Sie erstellen möchten.
Schreiben wir zuerst das Ergebnis. Durch Versuch und Irrtum, während ich googelte und Bücher las und rücksichtslose Fehlermeldungen bekämpfte, kam ich schließlich zu docker-compose.yml wie diesem. Wenn ich auf die lange Reise zurückblicke, wird der innere Augenwinkel heiß.
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
Wenn Sie die Komposition entsprechend abkürzen, sieht es so aus.
Wie auch immer, aus den Django-Einstellungen. Bearbeiten Sie `` `Dockerfile``` direkt unter dem" Python "-Verzeichnis wie folgt.
./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/
Erstellen Sie zunächst ein Arbeitsverzeichnis mit dem Namen "Code" und wechseln Sie dorthin. Nachdem Sie `require.txt``` zu diesem Verzeichnis hinzugefügt haben, installieren Sie die erforderlichen Pakete mit`
pip``` und fügen Sie schließlich `` `code```` zum Container hinzu.
Daher sind die Pakete, die mit `pip``` installiert werden sollen, in`
require.txt``` wie folgt aufgeführt. Dieses Mal benötigen Sie drei Dinge: Django selbst, uWSGI für die Socket-Kommunikation mit nginx und mysqlclient für die Verbindung zu MySQL.
:./python/requirements.txt
Django==2.2.12
uwsgi==2.0.18
mysqlclient==1.4.6
Übrigens, lassen Sie uns auch `` `.dockerignore``` bearbeiten. Es wäre ein Problem, wenn zusätzliche Dateien in den Container gelegt würden.
:./python/.dockerignore
**/__pycache__
**/.DS_Store
**/.Thumbs.db
**/.git
**/.gitignore
Basierend auf den bisherigen Einstellungen sieht es wie folgt aus, wenn Sie Django in `` `docker-compose.yml``` einstellen.
docker-compose.yml (Auszug)
python:
build:
context: ./python # docker-compose.Relativer Pfad zu Dockerfile von yml
dockerfile: Dockerfile #Explizite Angabe, dass die Einstellung in "Dockerfile" geschrieben ist
command: uwsgi --socket :8001 --module app.wsgi --py-autoreload 1 --logto /tmp/uwsgi.log
restart: unless-stopped #Wenn der Container abnormal stoppt, starten Sie ihn neu
container_name: Django #Containernamen definieren
networks:
- django_net #Netzwerkname "django_Geben Sie "net" an
volumes:
- ./src:/code # ./In src/Code einbinden
- ./static:/static # ./Zu statisch/Statisch montieren
expose:
- "8001" #Öffnen Sie den Port 8001, damit uwsgi mit nginx kommunizieren kann
depends_on:
- db
Die uWSGI-Einstellungen sind verwirrend, aber wenn Sie den Teil `app.wsgi``` als`
[Django-Projektname] .wsgi``` behalten, ist der Rest magisch.
Um ehrlich zu sein, bin ich mir bei den MySQL-Einstellungen nicht sicher. Meistens hasse ich RDB auf einer Ebene, auf der ich keine zufriedenstellenden Abfragen schreiben kann.
Aufgrund der Prüfung verschiedener Handbücher scheint dies die beste Vorgehensweise zu sein. Ich weiß es nicht.
./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 '[Passwort]';
GRANT ALL PRIVILEGES ON app_db.* TO 'app_user'@'%';
FLUSH PRIVILEGES;
Übrigens ist die `app.db``` (Datenbankname), die von der oben genannten`
init.sql erstellt wurde, für die Einstellung von` `settings.py
erforderlich, die später beschrieben wird. Also werde ich nicht vergessen.
Basierend auf dieser Einstellung sieht es folgendermaßen aus, wenn Sie MySQL mit `` `docker-compose.yml``` konfigurieren:
docker-compose.yml (Auszug)
db:
build:
context: ./mysql # docker-compose.Relativer Pfad zu Dockerfile von yml
dockerfile: Dockerfile #Explizite Angabe, dass die Einstellung in "Dockerfile" geschrieben ist
restart: unless-stopped #Wenn der Container abnormal stoppt, starten Sie ihn neu
container_name: MySQL #Containernamen definieren
networks:
- django_net #Netzwerkname "django_Geben Sie "net" an
ports:
- "3306:3306" #Geben Sie die zu kommunizierende Portnummer an
environment:
MYSQL_ROOT_PASSWORD: "*******" #Legen Sie das Root-Passwort mit der Umgebungsvariablen fest
TZ: "Asia/Tokyo" #Zeitzone mit Umgebungsvariable einstellen
volumes:
- app.db.volume:/var/lib/mysql #Volume the database "App.db.Auf "Lautstärke" speichern
- ./mysql/init.d:/docker-entrypont-initdb.d
Wir haben beschlossen, die Datenbank auf einem Volume mit dem Namen "app.db.volume" zu speichern. Legen Sie daher "Volumes" fest.
docker-compose.yml (Auszug)
volumes:
app.db.volume:
name: app.db.volume
Ich bin mir auch nicht sicher über die uWSGI-Einstellungen. Um ehrlich zu sein, hatte ich keine Lust, uWSGI zu untersuchen. Es tut uns leid.
Es scheint, dass Sie die Parameter wie folgt entsprechend einstellen sollten. Ich weiß es nicht.
./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;
Es ist also die Einstellung von nginx, aber zuerst müssen Sie Port 8001 für die Socket-Kommunikation mit uWSGI öffnen.
Außerdem wird der Abhörport für Nginx festgelegt. Meine Einstellung ist Nummer 80, aber dies ist die Einstellung der virtuellen Maschine, auf der der Container ausgeführt wird, und Stellen Sie die Daten, die durch Nummer 80 des Gasts (virtuelle Maschine) fließen, auf Nummer 8081 des Hosts ein. Is.
Wenn Sie jetzt mit dem Host-Browser auf "127.0.0.1:8081" zugreifen, wird die Webanwendung angezeigt, die als Gast ausgeführt wird.
conf:./nginx/conf/app_nginx.conf
upstream django {
ip_hash;
server python:8001; #Port für die Kommunikation zwischen Django und Nginx auf uWSGI
}
server {
listen 80; #Standby-Port
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;
Basierend auf dieser Einstellung ergibt das Setzen von nginx in `docker-compose.yml```: Ähnlich wie bei den Django-Einstellungen wird
. / Static``` auf``
/ static``` gemountet, sodass statische Inhalte, die Django nicht verarbeitet, mit nginx zurückgegeben werden können.
docker-compose.yml (Auszug)
nginx:
image: nginx:1.17 #Holen Sie sich das Bild von Nginx richtig
restart: unless-stopped #Wenn der Container abnormal stoppt, starten Sie ihn neu
container_name: nginx #Containernamen definieren
networks:
- django_net #Netzwerkname "django_Geben Sie "net" an
ports:
- "80:80" #Geben Sie die zu kommunizierende Portnummer an
volumes:
- ./nginx/conf:/etc/nginx/conf.d
- ./nginx/uwsgi_params:/etc/nginx/uwsgi_params
- ./static:/static # ./Zu statisch/Statisch montieren
depends_on:
- python
Außerdem habe ich gesagt, dass ich bisher "django_net" verwenden würde, aber ich habe es überhaupt nicht festgelegt. Vergessen Sie also nicht, auch das Element "Netzwerke" festzulegen.
docker-compose.yml (Auszug)
networks:
django_net:
driver: bridge
Übrigens sind alle Einstellungen von Docker abgeschlossen. Alles was Sie tun müssen, ist die Einstellungen für Django selbst zu belassen.
Lassen Sie uns zunächst das Projekt starten.
$ docker-compose run python django-admin.py startproject app .
Wenn Sie nach dem Drücken dieses Befehls in `src``` und`
static``` schauen, sollten Sie verschiedene Dateien für Django sehen.
Bearbeiten Sie dann `` `. / Src / app / settings.py```.
python:./src/app/settings.py
DATABASES = {
'default': {
# 'ENGINE': 'django.db.backends.sqlite3', #Auskommentieren
'ENGINE': 'django.db.backends.mysql', #hinzufügen
# 'NAME': os.path.join(BASE_DIR, 'app_db'), #Auskommentieren
'NAME': 'app_db', # init.Stellen Sie sicher, dass es mit dem Datenbanknamen identisch ist, der in SQL CREATE war
'USER': 'app_user', #hinzufügen
'PASSWORD': '*****', #Hinzufügen (wie das in der Umgebungsvariablen angegebene Kennwort)
'PORT': '3306', #hinzufügen
'HOST': 'db', #hinzufügen
}
}
STATIC_URL = '/static/' #hinzufügen
STATIC_ROOT = '/static/' #hinzufügen
...(Weggelassen)
LANGUAGE_CODE = 'ja' #Bearbeiten
TIME_ZONE = 'Asia/Tokyo' #Bearbeiten
Alles was Sie tun müssen, ist den bekannten Befehl in Django mit Docker-Compose zu drücken.
$ docker-compose run python ./manage.py migrate #DB-Migration
$ docker-compose run python ./manage.py createsuperuser #Administratoreinstellungen
$ docker-compose run python ./manage.py collectstatic #Statische Datei kopieren
Bewegen wir nun den Container. Komm raus, Django!
$ docker-compose up -d
Und wenn ich über den Host-Browser auf 127.0.0.1:8081 zugreife ... Ich habs gemacht! !! **Hallo! Docker! Hallo! Django! ** ** **
Um den Container anzuhalten, machen Sie `` `stop```.
$ docker-compose stop
Übrigens, wenn Sie es in einem Artikel wie diesem zusammenstellen, scheint es missverstanden zu werden, als ob ich es als knusprig eingestellt hätte, also werde ich aufschreiben, wie viele Drehungen und Wendungen ich durchgemacht habe.
Zuerst diese Fehlermeldung.
ERROR: The Compose file './docker-compose.yml' is invalid because:
services.pithon.volumes contains an invalid type, it should be an array
Ich war wütend und wütend darüber, was daran falsch war, aber ich konnte keine direkte Lösung finden.
Plötzlich bemerkte ich, dass "es sollte ein Array sein" (es sollte ein Array sein, aber es sollte nicht sein) der Punkt ist, und als ich die Syntax von YAML überprüfte ... Drücken Sie das Array durch aus. Bitte setzen Sie nach "-" "ein Leerzeichen mit halber Breite](https://magazine.rubyist.net/articles/0009/0009-YAML.html#%E9%85%8D % E5% 88% 97) wird angegeben.
Wenn Sie genau hinschauen, hier,
volumes:
- ./src:/code
Aber,
volumes:
-./src:/code # 「-Es gibt kein halbes Feld danach
Es war so. ** Ich habe 2 Stunden gebraucht, um das zu bemerken **.
** Dieser verdammte Taschenrechner! !! Bist du der nervige Mann eines Verwandten? !! ** **. Diese Behandlung wird durchgeführt, weil nur ein Raum mit halber Breite vorhanden war. Ich kann es nicht mehr machen Erstens mag ich den Namen "Yamuru" nicht. Ist es koreanisches Essen (das ist Namuru)?
Dann diese Fehlermeldung.
Unsupported config option for services.nginx: 'deponds_on'
Wie Sie bei näherer Betrachtung sehen können, ist `abhängiges_``` korrekt, nicht`
deponds_on```. Es ist eine dumme Rechtschreibfehler, aber ** ich habe zwei Stunden gebraucht, um das zu bemerken **.
** Dieser verdammte Taschenrechner! !! Gib meine kostbare Zeit im Leben zurück! !! ** ** ** Ich interessiere mich nicht wirklich für Gesichtserkennung mit tiefem Lernen, und ich möchte einen raffinierten Computer, der diese Art von menschlichem Fehler sanft korrigiert.
Ja, auch diese Fehlermeldung.
ERROR: Service 'nginx' depends on service 'python' which is undefined.
Der Grund, warum ich diesen Fehler bekam, war, dass ich `python``` als`
pithon``` falsch eingegeben habe (siehe die erste Fehlermeldung). ** Ich habe eine Stunde gebraucht, um das zu bemerken **.
** Dieser verdammte Taschenrechner! !! Dein Kopf ist ein fröhlicher Satz! !! ** **. Ich bin überrascht über die Entwicklung wie ein Zwei-Frame-Cartoon, aber die Ursache ist im Dvorak-Array sind y und ich nebeneinander. Es scheint.
Verstehst du jetzt, wie sehr ich Computer hasse, warum ich mich für maschinelles Lernen an der Graduiertenschule entschieden habe und warum sowohl Forscher als auch Ingenieure aufgehört haben (eine Geschichte, die sich völlig vom Zweck dieses Artikels unterscheidet).
** Es ist genau richtig, als Spielzeug zu spielen, aber ich habe keine Lust, es als Job zu machen **. Kurz gesagt, er ist in keiner Weise inkompetent. Ich bin dir wirklich dankbar.
Am Ende war es eine sehr herzerwärmende Pointe, aber beim nächsten Mal möchte ich eine Produktionsumgebung auf AWS erstellen. Bleib dran.