① 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
J'espère que cela sera utile pour les personnes suivantes
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
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 **
--Editor (vérifié avec VS Code) Visual Studio Code - Code Editing. Redefined
Connaissance des commandes Linux de base (cd, ls, vi ..., même si vous ne l'avez pas, vous pouvez le copier)
Docker desktop Docker Desktop for Mac and Windows | Docker
―― 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)
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
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
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
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.
Code source préparé pour cet article basé sur ce qui précède https://github.com/naokit-dev/try_nginx_on_docker.git
#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:
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
Je n'utilise pas encore l'application Rails Ici, nous allons contester ce qui suit
--Vérifiez le réglage minimum de Nginx
Essayez de démarrer le conteneur seul (nginx uniquement) en utilisant Docker-compose
Essayez de fournir un contenu statique simple (HTML) avec Nginx seul
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 monte
static.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).
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
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
.
Lorsque vous accédez à localhost depuis votre navigateur, Vous pouvez voir qu'il est livré au format HTML comme indiqué ci-dessous.
** 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
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
** À 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.
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 ②