[RAILS] Entrez à partir de docker-compose pour le moment et apprenez Docker tout en apprenant la conception de base du serveur Web (Nginx) ①

① Construction de l'environnement - la construction de serveur Web la plus simple

Si vous commentez des points difficiles à comprendre ou inexacts, cela mènera à la motivation. Avant cette époque, j'ai écrit un article avec un service appelé Zenn Article original Entrez depuis docker-compose pour le moment et apprenez Docker tout en apprenant la conception de base du serveur Web ① | Zenn

introduction

J'espère que cela sera utile pour les personnes suivantes

  1. Créez votre première application Web
  2. Créez une application Web et déployez-la maintenant
  3. J'ai atteint le déploiement pour la première fois, mais je ne comprends pas ce que fait Nginx ou le contenu des paramètres en copiant

Je pense que c'est près de 3 au 5e mois de programme d'auto-apprentissage Comme message personnel, il y a plus de personnes dans l'état de 1. J'espère que le contenu de cet article arrivera. ** Je pense qu'il est pratique de comprendre Docker en quelque sorte! **, ** Développer l'intérêt pour le fonctionnement des applications Web **, j'espère pouvoir partager cette prise de conscience.

Le même contenu que cet article peut être reproduit en utilisant EC2 sur AWS ou en utilisant le VPS sous contrat, mais si vous utilisez docker, vous pouvez défier ** totalement gratuitement **! Plus facile et n'ayez pas peur de la facturation imprévue


Ce que vous pouvez trouver dans cet article

Élargissez vos horizons au réseau

Connaître les bases de Docker

Environnement de développement d'applications Web - connaître la différence dans l'environnement de production

Par conséquent, à la fin de cet article, j'essaierai de déployer l'application sur Docker tout en abordant la différence avec l'environnement de développement dans l'environnement de production virtuel.

Appendix

l'annexe est un contenu supplémentaire J'ai écrit le contenu qui peut être connu dans cette section au début, donc Si vous n'avez pas besoin de le connaître à nouveau, vous pouvez l'ignorer. Si vous ne savez pas ce que vous faites, vous pouvez déplacer votre main et la garder dans le coin de votre tête. ** Il y aura peut-être quelque chose d'utile plus tard **


Ce dont vous avez besoin, des compétences

--Editor (vérifié avec VS Code) Visual Studio Code - Code Editing. Redefined

―― Qu'est-ce que Docker? Ce qui suit est recommandé pour ceux qui disent

[Série] Le conteneur le plus compréhensible au monde & Introduction à Docker ~ Partie 1: Qu'est-ce qu'un conteneur? ~ | SIOS Tech. Lab Il est recommandé de comprendre rapidement le concept et de déplacer vos mains ici.

La partie app utilise Rails pour FW (framework), Vous n'avez pas besoin de connaître Rails

(Je n'ai aucune expérience de développement autre que Rails, il peut donc y avoir du contenu inapproprié dans d'autres FW)

Environnement de vérification

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

Vue d'ensemble de l'architecture (conception)

Dans l'environnement à construire avec Docker à partir de maintenant ** Nginx agit comme un proxy inverse, fournissant du contenu statique au nom de ʻapp: Rails (= proxy) et ne transmettant que les demandes de contenu dynamique à ʻapp: Rails Il est devenu **

J'aimerais comprendre que petit à petit

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

C'est une configuration que vous voyez souvent (base de données et autres parties omises) Les services appelés web (Nginx) et app (rails) s'exécutent sur docker dans des conteneurs indépendants. Il est entendu que chaque dépendance, etc. est définie par docker-compose


Objectif 5 minutes, créer un environnement Rails avec Docker

Nginx --Construire un environnement Rails Je vais me référer au merveilleux article suivant (rires) Nginx, Rails 6, l'environnement PostgreSQL (et même Bootstrap) peuvent être construits immédiatement! Nous nous améliorons petit à petit, nous apprécions donc vos commentaires.

Création d'un environnement de développement Rails6 en 5 minutes avec une commande sur Docker --Rails6 + Nginx + PostgreSQL + Webpack (Bootstrap installé) --Qiita

Code source préparé pour cet article basé sur ce qui précède https://github.com/naokit-dev/try_nginx_on_docker.git

Git clone le code source

#Créer un répertoire pour placer l'application (racine de l'application)
mkdir try_nginx_on_docker

#Aller à la racine de l'application
cd $_

#Obtenir le code source
git clone https://github.com/naokit-dev/try_nginx_on_docker.git

#Déplacer le code source vers la racine de l'application
cp -a try_nginx_on_docker/. .
rm -rf try_nginx_on_docker

Je pense qu'il aura la configuration suivante

.(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

Une partie du code source docker-compose.yml 4 conteneurs sont définis

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:

Environnement

source setup.sh

Si la configuration est terminée normalement Après avoir lancé le conteneur avec la commande suivante dans le répertoire racine de l'application

docker-compose up

#Lors du démarrage en arrière-plan-option d
docker-compose up -d

Lorsque vous accédez à localhost ou localhost: 80 depuis votre navigateur

Vous pouvez voir "Yay! You are on Rails!" ** Tout le monde peut facilement créer un environnement de développement! Le premier avantage de Docker **

Vérifions le conteneur qui s'exécute ici (Si vous faites docker-compose up sans l'option -d, un nouveau terminal sera ouvert. Pour VS Code, control + @ \ * environnement mac)

docker ps

Assurez-vous simplement que les quatre conteneurs web (Nginx), app (Rails), webpacker (webpack-dev-server) et db (PostgreSQL) sont en cours d'exécution

Si vous pouvez le confirmer, fermez le conteneur une fois

docker-compose down

Essayez de diffuser du contenu statique avec Nginx

Je n'utilise pas encore l'application Rails Ici, nous allons contester ce qui suit

--Vérifiez le réglage minimum de Nginx

La configuration Nginx la plus simple

Modifiez docker-compose.yml pour modifier les paramètres Nginx

services:
  web:
    image: nginx:1.18
    ports:
      - "80:80"
    volumes:
    #Réécrire ici./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
...

** Un peu sur le volume Docker ** ./docker/nginx/static.conf: / etc / nginx / conf.d / default.conf of volumes: ʻis <chemin côté hôte>: <chemin côté conteneur> Cela montestatic.conf du côté hôte (local) comme un volume afin qu'il puisse être traité comme default.conf` dans le conteneur. Gardez simplement à l'esprit que ** un montage de volume comme celui-ci est nécessaire ** car le stockage se comporte indépendamment du côté hôte et à l'intérieur du conteneur.

Les paramètres de Nginx sont décrits dans docker / nginx / static.conf, et le contenu est comme suit.

server { #D'ici
      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;
} #Un bloc de serveur ici=Spécifications d'un serveur virtuel géré par Nginx

** serveur **: définissez un serveur virtuel basé sur le contenu inclus dans "{}" (bloc serveur)

Ici, les 3 éléments suivants doivent être définis

** listen **: Spécifiez l'adresse IP et le port d'écoute (xxx.xxx.xxx.xxx:80, localhost: 80, 80) ** nom_serveur **: le nom attribué au serveur virtuel. Nginx recherche les serveurs virtuels qui correspondent au nom d'hôte (example.com) et à l'adresse IP (xxx.xxx.xxx.xxx) inclus dans la demande. ("_" Signifie que toutes les conditions sont remplies. De plus, des caractères génériques et des expressions régulières peuvent être utilisés) ** root **: spécifie la racine du document, le répertoire où se trouve le contenu

Au fait, pour le journal, le même chemin que ci-dessus est défini dans le fichier ʻetc / nginx / nginx.conf, donc Même s'il n'y a pas de description ici, error_log et access_log doivent être enregistrés sous / var / log / nginx / Par exemple, en réglant ʻaccess_log /var/log/nginx/static.access.log;, il semble qu'il soit possible d'enregistrer un journal spécifique au serveur virtuel concerné (bloc serveur).

Démarrer le conteneur Nginx seul

Dans le précédent docker-compose up, tous les conteneurs de nginx, rails, webpack-dev-server, db sont démarrés, mais vous pouvez également démarrer uniquement un conteneur spécifique en utilisant l'option docker-compose. Est possible

--no-deps: Commencez à ignorer les dépendances entre les conteneurs (ici web: nginx uniquement) -d: Démarre le conteneur en arrière-plan, le shell peut continuer à taper -p: Mappage de port \ <hôte>: \ web: conteneur nginx défini par compose

Démarrez le conteneur Nginx avec la commande suivante

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

(Le mappage de port est également spécifié dans compose, mais il doit être spécifié à nouveau et le port 80 du côté hôte est mappé au port 80 dans le conteneur Web.)

Vérifiez la différence avec l'exécution de docker-compose sans options

docker ps

Contrairement à avant, je pense que seul le conteneur nginx est en cours d'exécution

Créer du contenu HTML

Appelez le shell à l'intérieur du conteneur

docker-compose run --no-deps web bash

Voici le travail à l'intérieur du conteneur Web

# index.Créer du HTML
touch /var/www/html/index.html

# index.Ajouter le contenu de html
echo "<h1>I am Nginx</h1>" > /var/www/html/index.html

# index.Vérifiez html
cat /var/www/html/index.html
<h1>I am Nginx</h1>

Maintenant que vous avez créé ʻindex.html directement sous la racine du document dans le conteneur, fermons le shell avec ʻexit.

Contrôle de fonctionnement

Lorsque vous accédez à localhost depuis votre navigateur, Vous pouvez voir qu'il est livré au format HTML comme indiqué ci-dessous.

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

** Nginx a ici un comportement simple de recherche à la racine du document pour le contenu qui correspond à la demande et de retour de la correspondance **

Si vous pouvez le confirmer, fermez le conteneur une fois

docker-compose down

Annexe - Comportement de Nginx lorsqu'aucun serveur virtuel ne correspond à la demande

Nginx définit le serveur virtuel vers lequel acheminer en fonction des informations du champ Hôte incluses dans la demande du client.

** Alors que se passe-t-il si aucun des serveurs virtuels ne correspond à la demande? ** ** Cela semblait important en pensant au design, alors vérifions-le ici.

Dans le bloc serveur du fichier de configuration précédent, j'ai défini le nom du serveur comme applicable à toute demande, mais je le réécrirai avec un nom aléatoire qui ne correspond pas à la demande

server_name undefined_server;

Redémarrez le conteneur Nginx

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

Lorsque j'accède à localhost à partir d'un navigateur, même s'il n'y a pas de serveur virtuel correspondant à la demande De manière inattendue, vous devriez voir le même "Je suis Nginx" qu'avant

default server

Nginx est utilisé pour traiter la demande avec le serveur par défaut lorsque la demande ne correspond à aucun serveur virtuel, et la spécification est de traiter le serveur virtuel décrit en haut en premier comme le serveur par défaut.

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

Vous pouvez également spécifier explicitement default_server dans la directive listen.

listen      80 default_server;

Dans cette expérience, "undefined_server" ne correspond pas à la requête, mais il n'y a rien d'autre à faire correspondre Probablement acheminé comme serveur par défaut

** Si aucun des serveurs virtuels ne correspond à la demande => acheminé vers le serveur par défaut **

Je pense que cela aide à isoler l'erreur, par exemple lorsqu'il ne se connecte pas correctement au serveur principal.

Fermons le conteneur une fois

docker-compose down

annexe - Un peu de compréhension du volume Docker

** À propos de l'importance que le volume est nécessaire (= la persistance est nécessaire) en premier lieu ** Docker crée et gère des volumes pour conserver les données dans le conteneur

Je ne suis pas sûr alors je vais le vérifier

Appelez le shell à l'intérieur du conteneur Web

docker-compose run --no-deps web bash

Voici le travail à l'intérieur du conteneur Web

#Créer un répertoire pour vérification
mkdir /var/www/test

#Créer un fichier pour vérification
touch /var/www/test/index.html

#vérifier l'existence
ls /var/www/test/

Le fait est que / var / www / test est maintenant un chemin qui n'est pas géré en tant que volume dans docker-compose.yml.

Fermons le shell une fois avec ʻexit` (le conteneur sera également fermé)

Redémarrez le conteneur Web et appelez le shell

docker-compose run --no-deps web bash

J'essaierai de retrouver le fichier précédent

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

Qu'est-ce que tu penses, Je ne pense pas que vous puissiez trouver à la fois le répertoire / var / www / test et le fichier / var / www / test / index.html

** Lorsque le conteneur est fermé, les données du conteneur ne sont pas conservées ** C'est le principe Des volumes sont disponibles pour contourner ce mécanisme

Fermez le terminal avec ʻexit`

Arrêtez tous les conteneurs

docker-compose down

** Type de volume **

Il existe les types de volumes suivants dans Docker, mais ils sont identiques en ce sens qu'ils conservent les données dans le conteneur.

  1. volume de l'hôte? (Je ne connais pas le nom)
  2. volume anonyme (j'ai l'impression de passer par un volume anonyme)
  3. volume nommé

Jetez un œil à 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 #host volume
      - public:/myapp/public # named volume
      - log:/var/log/nginx # named volume
      - html:/var/www/html # named volume

...

volumes: #Définissez ici le partage entre différents conteneurs
  public:
  log:
  html:

host volume Je l'ai mentionné dans la partie paramètres nginx Montez le chemin côté hôte en tant que volume dans la partie ./docker/nginx/static.conf: / etc / nginx / conf.d / default.conf ** Image de la copie de fichiers dans l'hôte vers le côté conteneur **

named volume partie html: / var / www / html Je monte le volume avec le nom "html" De plus, en le définissant avec ce nom dans le bloc "volumes" de la même ligne que le bloc "services" ** Permet le partage de volumes entre plusieurs conteneurs **

Et ** ce volume est conservé indépendamment du côté hôte **

Enfin ** volume anonyme ** Dans la documentation officielle, la seule différence avec le volume nommé est ** avec ou sans nom ** Plutôt que de n'avoir aucun nom, ** la partie correspondant au nom du volume nommé est donnée sous forme de hachage pour chaque conteneur ** C'est un peu déroutant, mais il est possible de l'utiliser lorsque vous n'avez pas besoin de monter le côté hôte, mais vous devez le conserver ** et vous ne vous attendez pas à un partage dans plusieurs conteneurs **. (C'est encore difficile à imaginer, mais dans le contenu qui suit, je vais tomber sur une scène où il doit s'agir d'un volume anonyme)

Ici, je vais le vérifier pour une compréhension un peu plus profonde. Remplacez / var / www / html, qui a été initialement défini comme volume nommé, en volume anonyme Je vais répéter la procédure de création d'un fichier HTML effectuée dans cette section.

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 #Spécifiez uniquement le chemin d'accès côté conteneur et passez au volume anonyme

...

volumes:
  public:
  log:
  # html:Commentez ici

Démarrez Nginx en tant que serveur Web

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

Appelle la coquille

docker-compose run --no-deps web bash

Ceci est important, mais si vous vérifiez le conteneur en cours d'exécution dans un autre terminal

docker ps

** Vous pouvez voir que le conteneur avec deux conteneurs en cours d'exécution et le shell en cours d'exécution est différent du conteneur avec mappage de port à 80:80 **

Créer du HTML dans le conteneur tel quel

# index.Créer du HTML
touch /var/www/html/index.html

# index.Confirmer l'existence du html
ls /var/www/html

Accédons à localhost depuis le navigateur comme avant

Le navigateur affiche alors une erreur 403 Vérification du journal des erreurs Nginx

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

Une erreur est enregistrée si le répertoire est introuvable

En passant au volume nommé-> volume anonyme ** Le contenu sous / var / www / html / ne sera pas partagé entre les deux conteneurs ** Puisque le conteneur qui a reçu la demande sur le port 80 du local ne peut plus faire référence à ʻindex.html` Il est probable qu'une telle erreur s'est produite

** Persistance, mais ne partagez pas le volume avec d'autres conteneurs **, je pense que vous pourriez toucher les caractéristiques

Si vous pouvez confirmer, fermez le shell avec ʻexit`

Fermons le conteneur à chaque fois

docker-compose down

(Le contenu modifié de docker-compose.yml peut être laissé tel quel)

...

Le contenu de l'appendice est devenu plus chaud que prévu et il est devenu plus long, alors je vais le casser ici (pour garder ma motivation)

Continuer vers ②


Recommended Posts

Entrez à partir de docker-compose pour le moment et apprenez Docker tout en apprenant la conception de base du serveur Web (Nginx) ①
[Deep Learning from scratch] en Java 1. Pour le moment, différenciation et différenciation partielle
Apprenez à créer un serveur WEB Introduction au développement d'applications WEB à partir des bases
Apprentissage pour la première fois des expressions et opérateurs Java # 3
Commande pour essayer d'utiliser Docker pour le moment
Accédez à l'API Web avec Get sur Android et traitez Json (Java pour le moment)
[Résumé des livres techniques] Résumé de la lecture "Apprendre Docker à partir des bases"
[Docker] Comment sauvegarder et restaurer les données de base de données de l'application Rails sur docker-compose [MySQL]