Dieses Mal werde ich das Verfahren zum Erstellen einer Docker-Umgebung für eine Webanwendung vorstellen, die Rails 6 und MySQL 8 kombiniert.
Ab Rails 6 wird Webpacker standardmäßig installiert, und ab MySQL 8 hat sich die Benutzerauthentifizierungsmethode geändert.
Um eine reibungslose Entwicklung durch mehrere Personen zu ermöglichen, besteht das Ziel darin, eine Umgebung zu erstellen, in der ** wenn Sie aus einem Remote-Repository klonen, die Anwendung nur durch Docker-Compose-Up gestartet wird **.
Die verschiedenen Versionen sind wie folgt.
Die Ausführungsumgebung verwendet Docker Desktop für Mac (Version 2.3.0.4).
Erstellen / Verschieben eines Verzeichnisses. Der Name der diesmal erstellten Rails-Anwendung lautet "sample_app".
$ mkdir sample_app && cd $_
Erstellen Sie mit dem Ruby-Bild eine Gemfile in Ihrer lokalen Umgebung.
-v
ist eine Option für Bind Mount (Synchronisation von Host- und Containerverzeichnissen).
Durch Synchronisieren des aktuellen Verzeichnisses des Hosts mit dem Arbeitsverzeichnis des Containers werden die auf dem Container erstellten Dateien auf dem Host abgelegt.
$ docker run --rm -v `pwd`:/sample_app -w /sample_app ruby:2.7.1 bundle init
Kommentieren Sie den Teil "gem" Rails "der erstellten Gemfile aus und geben Sie die Version der Rails an.
Gemfile
# frozen_string_literal: true
source "https://rubygems.org"
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
- # gem "rails"
+ gem "rails", '~> 6.0.3.2'
Erstellen Sie eine Docker-Datei, um eine Docker-Umgebung zu erstellen, in der "Rails New" ausgeführt wird.
Rails 6 führt beim Erstellen einer Anwendung auch "Rails Webpacker: Install" aus. Vergessen Sie also nicht, ** Garn zu installieren. ** ** ** Verwenden Sie dieses Mal "npm", um "Garn" zu installieren.
Dockerfile
FROM ruby:2.7.1
RUN apt-get update -qq && \
apt-get install -y nodejs \
npm && \
npm install -g yarn
#Arbeitsverzeichnis/sample_In App angegeben
WORKDIR /sample_app
#Kopieren Sie die lokale Gemfile nach Dokcer
COPY Gemfile /sample_app/Gemfile
# /sample_Bundle-Installation im App-Verzeichnis
RUN bundle install
Starten Sie den Container mit dem Image, das durch Erstellen der Docker-Datei erstellt wurde, und führen Sie "Rails New" für den Container aus.
$ docker build -t sample_app .
$ docker run --rm -v `pwd`:/sample_app sample_app rails new . –skip-bundle --database=mysql
Erstellen Sie "docker-compose.yml".
Dieses Mal verbinde ich mich der Kürze halber mit MySQL als Root-Benutzer. Wenn Sie als allgemeiner Benutzer eine Verbindung herstellen, müssen Sie die folgenden Umgebungsvariablen für das MySQL-Image festlegen.
Umgebungsvariable | Inhalt |
---|---|
MYSQL_USER | Nutzername |
MYSQL_PASSWORD | Benutzer-Passwort |
Datenbankinformationen werden beibehalten, indem ein Volume mit dem Namen "mysql_data" erstellt wird.
docker-compose.yml
version: '3'
services:
web: #Container von Ruby on Rails gestartet
build: .
ports:
- '3000:3000' #Machen Sie es auf Port 3000 von localhost zugänglich
volumes:
- .:/sample_app #Synchronisierung von Anwendungsdateien
depends_on:
- db
command: ["rails", "server", "-b", "0.0.0.0"]
db: #Container, den MySQL startet
image: mysql:8.0.21
volumes:
- mysql_data:/var/lib/mysql #Datenpersistenz
command: --default-authentication-plugin=mysql_native_password #Stellen Sie die Authentifizierungsmethode auf 8 Serien oder früher ein.
environment:
MYSQL_ROOT_PASSWORD: 'pass'
MYSQL_DATABASE: 'sample_app_development'
volumes:
mysql_data: #Registrierung des Datenvolumens
Ich werde eine ergänzende Erklärung der obigen "docker-compose.yml" geben.
Das MySQL Docker-Image erstellt eine Datenbank mit dem in MYSQL_DATABASE
festgelegten Namen.
Da die Entwicklungsumgebung von Ruby on Rails die Datenbank "[Anwendungsname] _development" verwendet, ist "sample_app_development" in "MYSQL_DATABASE" registriert.
Jetzt können Sie die Datenbank für die Entwicklungsumgebung vorbereiten, ohne "Rails db: create" auszuführen.
Ab MySQL 8 wurde die Authentifizierungsmethode von "mysql_native_password" in "caching_sha2_password" geändert. Mit der MySQL 8-Standardauthentifizierungsmethode "caching_sha2_password" kann keine Verbindung zur Datenbank hergestellt werden. Die folgende Fehlermeldung wird beim Starten der Rails-Anwendung angezeigt.
Mysql2::Error::ConnectionError
Plugin caching_sha2_password could not be loaded: /usr/lib/x86_64-linux-gnu/mariadb19/plugin/caching_sha2_password.so: cannot open shared object file: No such file or directory
Daher verwendet "--default-authentication-plugin = mysql_native_password" die vorherige Authentifizierungsmethode von "mysql_native_password".
Richten Sie als Nächstes die Datenbankverbindung für Ruby on Rails ein.
config/database.yml
default: &default
adapter: mysql2
encoding: utf8
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: root
password: pass # (Diesmal ist es root)MYSQL_ROOT_Spiel mit PASSWORT
host: db #Legen Sie den Namen des Datenbankcontainers fest
Nachdem wir nun eine Docker-Umgebung haben, die Ruby on Rails 6 und MySQL 8 kombiniert, können wir sie starten.
$ docker-compose up
Es ist in Ordnung, wenn Sie auf localhost: 3000
zugreifen und der folgende Bildschirm angezeigt wird.
Überprüfen wir auch die Persistenz der Daten in der Datenbank. Erstellen Sie beispielsweise eine Funktion für "Ereignis" mit "Gerüst".
$ docker-compose exec web rails g scaffold event title:string
$ docker-compose exec web rails db:migrate
Greifen Sie auf localhost: 3000 / events / new
zu und registrieren Sie als Beispiel einen Datensatz mit dem Namen" sample event ".
Es ist in Ordnung, wenn die Daten auch dann erhalten bleiben, wenn der Container gelöscht und gestartet wird.
$ docker-compose down
$ docker-compose up
$ docker-compose exec web rails c
> Event.last.title
=> "Beispielereignis"
Durch Erstellen einer Datenbank in der Entwicklungsumgebung mit MYSQL_DATABASE
kann die Rails-Anwendung gestartet werden, ohne db: create
auszuführen.
** Dies allein reicht jedoch als Entwicklungsumgebung nicht aus **, da die Datenbank ([Anwendungsname] _test
) der im Testcode verwendeten Testumgebung nicht erstellt wurde.
Wenn Sie im MySQL Docker-Image Skripte (.sql
, .sh
, .sql.gz
) in / docker-entrypoint-initdb.d
platzieren, wird es ausgeführt, wenn der Container gestartet wird. es gibt. [^ Docker-Entrypoint-Initdb]
Nutzen Sie diese Funktion, um eine Datenbank für die Testumgebung zu erstellen.
** Skripte werden in alphabetischer Reihenfolge ausgeführt **. Wenn also eine Abhängigkeit zwischen Skripten besteht, beachten Sie auch den Dateinamen.
$ mkdir docker-entrypoint-initdb.d && cd $_
$ vim 00_create.sql
00_create.sql
--Erstellen Sie eine Datenbank für die Testumgebung
CREATE DATABASE sample_app_test;
Darüber hinaus ist das Datenbankzugriffsrecht allgemeiner Benutzer nur die Datenbank, die auf "MYSQL_DATABASE" festgelegt ist. Daher ** Wenn Sie als allgemeiner Benutzer eine Verbindung zu einer Datenbank herstellen, müssen Sie nicht nur die Datenbank erstellen, sondern auch die folgenden Zugriffsrechte gewähren. ** ** **
01_grant.sql
--Bei Verwendung eines allgemeinen Benutzers namens webapp
GRANT ALL ON `sample_app_test`.* TO webapp@'%';
Fügen Sie einen Bind-Mount hinzu, damit das erstellte Skript im Container gelesen werden kann.
docker-compose.yml
version: '3'
services:
web:
build: .
ports:
- '3000:3000'
volumes:
- .:/sample_app
depends_on:
- db
command: ["rails", "server", "-b", "0.0.0.0"]
db:
image: mysql:8.0.21
volumes:
- mysql_data:/var/lib/mysql
+ - ./docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
command: --default-authentication-plugin=mysql_native_password
environment:
MYSQL_ROOT_PASSWORD: 'pass'
MYSQL_DATABASE: 'sample_app_development'
volumes:
mysql_data:
Löschen und starten Sie den Datenbankcontainer und prüfen Sie, ob die Datenbank automatisch erstellt wird. Es ist in Ordnung, wenn die Datenbanken "[Anwendungsname] _Entwicklung" und "[Anwendungsname] _Test" vorhanden sind.
#Erstellen Sie eine Datenbank von Grund auf neu, indem Sie auch die Informationen zur Datenbankpersistenz löschen
$ docker-compose down --volumes
$ docker-compose up
$ docker-compose exec db mysql -uroot -ppass -D sample_app_development
mysql> show databases;
+------------------------+
| Database |
+------------------------+
| information_schema |
| mysql |
| performance_schema |
| sample_app_development |
| sample_app_test |← db für Test wurde erstellt
| sys |
+------------------------+
6 rows in set (0.00 sec)
Sie können auch erfolgreich eine Verbindung über eine Rails-Anwendung herstellen.
$ docker-compose exec web rails c
> ENV['RAILS_ENV']
=> "development
$ docker-compose exec web rails c -e test
> ENV['RAILS_ENV']
=> "test"
Die folgenden Muster werden häufig als Möglichkeit zum Erstellen einer Rails-Entwicklungsumgebung mit Docker angesehen.
#Starten Sie den Container
$ docker-compose up
#Datenbank erstellen
$ docker-compose exec web rails db:create
#Tabellenmigration
$ docker-compose exec web rails db:migrate
Die Rails-Anwendung und die Datenbank sind durch Docker-Compose verknüpft, und die von der Anwendung verwendete Datenbank basiert auf dem Container.
Mit der obigen Methode gibt es kein Problem, aber in diesem Fall ** Es dauert einige Zeit, die Datenbank und die Tabelle auf dem Container beim ersten Start manuell zu erstellen. ** ** **
In Anbetracht des Falls, eine Docker-Umgebung für mehrere Personen freizugeben, ist es ideal, dass die Umgebung gestartet wird, indem nach dem Klonen der Anwendungsdatei aus dem Remote-Repository einfach "Docker-Compose up" ausgeführt wird.
Wenn möglich, möchte ich die Situation vermeiden, in der ich den freigegebenen Mitgliedern mitteilen muss: "Erstellen Sie die Datenbank auf dem Container, wenn Sie zum ersten Mal starten."
Wenn Sie von hier aus aus einem Remote-Repository klonen, führen Sie einfach "Docker-Compose Up" aus, um die Einstellungen so zu konfigurieren, dass die Rails-Anwendung gestartet werden kann.
In der Entwicklungsumgebung wird häufig die Quellcodesynchronisierung mithilfe von bind mout (Synchronisierung von Host- und Containerverzeichnissen) verwendet.
Die aus dem Remote-Repository geklonte Anwendungsdatei hat ein "package.json", aber kein "node_modules" -Verzeichnis. Wenn Sie nach dem Klonen "Docker-Compose" ausführen, wird das Verzeichnis ohne "Node_Modules" gebunden. Infolgedessen tritt ein Fehler auf, der Sie zur Ausführung der Garninstallation auffordert, und die Anwendung kann nicht gestartet werden.
========================================
Your Yarn packages are out of date!
Please run `yarn install --check-files` to update.
========================================
To disable this check, please change `check_yarn_integrity`
to `false` in your webpacker config file (config/webpacker.yml).
yarn check v1.22.5
info Visit https://yarnpkg.com/en/docs/cli/check for documentation about this command.
Um dies zu verhindern, müssen Sie beim Starten des Containers die Garninstallation ausführen. Beispielsweise können Sie beim Starten des Containers die Garninstallation wie folgt ausführen.
docker-compose.yml
version: '3'
services:
web:
build: .
+ command: ["./start.sh"]
- command: ["rails", "server", "-b", "0.0.0.0"]
ports:
- '3000:3000'
volumes:
- .:/sample_app
depends_on:
- db
db:
image: mysql:8.0.21
command: --default-authentication-plugin=mysql_native_password
environment:
MYSQL_ROOT_PASSWORD: 'pass'
MYSQL_DATABASE: 'sample_app_development'
start.sh
#!/bin/bash -eu
yarn
rails server -b '0.0.0.0'
Ändern Sie die Shell-Berechtigungen.
$ chmod 755 start.sh
Die Shell wird beim Starten des Containers vom Befehl aufgerufen, und "Garninstallation" wird in der Shell ausgeführt. Nach der Ausführung der Garninstallation wird die Rails-Anwendung auf dem Rails-Server gestartet, sodass der vorherige Fehler behoben wird.
Wie bei "Garninstallation" sollte die Tabellenmigration vom Shell-Skript ausgeführt werden, das beim Starten des Containers aufgerufen wird.
start.sh
#!/bin/bash -eu
yarn
+ rails db:migrate
rails server -b '0.0.0.0'
Obwohl Sie die Startreihenfolge von Containern mithilfe von "Dependent_on" von "Docker-Compose.yml" steuern können, können Sie nicht auf den Start des Containers warten [^ Startreihenfolge]. Bereiten Sie sich also auf den Start des DB-Containers vor. Wenn db: migrate
vor dem Ende von ausgeführt wird, ist die Migration nicht erfolgreich.
[^ Startreihenfolge]: Docker-Dokument "Steuern der Startreihenfolge in Compose"
Um die Migration zu automatisieren, müssen Sie warten, bis der Datenbankcontainer gestartet ist, bevor "db: migrate" ausgeführt wird.
Es gibt verschiedene Möglichkeiten, auf die Bereitschaft der Datenbank zu warten, diesmal jedoch darauf warten Hier erfahren Sie, wie Sie> verwenden.
Wenn Sie wait-for-it.sh
in das aktuelle Verzeichnis einfügen und docker-compose.yml
wie folgt erstellen, wird das Skript ausgeführt, nachdem Sie auf den Start der Datenbank gewartet haben.
docker-compose.yml
version: '3'
services:
web:
build: .
- command: [""./start.sh"]
+ command: ["./wait-for-it.sh", "db:3306", "--", "./start.sh"]
ports:
- '3000:3000'
volumes:
- .:/sample_app
depends_on:
- db
db:
image: mysql:8.0.21
command: --default-authentication-plugin=mysql_native_password
environment:
MYSQL_ROOT_PASSWORD: 'pass'
MYSQL_DATABASE: 'sample_app_development'
Damit ist die Einführung des Verfahrens zum Erstellen einer Docker-Umgebung für Rails 6 + MySQL 8 abgeschlossen.
Durch Ausführen der Shell beim Starten des Containers kann die Entwicklungsumgebung reibungslos erstellt werden, selbst wenn mehrere Personen die Docker-Umgebung verwenden. Dieses Mal werden durch Aufrufen der Shell beim Starten des Containers "Garninstallation" und "DB: Migration" sicher ausgeführt, aber die Steuerung des Befehls beim Starten des Containers ist <a href = "https: //". Sie können dies auch mit einem Tool namens github.com/progrium/entrykit "target =" _ blank "> Entrykit tun.
Informationen zu Entrykit So installieren Sie Entrykit in der Rails Docker-Umgebung und führen die Bundle-Installation automatisch aus </ strong> Es wird in einem> vorgestellt, schauen Sie also bitte vorbei, wenn Sie interessiert sind.
Ich mache Twitter ( @ nishina555 ). Ich hoffe du folgst mir!