[RAILS] Betreten Sie Docker-Compose vorerst und lernen Sie Docker, während Sie das grundlegende Design des Webservers (Nginx) lernen

① Umgebungskonstruktion - die einfachste Webserverkonstruktion

Wenn Sie Punkte kommentieren, die schwer zu verstehen oder ungenau sind, führt dies zu Motivation. Vor dieser Zeit schrieb ich einen Artikel mit einem Dienst namens Zenn Originaler Artikel Geben Sie vorerst von Docker-Compose ein und lernen Sie Docker, während Sie das grundlegende Design des Webservers lernen ① | Zenn

Einführung

Ich hoffe, es wird für die folgenden Personen nützlich sein

  1. Erstellen Sie Ihre erste Web-App
  2. Erstellen Sie eine Web-App und stellen Sie sie jetzt bereit
  3. Ich habe die Bereitstellung zum ersten Mal erreicht, verstehe aber nicht, was Nginx tut oder welche Inhalte durch Kopieren eingestellt werden

Ich denke, es ist fast 3 im 5. Monat der Selbststudienprogrammierung Als persönliche Nachricht gibt es mehr Personen im Zustand 1. Ich hoffe, dass der Inhalt dieses Artikels ankommen wird. ** Ich finde es bequem, Docker irgendwie zu verstehen! **, ** Erweitern Sie das Interesse an der Funktionsweise von Web-Apps **. Ich hoffe, ich kann dieses Bewusstsein teilen.

Der gleiche Inhalt wie dieser Artikel kann mit EC2 unter AWS oder mit dem vertraglich vereinbarten VPS reproduziert werden. Wenn Sie jedoch Docker verwenden, können Sie ** völlig kostenlos ** herausfordern! Einfacher und keine Angst vor ungeplanten Abrechnungen


Was Sie in diesem Artikel finden können

Erweitern Sie Ihren Horizont für das Netzwerk

--Kennen Sie die Mindestkonfiguration, die erforderlich ist, damit eine Web-App funktioniert

Kennen Sie die Grundlagen von Docker

Web-App-Entwicklungsumgebung - kennen den Unterschied in der Produktionsumgebung

Daher werde ich am Ende dieses Artikels die Anwendung auf Docker bereitstellen und dabei den Unterschied zur Entwicklungsumgebung in der virtuellen Produktionsumgebung ansprechen.

Appendix

Anhang ist ergänzender Inhalt Ich habe den Inhalt geschrieben, der in diesem Abschnitt am Anfang bekannt sein kann Wenn Sie es nicht erneut wissen müssen, können Sie es überspringen. Wenn Sie nicht wissen, was Sie tun, können Sie Ihre Hand tatsächlich bewegen und in der Ecke Ihres Kopfes halten.


Was du brauchst, Fähigkeiten

--Editor (verifiziert mit VS Code) Visual Studio Code - Code Editing. Redefined

――Was ist Docker? Das Folgende wird für diejenigen empfohlen, die sagen

[Serie] Der verständlichste Container der Welt & Einführung in Docker ~ Teil 1: Was ist ein Container? ~ | SIOS Tech. Lab Es wird empfohlen, dass Sie das Konzept schnell verstehen und Ihre Hände hierher bewegen.

Der App-Teil verwendet Rails for FW (Framework), Sie müssen Rails nicht kennen

(Ich habe keine andere Entwicklungserfahrung als Rails, daher gibt es möglicherweise unangemessene Inhalte in anderen FWs.)

Überprüfungsumgebung

macOS Catalina docker desktop: 2.3.05 (docker engin: 19.03.12, docker-compose: 1.27.2) Nginx: 1.18 Rails: 6.03 PostgreSQL: 11.0

Architektur (Design) Übersicht

In der Umgebung, die von nun an mit Docker erstellt werden soll ** Nginx fungiert als Reverse-Proxy, liefert statische Inhalte im Auftrag von "app: Rails" (= Proxy) und leitet nur Anfragen nach dynamischen Inhalten an "app: Rails" weiter Es ist geworden **

Das möchte ich nach und nach verstehen

スクリーンショット 2020-09-28 2.53.04.png

Es ist eine Konfiguration, die Sie häufig sehen (Datenbank und andere Teile weggelassen) Die Dienste Web (Nginx) und App (Rails) werden auf Docker in unabhängigen Containern ausgeführt. Es versteht sich, dass jede Abhängigkeit usw. durch Docker-Compose definiert wird


Ziel 5 Minuten: Erstellen Sie eine Rails-Umgebung mit Docker

Nginx - Erstellen Sie eine Rails-Umgebung Ich werde auf den folgenden wunderbaren Artikel verweisen (lacht) Nginx, Rails 6, PostgreSQL-Umgebung (und sogar Bootstrap) können sofort erstellt werden! Wir verbessern uns nach und nach, daher freuen wir uns über Ihre Kommentare.

Erstellen einer Rails6-Entwicklungsumgebung in 5 Minuten mit einem Befehl in Docker - Rails6 + Nginx + PostgreSQL + Webpack (Bootstrap installiert) - Qiita

Quellcode für diesen Artikel basierend auf den oben genannten vorbereitet https://github.com/naokit-dev/try_nginx_on_docker.git

Git klonen den Quellcode

#Erstellen Sie ein Verzeichnis zum Platzieren der Anwendung (Anwendungsstamm)
mkdir try_nginx_on_docker

#Gehen Sie zum Anwendungsstamm
cd $_

#Quellcode abrufen
git clone https://github.com/naokit-dev/try_nginx_on_docker.git

#Verschieben Sie den Quellcode in das Anwendungsstammverzeichnis
cp -a try_nginx_on_docker/. .
rm -rf try_nginx_on_docker

Ich denke, es wird die folgende Konfiguration haben

.(try_nginx_on_docker)
├── Dockerfile
├── Gemfile
├── Gemfile.lock
├── README.md
├── docker
│   └── nginx
│       ├── default.conf
│       ├── load_balancer.conf
│       └── static.conf
├── docker-compose.prod.yml
├── docker-compose.yml
├── entrypoint.sh
├── setup.sh
└── temp_files
    ├── copy_application.html.erb
    ├── copy_database.yml
    └── copy_environment.js

Teil des Quellcodes docker-compose.yml Es sind 4 Container definiert

version: "3.8"

services:
  web:
    image: nginx:1.18
    ports:
      - "80:80"
    volumes:
      - ./docker/nginx/static.conf:/etc/nginx/conf.d/default.conf
      - public:/myapp/public
      - log:/var/log/nginx
      - /var/www/html
    depends_on:
      - app

  db:
    image: postgres:11.0-alpine
    volumes:
      - postgres:/var/lib/postgresql/data:cached
    ports:
      - "5432:5432"
    environment:
      PGDATA: /var/lib/postgresql/data/pgdata
      POSTGRES_USER: ${POSTGRES_USER:-postgres}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-password}
      POSTGRES_INITDB_ARGS: "--encoding=UTF-8 --locale=ja_JP.UTF-8"
      TZ: Asia/Tokyo

  app:
    build:
      context: .
    image: rails_app
    tty: true
    stdin_open: true
    command: bash -c "rm -f tmp/pids/server.pid && ./bin/rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/myapp:cached
      - rails_cache:/myapp/tmp/cache:cached
      - node_modules:/myapp/node_modules:cached
      - yarn_cache:/usr/local/share/.cache/yarn/v6:cached
      - bundle:/bundle:cached
      - public:/myapp/public
      - log:/myapp/log
      - /myapp/tmp/pids
    tmpfs:
      - /tmp
    ports:
      - "3000-3001:3000"
    environment:
      RAILS_ENV: ${RAILS_ENV:-development}
      NODE_ENV: ${NODE_ENV:-development}
      DATABASE_HOST: db
      DATABASE_PORT: 5432
      DATABASE_USER: ${POSTGRES_USER}
      DATABASE_PASSWORD: ${POSTGRES_PASSWORD}
      WEBPACKER_DEV_SERVER_HOST: webpacker
    depends_on:
      - db
      - webpacker

  webpacker:
    image: rails_app
    command: ./bin/webpack-dev-server
    volumes:
      - .:/myapp:cached
      - public:/myapp/public
      - node_modules:/myapp/node_modules:cached
    environment:
      RAILS_ENV: ${RAILS_ENV:-development}
      NODE_ENV: ${NODE_ENV:-development}
      WEBPACKER_DEV_SERVER_HOST: 0.0.0.0
    tty: false
    stdin_open: false
    ports:
      - "3035:3035"

volumes:
  rails_cache:
  node_modules:
  yarn_cache:
  postgres:
  bundle:
  public:
  log:
  html:

Umgebung

source setup.sh

Wenn das Setup normal abgeschlossen ist Nach dem Starten des Containers mit dem folgenden Befehl im Anwendungsstammverzeichnis

docker-compose up

#Beim Start im Hintergrund-d Option
docker-compose up -d

Wenn Sie über Ihren Browser auf localhost oder localhost: 80 zugreifen

Sie können sehen, "Yay! Sie sind auf Schienen!" ** Jeder kann problemlos eine Entwicklungsumgebung erstellen! Der erste Vorteil von Docker **

Lassen Sie uns den Container überprüfen, der hier ausgeführt wird (Wenn Sie "Docker-Compose Up" ohne die Option "-d" ausführen, wird ein neues Terminal geöffnet. Für VS-Code "Control" + "@" \ * Mac-Umgebung)

docker ps

Stellen Sie einfach sicher, dass die vier Container Web (Nginx), App (Rails), Webpacker (Webpack-Dev-Server) und DB (PostgreSQL) ausgeführt werden

Wenn Sie dies bestätigen können, schließen Sie den Behälter einmal

docker-compose down

Versuchen Sie, statische Inhalte mit Nginx bereitzustellen

Ich benutze die Rails App noch nicht Hier werden wir Folgendes herausfordern

--Überprüfen Sie die Mindesteinstellung von Nginx

Die einfachste Nginx-Konfiguration

Bearbeiten Sie "docker-compose.yml", um die Nginx-Einstellungen zu ändern

services:
  web:
    image: nginx:1.18
    ports:
      - "80:80"
    volumes:
    #Hier umschreiben./docker/nginx/default.conf... -> ./docker/nginx/static.conf...
      - ./docker/nginx/static.conf:/etc/nginx/conf.d/default.conf
      - public:/myapp/public
      - log:/var/log/nginx
    depends_on:
      - app
...

** Ein wenig über Docker-Lautstärke ** ./docker/nginx/static.conf: / etc / nginx / conf.d / default.conf von Volumes: is<Host-Pfad>: <Container-Pfad> Dadurch wirdstatic.conf auf der Hostseite (lokal) als Volume bereitgestellt, sodass es im Container als default.conf` behandelt werden kann. Denken Sie daran, dass ** ein Volume-Mount wie dieser erforderlich ist **, da sich der Speicher auf der Host-Seite und im Container unabhängig verhält.

Die Nginx-Einstellungen werden in "docker / nginx / static.conf" beschrieben. Der Inhalt ist wie folgt.

server { #Von hier
      listen 80; # must
      server_name _; # must
      root /var/www/html; # must
      index index.html;
      access_log /var/log/nginx/access.log;
      error_log  /var/log/nginx/error.log;
} #Ein Serverblock bis hierher=Spezifikationen eines virtuellen Servers, der von Nginx verwaltet wird

** Server **: Definieren Sie einen virtuellen Server basierend auf den Inhalten in "{}" (Serverblock).

Hier müssen die folgenden 3 Punkte gesetzt werden

** listen **: Geben Sie die Überwachungs-IP und den Port an (xxx.xxx.xxx.xxx:80, localhost: 80, 80). ** Servername **: Der dem virtuellen Server zugewiesene Name. Nginx sucht nach virtuellen Servern, die dem Hostnamen (example.com) und der IP-Adresse (xxx.xxx.xxx.xxx) entsprechen, die in der Anforderung enthalten sind. ("_" Bedeutet, dass alle Bedingungen erfüllt werden. Außerdem können Platzhalter und reguläre Ausdrücke verwendet werden.) ** root **: Gibt das Dokumentstammverzeichnis an, das Verzeichnis, in dem sich der Inhalt befindet

Übrigens ist für das Protokoll derselbe Pfad wie oben in der Datei "etc / nginx / nginx.conf" definiert Auch wenn es hier keine Beschreibung gibt, sollten sowohl error_log als auch access_log unter / var / log / nginx / aufgezeichnet werden Wenn Sie beispielsweise "access_log /var/log/nginx/static.access.log;" festlegen, scheint es möglich zu sein, ein Protokoll aufzuzeichnen, das für den jeweiligen virtuellen Server (Serverblock) spezifisch ist.

Starten Sie den Nginx-Container alleine

Im vorherigen "Docker-Compose-Up" wurden alle Container von Nginx, Rails, Webpack-Dev-Server und DB gestartet. Sie können jedoch auch nur einen bestimmten Container mithilfe der Docker-Compose-Option starten. Ist möglich

--no-deps: Ignorieren Sie Abhängigkeiten zwischen Containern (hier Web: nur Nginx) -d: Startet den Container im Hintergrund, die Shell kann weiter tippen -p: Portzuordnung \ : \ web: durch compose definierter nginx container

Starten Sie den Nginx-Container mit dem folgenden Befehl

docker-compose run --no-deps -d -p 80:80 web

(Die Portzuordnung wird auch in compose angegeben, muss jedoch erneut angegeben werden, und Port 80 auf der Hostseite wird Port 80 im Webcontainer zugeordnet.)

Überprüfen Sie den Unterschied zum Ausführen von Docker-Compose ohne Optionen

docker ps

Im Gegensatz zu früher denke ich, dass nur der Nginx-Container läuft

Erstellen Sie HTML-Inhalte

Rufen Sie die Shell im Container auf

docker-compose run --no-deps web bash

Unten finden Sie die Arbeit im Webcontainer

# index.Erstellen Sie HTML
touch /var/www/html/index.html

# index.Fügen Sie den Inhalt von HTML hinzu
echo "<h1>I am Nginx</h1>" > /var/www/html/index.html

# index.Überprüfen Sie HTML
cat /var/www/html/index.html
<h1>I am Nginx</h1>

Nachdem Sie "index.html" direkt unter dem Dokumentstamm im Container erstellt haben, schließen wir die Shell mit "exit".

Funktionsprüfung

Wenn Sie über Ihren Browser auf localhost zugreifen, Sie können sehen, dass es wie unten gezeigt als HTML geliefert wird.

スクリーンショット 2020-09-22 11.25.12.png

** Nginx hat hier ein einfaches Verhalten beim Durchsuchen des Dokumentstamms nach Inhalten, die der Anforderung entsprechen, und beim Zurückgeben der Übereinstimmung **

Wenn Sie dies bestätigen können, schließen Sie den Behälter einmal

docker-compose down

Anhang - Nginx-Verhalten, wenn kein virtueller Server mit der Anforderung übereinstimmt

Nginx definiert basierend auf den Informationen im Feld Host, die in der Anforderung vom Client enthalten sind, an welchen virtuellen Server weitergeleitet werden soll.

** Was passiert also, wenn keiner der virtuellen Server mit der Anforderung übereinstimmt? ** ** ** Es schien wichtig zu sein, über das Design nachzudenken, also lasst es uns hier überprüfen.

Im Serverblock der vorherigen Konfigurationsdatei habe ich "Servername" so definiert, dass er auf jede Anforderung anwendbar ist, aber ich werde ihn mit einem zufälligen Namen umschreiben, der nicht mit der Anforderung übereinstimmt

server_name undefined_server;

Starten Sie den Nginx-Container erneut

docker-compose run --no-deps -p 80:80 web

Wenn ich über einen Browser auf localhost zugreife, obwohl es keinen virtuellen Server gibt, der der Anforderung entspricht Unerwartet sollten Sie das gleiche "Ich bin Nginx" wie zuvor sehen

default server

Nginx wird verwendet, um die Anforderung mit dem Standardserver zu verarbeiten, wenn die Anforderung keinem virtuellen Server entspricht, und die Spezifikation besteht darin, den oben beschriebenen virtuellen Server zuerst als Standardserver zu behandeln.

In the configuration above, the default server is the first one — which is nginx’s standard default behaviour. It can also be set explicitly which server should be default, with the default_server parameter in the listen directive: How nginx processes a request

Alternativ können Sie in der Listen-Direktive explizit "default_server" angeben.

listen      80 default_server;

In diesem Experiment stimmt "undefined_server" nicht mit der Anforderung überein, aber es gibt nichts anderes, das übereinstimmt Wahrscheinlich als Standardserver weitergeleitet

** Wenn keiner der virtuellen Server mit der Anforderung übereinstimmt => an Standardserver weitergeleitet **

Ich bin der Meinung, dass es hilfreich ist, den Fehler zu isolieren, z. B. wenn keine gute Verbindung zum Backend-Server besteht.

Lassen Sie uns den Behälter einmal schließen

docker-compose down

Anhang - Ein wenig Verständnis des Docker-Volumens

** Über die Bedeutung, dass Volumen an erster Stelle notwendig ist (= Persistenz ist notwendig) ** Docker erstellt und verwaltet Volumes, um die Daten im Container beizubehalten

Ich bin mir nicht sicher, also werde ich es überprüfen

Rufen Sie die Shell im Webcontainer auf

docker-compose run --no-deps web bash

Unten finden Sie die Arbeit im Webcontainer

#Erstellen Sie ein Verzeichnis zur Überprüfung
mkdir /var/www/test

#Erstellen Sie eine Datei zur Überprüfung
touch /var/www/test/index.html

#Existenz prüfen
ls /var/www/test/

Der Punkt ist, dass / var / www / test jetzt ein Pfad ist, der nicht als Volume in docker-compose.yml verwaltet wird.

Lassen Sie uns die Shell einmal mit "exit" schließen (der Container wird ebenfalls geschlossen)

Starten Sie den Webcontainer erneut und rufen Sie die Shell auf

docker-compose run --no-deps web bash

Ich werde versuchen, die vorherige Datei zu finden

cat /var/www/test/index.html
ls /var/www

Was denken Sie, Ich glaube nicht, dass Sie sowohl das Verzeichnis "/ var / www / test" als auch die Datei "/ var / www / test / index.html" finden können

** Wenn der Container geschlossen ist, bleiben die Daten im Container nicht erhalten ** Dies ist das Prinzip Zur Umgehung dieses Mechanismus stehen Volumes zur Verfügung

Schließen Sie das Terminal mit "exit"

Stoppen Sie alle Container

docker-compose down

** Volumentyp **

In Docker gibt es die folgenden Datenträgertypen, die jedoch insofern identisch sind, als sie die Daten im Container beibehalten.

  1. Host-Volume? (Ich kenne den Namen nicht)
  2. anonymes Volume (Ich habe das Gefühl, ich gehe durch anonymes Volume)
  3. benanntes Volume

Schauen Sie sich docker-compose.yml an

version: "3.8"

services:
  web:
    image: nginx:1.18
    ports:
      - "80:80"
    volumes:
      - ./docker/nginx/static.conf:/etc/nginx/conf.d/default.conf #host volume
      - public:/myapp/public # named volume
      - log:/var/log/nginx # named volume
      - html:/var/www/html # named volume

...

volumes: #Definieren Sie hier die Freigabe zwischen verschiedenen Containern
  public:
  log:
  html:

host volume Ich habe es im Teil mit den Nginx-Einstellungen erwähnt Hängen Sie den hostseitigen Pfad als Volume im Teil ./docker/nginx/static.conf: / etc / nginx / conf.d / default.conf ein ** Bild des Kopierens von Dateien auf dem Host auf die Containerseite **

named volume html: / var / www / html Teil Ich mounte das Volume mit dem Namen "html" Durch Definieren mit diesem Namen im Block "Volumes" in derselben Zeile wie im Block "Services" ** Ermöglicht die gemeinsame Nutzung von Volumes zwischen mehreren Containern **

Und ** dieses Volume bleibt unabhängig von der Host-Seite bestehen **

Endlich ** anonymer Band ** Im offiziellen Dokument ist der einzige Unterschied zum benannten Volume ** mit oder ohne Namen ** Anstatt tatsächlich keinen Namen zu haben **, wird der Teil, der dem Namen des benannten Volumes entspricht, als Hash für jeden Container angegeben ** Es ist ein bisschen verwirrend, kann aber in Fällen verwendet werden, in denen Sie die Host-Seite nicht mounten müssen, sie aber beibehalten müssen ** und nicht erwarten, dass sie in mehreren Containern geteilt wird **. (Es ist immer noch schwer vorstellbar, aber im folgenden Inhalt werde ich auf eine Szene stoßen, in der es sich um einen anonymen Band handeln muss.)

Hier werde ich es für ein etwas tieferes Verständnis überprüfen. Ändern Sie / var / www / html, das ursprünglich als benanntes Volume definiert wurde, in anonymes Volume Ich werde das in diesem Abschnitt durchgeführte Verfahren zum Erstellen einer HTML-Datei wiederholen.

docker-compose.yml

version: "3.8"

services:
  web:
    image: nginx:1.18
    ports:
      - "80:80"
    volumes:
      - ./docker/nginx/static.conf:/etc/nginx/conf.d/default.conf
      - public:/myapp/public
      - log:/var/log/nginx
      - /var/www/html #Geben Sie nur den Pfad auf der Containerseite an und wechseln Sie zu einem anonymen Volume

...

volumes:
  public:
  log:
  # html:Kommentar hier raus

Starten Sie Nginx als Webserver

docker-compose run --no-deps -d -p 80:80 web

Rufen Sie die Shell

docker-compose run --no-deps web bash

Dies ist wichtig, aber wenn Sie den Container überprüfen, der derzeit in einem anderen Terminal ausgeführt wird

docker ps

** Sie können sehen, dass sich der Container mit zwei laufenden Containern und der laufenden Shell von dem Container mit Portzuordnung um 80:80 unterscheidet. **

Erstellen Sie HTML im Container so wie es ist

# index.Erstellen Sie HTML
touch /var/www/html/index.html

# index.Bestätigen Sie die Existenz von HTML
ls /var/www/html

Lassen Sie uns wie zuvor über den Browser auf localhost zugreifen

Der Browser zeigt dann einen 403-Fehler an Überprüfen des Nginx-Fehlerprotokolls

tail -f 20 /var/log/nginx/error.log
...directory index of "/var/www/html/" is forbidden...

Ein Fehler wird protokolliert, wenn das Verzeichnis nicht gefunden werden kann

Durch Ändern auf benanntes Volume-> anonymes Volume ** Der Inhalt unter / var / www / html / wird nicht zwischen den beiden Containern geteilt ** Da der Container, der die Anforderung an Port 80 vom lokalen empfangen hat, nicht mehr auf "index.html" verweisen kann Es ist wahrscheinlich, dass ein solcher Fehler aufgetreten ist

** Persistenz, aber nicht Volumen mit anderen Containern teilen **, ich denke, Sie könnten die Eigenschaften berühren

Wenn Sie dies bestätigen können, schließen Sie die Shell mit "exit"

Lassen Sie uns den Behälter jedes Mal schließen

docker-compose down

(Der geänderte Inhalt von docker-compose.yml kann unverändert bleiben.)

...

Der Inhalt des Anhangs wurde heißer als ich erwartet hatte und er wurde länger, also werde ich ihn hier brechen (um meine Motivation zu behalten)

Weiter zu ②


Recommended Posts

Betreten Sie Docker-Compose vorerst und lernen Sie Docker, während Sie das grundlegende Design des Webservers (Nginx) lernen
[Deep Learning von Grund auf neu] in Java 1. Zur Zeit Differenzierung und teilweise Differenzierung
Lernen Sie beim Erstellen eines WEB-Servers die Einführung in die Entwicklung von WEB-Anwendungen anhand der Grundlagen
Zum ersten Mal lernen Java # 3 Ausdrücke und Operatoren
Befehl, um Docker vorerst zu verwenden
Greifen Sie mit Get on Android auf die Web-API zu und verarbeiten Sie Json (vorerst Java).
[Zusammenfassung der technischen Bücher] Zusammenfassung der Lektüre "Lernen Sie Docker aus den Grundlagen"
[Docker] So sichern und wiederherstellen Sie DB-Daten der Rails-Anwendung auf Docker-Compose [MySQL]