- 投稿日:2020-06-23T23:31:50+09:00
【Rails】 本番環境MySQLデータを開発環境に入れた後に消す方法
はじめに
本番環境にMySQLのデータを開発環境に入れる時には特にエラーもなくインプットすることができたのですが、消す時になってエラーが発生してハマってしまいました。
少し珍しいケースかもしれませんが、他の方の参考になればと思いまとめることにしました。関連リンク
そもそも本番環境のMySQLのデータをどうやって開発環境に入れるのかという記事は下記をご参照ください。
- EC2からMySQL(RDS)接続後にローカルMySQLにデータを入力する方法
エラー
開発環境でDB自体を削除するコマンドを実行したところ、、、
$ rails db:dropエラー
ActiveRecord::ProtectedEnvironmentError
が出ました。。。このエラーの意味は、
本番環境のDBを操作しようとしているが問題ないですか?
という警告のようなもので、環境変数を入れると操作を続けることができるよ。と言ってます。
そもそも開発環境なんですけど、なんで本番環境と出るんですか??
rails aborted! ActiveRecord::ProtectedEnvironmentError: You are attempting to run a destructive action against your 'production' database. If you are sure you want to continue, run the same command with the environment variable: DISABLE_DATABASE_ENVIRONMENT_CHECK=1 bin/rails:4:in `<main>' Tasks: TOP => db:migrate:reset => db:drop => db:check_protected_environments (See full trace by running task with --trace)結論
先に結論から書いてしまいますが、
Rails5では MySQLに環境変数を格納しており、本番環境のデータをそのまま開発環境に入れたことにより、MySQLの環境変数に本番環境の変数が格納されてしまったため、上記のエラーがでてしまいました。
なので、解決する方法としては、MySQLの環境変数を本番環境のものから開発環境のものに書き換えればいいということです。
解決手順
MySQLに接続します。
$ mysql -h db -u root -p存在するデータベースを確認します。
$ show databases;対象のデータベースを指定します。
$ use *******;データベースないのテーブルの一覧を表示します。
$ show tables;テーブル一覧の中に
ar_internal_metadata
があると思います。
この中に、環境変数を格納しています。+---------------------------------------------------+ | Tables_in_scm_development | +---------------------------------------------------+ | ar_internal_metadata | | ... | +---------------------------------------------------+ar_internal_metadataの中身をみてみると、
$ select * from ar_internal_metadata;見つけました
production
の文字を。+-------------+-------------+---------------------+---------------------+ | key | value | created_at | updated_at | +-------------+-------------+---------------------+---------------------+ | environment | production | 2020-01-10 09:37:29 | 2020-01-10 09:37:29 | +-------------+-------------+---------------------+---------------------+この
production
をdevelopment
へ修正します。$ update ar_internal_metadata set value='development'もう一度、ar_internal_metadataの中身をみてみると、
$ select * from ar_internal_metadata;環境変数は
development
に変更できました。+-------------+-------------+---------------------+---------------------+ | key | value | created_at | updated_at | +-------------+-------------+---------------------+---------------------+ | environment | development | 2020-01-10 09:37:29 | 2020-01-10 09:37:29 | +-------------+-------------+---------------------+---------------------+MySQLから抜けて
$ exitもう一度、DBを削除するコマンドを実行。すると成功しました!
$ rails db:dropまとめ
つらつらと手順を書いたので、人によっては理解しづらいかもしれませんが、困っている誰かの役に立てばなーと思います。
参考
- 本番環境のデータをローカルのDBに投入したら UnknownMigrationVersionError と ProtectedEnvironmentError (Rails 5)
- 投稿日:2020-06-23T23:16:07+09:00
「数GBのdumpいつ終わるんやろか」
TL;DR
- プログレスバー表示するには
pv
使ったらいいよbrew install pv
でインストールできるよmysqldump <parameters> | pv --progress --size 100m > dumpfile.sql
さあdumpだ
「よーし、mysqldump叩くぞー」
「userとhost、databaseとport指定して、と」MYSQL_PWD=$DUMP_DB_PASSWORD mysqldump -u $DUMP_DB_USER -h $DUMP_DB_HOST -P $DUMP_DB_PORT --set-gtid-purged=OFF --column-statistics=0 > $DUMP_FILE「そんでもってこいつを.shファイルにして、」
「よし、これでいつでもdumpし放題や!」「よっしゃ、叩くでー」
$ sh dump.sh「楽しみやな」
「…」
$ sh dump.sh「…」
「そういや、このDBって確か数GBのサイズやったな・・・」
「…」
$ sh dump.sh「(果たしていつ頃終わるんやろか・・・・)」
せや!
「せや!プログレスバーを表示したればええんや!」
「
mysql dump progressbar
で、検索っと」mysql - Does mysqldump support a progress bar? - Stack Overflow
「ほう、
pv
ってのを使ってやればええんか」「macはbrewでインストールできるんやな。
brew install pv
でインストールして、っと!」「あとはこいつに組み込んでやるだけ・・・」
「どうやら、大体のファイルサイズを指定するとそいつを100%で表示してくれるみたいや」
「確か2GBくらいあったはずや」
MYSQL_PWD=$DUMP_DB_PASSWORD mysqldump -u $DUMP_DB_USER -h $DUMP_DB_HOST -P $DUMP_DB_PORT --set-gtid-purged=OFF --column-statistics=0 $DUMP_DATABASE | pv --progress --size 2000m > $DUMP_FILE「よし、こいつを実行や!」
$ sh dump.sh [> ] 0%「く、長い・・・。でもプログレスバーを得たワイなら待てる。待てるはずや。」
$ sh dump.sh [=====================================================================> ] 95%「終わる、終わるぞーーー!」
[================================================================================] 109%
「あ、あれ、、、」
[================================================================================] 149%
「(こいつ一体なんGBのデータ持ってるんや・・・!?)」
- 投稿日:2020-06-23T22:46:15+09:00
Docker+Rails6+MySQL+Nginx環境構築メモ
はじめに
弊社では未だにdockerを導入しておらず、このままだとマズいと思ったので勉強も兼ねて環境構築してみました。
ミスや間違った説明をしている箇所があるかもしれませんが、優しくご指摘頂けると助かります。
既に環境構築系の記事は出ていますが、実際試しても上手くいかないことがあったので自分の経験もまとめておきます。流れ
- "rails new"でプロジェクト作成
- "git init"でローカルリポジトリ作成
- GitHubにてリモートリポジトリ作成
- リモートリポジトリにプッシュ
-----ここから書きます-----
- EC2インスタンス作成
- gitインストール
- dockerインストール
- docker起動
- リモートリポジトリをプル
- イメージのビルド(docker-compose build --no-cache)
- コンテナ作成,起動(docker-compose up -d)
- マイグレーション(docker-compose exec sample-app_web_1 bundle exec rails db:migrate)
gitのインストール
Gitをインストールします
$ sudo yum install git $ git clone https://github.com/satou-yuuki/sample-app.gitdockerのインストール
AWS公式に従ってDockerをインストールします
参考:https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/docker-basics.html$ sudo yum update -y $ sudo amazon-linux-extras install docker $ sudo systemctl start docker.service または sudo service docker start $ sudo usermod -a -G docker ec2-user 一度ターミナルを抜けるとグループが追加されていると思いますdocker-composeのインストール
docker公式に従ってdocker-composeをインストールします
参考:https://docs.docker.com/compose/install/$ sudo curl -L "https://github.com/docker/compose/releases/download/1.26.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose $ sudo chmod +x /usr/local/bin/docker-composedocker-compose build
$ docker-compose build --no-cachedocker-compose up
$ docker-compose up -drails db:migrate
$ docker exec sample-app_web_1 bundle exec rails db:migrateブラウザから確認
ブラウザで http://host/users を確認するとエラー画面が表示されてしまったのでログを確認します。
Started GET "/users" for 111.239.186.32 at 2020-06-22 00:17:50 +0000 Cannot render console from 111.239.186.32! Allowed networks: 127.0.0.0/127.255.255.255, ::1 Processing by UsersController#index as HTML Rendering users/index.html.erb within layouts/application User Load (0.4ms) SELECT `users`.* FROM `users` ↳ app/views/users/index.html.erb:16 Rendered users/index.html.erb within layouts/application (Duration: 3.8ms | Allocations: 1537) [Webpacker] Compiling... [Webpacker] Compilation failed: yarn run v1.22.4 info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command. error Command "webpack" not found. Completed 500 Internal Server Error in 1573ms (ActiveRecord: 0.9ms | Allocations: 23784) ActionView::Template::Error (Webpacker can't find application in /sample-app/public/packs/manifest.json. Possible causes: 1. You want to set webpacker.yml value of compile to true for your environment unless you are using the `webpack -w` or the webpack-dev-server. 2. webpack has not yet re-run to reflect updates. 3. You have misconfigured Webpacker's config/webpacker.yml file. 4. Your webpack configuration is not creating a manifest. Your manifest contains: { } ): 6: <%= csp_meta_tag %> 7: 8: <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> 9: <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %> 10: </head> 11: 12: <body> app/views/layouts/application.html.erb:9ググった結果以下のコマンドを実行で解決しました。
babelやpostceeなど各種設定ファイルの生成とyarn addを実行してくれるようです。
ただ設定ファイルはrails newした時点で存在していたのでyarn addする必要があるみたいですね。yarn add @rails/webpacker@4.2.2 from "."
yarn add --dev webpack-dev-server from "."$ docker exec bundle exec rails webpacker:installconflict config/webpacker.yml Overwrite /sample-app/config/webpacker.yml? (enter "h" for help) [Ynaqdhm] n skip config/webpacker.yml Copying webpack core config exist config/webpack identical config/webpack/development.js identical config/webpack/environment.js identical config/webpack/production.js identical config/webpack/test.js Copying postcss.config.js to app root directory identical postcss.config.js Copying babel.config.js to app root directory identical babel.config.js Copying .browserslistrc to app root directory identical .browserslistrc The JavaScript app source directory already exists apply /usr/local/bundle/ruby/2.5.0/gems/webpacker-4.2.2/lib/install/binstubs.rb Copying binstubs exist bin identical bin/webpack identical bin/webpack-dev-server File unchanged! The supplied flag value not found! .gitignore Installing all JavaScript dependencies [4.2.2] run yarn add @rails/webpacker@4.2.2 from "." yarn add v1.22.4 [1/4] Resolving packages... [2/4] Fetching packages... info fsevents@1.2.13: The platform "linux" is incompatible with this module. info "fsevents@1.2.13" is an optional dependency and failed compatibility check. Excluding it from installation. info fsevents@2.1.3: The platform "linux" is incompatible with this module. info "fsevents@2.1.3" is an optional dependency and failed compatibility check. Excluding it from installation. [3/4] Linking dependencies... warning " > webpack-dev-server@3.11.0" has unmet peer dependency "webpack@^4.0.0 || ^5.0.0". warning "webpack-dev-server > webpack-dev-middleware@3.7.2" has unmet peer dependency "webpack@^4.0.0". [4/4] Building fresh packages... success Saved 0 new dependencies. Done in 49.21s. Installing dev server for live reloading run yarn add --dev webpack-dev-server from "." yarn add v1.22.4 [1/4] Resolving packages... [2/4] Fetching packages... info fsevents@2.1.3: The platform "linux" is incompatible with this module. info "fsevents@2.1.3" is an optional dependency and failed compatibility check. Excluding it from installation. info fsevents@1.2.13: The platform "linux" is incompatible with this module. info "fsevents@1.2.13" is an optional dependency and failed compatibility check. Excluding it from installation. [3/4] Linking dependencies... warning "webpack-dev-server > webpack-dev-middleware@3.7.2" has unmet peer dependency "webpack@^4.0.0". warning " > webpack-dev-server@3.11.0" has unmet peer dependency "webpack@^4.0.0 || ^5.0.0". [4/4] Building fresh packages... success Saved 1 new dependency. info Direct dependencies └─ webpack-dev-server@3.11.0 info All dependencies └─ webpack-dev-server@3.11.0 Done in 4.67s. Webpacker successfully installed ? ?もう一度ブラウザから確認するとユーザー一覧画面が表示されていました!
ログを見るとwebpackでコンパイルされていることが分かります。Started GET "/users" for 111.239.186.32 at 2020-06-22 00:24:31 +0000 Cannot render console from 111.239.186.32! Allowed networks: 127.0.0.0/127.255.255.255, ::1 (17.7ms) SET @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'), @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483 Processing by UsersController#index as HTML Rendering users/index.html.erb within layouts/application User Load (8.9ms) SELECT `users`.* FROM `users` ↳ app/views/users/index.html.erb:16 Rendered users/index.html.erb within layouts/application (Duration: 10.6ms | Allocations: 731) [Webpacker] Compiling... [Webpacker] Compiled all packs in /sample-app/public/packs [Webpacker] Hash: 15d1bb7b54cf6326b9ba Version: webpack 4.43.0 Time: 2988ms Built at: 06/22/2020 12:24:36 AM Asset Size Chunks Chunk Names js/application-9afcbb5693aa87623e69.js 124 KiB application [emitted] [immutable] application js/application-9afcbb5693aa87623e69.js.map 139 KiB application [emitted] [dev] application manifest.json 364 bytes [emitted] Entrypoint application = js/application-9afcbb5693aa87623e69.js js/application-9afcbb5693aa87623e69.js.map [./app/javascript/channels sync recursive _channel\.js$] ./app/javascript/channels sync _channel\.js$ 160 bytes {application} [built] [./app/javascript/channels/index.js] 211 bytes {application} [built] [./app/javascript/packs/application.js] 749 bytes {application} [built] [./node_modules/webpack/buildin/module.js] (webpack)/buildin/module.js 552 bytes {application} [built] + 3 hidden modules Completed 200 OK in 5083ms (Views: 5073.4ms | ActiveRecord: 8.9ms | Allocations: 6105)まとめ
勉強して分かったことを追記していく予定です。一旦ここまで。
誰かの参考になれば幸いです。
- 投稿日:2020-06-23T21:47:34+09:00
Metabase+MySQLをdocker-composeで立ち上げる
こんばんは、@0yanです。
OSSのBIツール「Metabase」のDockerイメージからコンテナを立ち上げ、ローカルホストのMySQLサーバーに接続しようと思っていたのですが、DockerコンテナからローカルホストのMySQLサーバーに接続するのに苦戦したため方針変更。
docker-composeでMetabaseのDockerイメージとMySQLのDockerイメージから立ち上げることにしました。
本記事はそのやり方をまとめたものです。環境
- Windows 10 Pro
- Docker Desktop for Windows 2.3.0.3
- PowerShell
構成
ディレクトリの構成は以下のようにしました。
├── db | ├── data | ├── sql │ └── my.cnf | ├── app │ └── data | └── docker-compose.yml各種ファイルの作成
①docker-compose.yml
MySQLとMetabaseは公式イメージを使用します。
docker-compose.ymlversion: '3' services: db: image: mysql:5.7 container_name: mysql-server environment: MYSQL_ROOT_PASSWORD: xxxx MYSQL_DATABASE: test_db MYSQL_USER: user MYSQL_PASSWORD: password TZ: 'Asia/Tokyo' ports: - 3306:3306 volumes: - ./db/my.cnf:/etc/mysql/conf.d/my.cnf - ./db/data:/var/lib/mysql - ./db/sql:/docker-entrypoint-initdb.d app: image: metabase/metabase:latest container_name: metabase ports: - 3000:3000 volumes: - ./app/data:/mnt/data②my.cnf
MySQLで日本語を使用したいので、文字コードの設定をしてます。
my.cnf[mysqld] character-set-server=utf8 [client] default-character-set=utf8コンテナ立ち上げ
docker-compose.ymlがあるディレクトリで以下のコマンドを実行、起動します。
PS > docker-compose up -d Creating mysql-server ... done Creating metabase ... done PS > docker-compose ps Name Command State Ports -------------------------------------------------------------------------------------- metabase /app/run_metabase.sh Up 0.0.0.0:3000->3000/tcp mysql-server docker-entrypoint.sh mysqld Up 0.0.0.0:3306->3306/tcp, 33060/tcpMetabase起動
1分程度待機した後、ブラウザでlocalhost:3000にアクセスすると下の画面が表示されますので「開始しましょう」をクリックします。
下の画面で「データベースを選択する」をクリックし、MySQLを選択します。
項目 入力内容 名前 任意の名前 ホスト db ポート 3306 データベース名 test_db データベースユーザー名 user データベースパスワード password 下の画面で「次へ」をクリックします(匿名の情報収集は許容する場合のみオンにしてください)。
下の画面で「Metabaseを使い始める」をクリックします。
MySQL接続確認
起動すると下の画面になります。
右上の「照会する」をクリックします。
下の画面で接続したデータベースの名前(上表でご自身が付けた名前。私はテストデータベースという名前にしました)をクリックします。
下の画面になりますので、任意のSQL文を入れてみてください。
なお、複数のSQL文を同時実行はできません(例えば以下のようなSQL文はNGです)。
一文ずつ実行するようにしてください。create table employee (employee_no integer, employee_name varchar(30)); insert into employee values (1, 'Taro Yamada'); select * from employee;さいごに
「会社の数字をMetabaseでビジュアル化する」という目標のもと、
- docker
- docker-compose
- MySQL
と学んできましたが、やっと現実化できそうです。
今度はこの内容をEC2上で実行したいと思います。参考記事
- 投稿日:2020-06-23T15:36:00+09:00
Equalumがやって来た!(展開編2)
今回は各機能の検証と少し複雑な(?)FLOWを作ってみる!
前回の検証で、Equalumを使うと複雑なコーディングを実施しないで、データベースを含むSQL周辺の基本が抑えられていれば、誰でもリアルタイム・ストリーミングをデータ処理のプロセスに活用出来る事が確認出来ました。そこで今回はこのデータ処理を便利に行う為に、標準で提供されている幾つかのオペレーターに関する基本的な検証を行ってみたいと思います。
まずはJOINから・・
JOINはデータベースを取り扱った経験をお持ちの方であれば、その概要や留意点についての基本的な情報は理解されていると思いますので、この場ではそれらの詳細についての解説は割愛させて頂き、Equalumではどう使うのか?について検証して行きます。
まずは、前回同様にEvent Stream形式のソース側を2個用意します。
次にOperatorメニューからJOINを選択します。
先ほど設置したEvent Streamを接続します。
JoinにあるEditボタンを選択して必要事項を設定します。
修正が必要な個所が赤字で指示されますので、適宜それらを修正して行きます。今回はidとtsが衝突していますので、この場所で編集作業を行います。編集は、各項目の右端にある編集アイコンを選択して行います。
JOINのタイプはプルダウンメニューで選択できます。今回はInnerで検証してみます。
次にConditionの項目にJOINの条件を設定します。今回はデータのIDで強制的に突合させてしまいます。最後に、ストリーミング処理ならでは(?)の条件を忘れずに設定しておきます。
Time Windowについては調整項目になる様ですが、今回の小規模環境では1を設定して検証しました。次にターゲットのデータソースを定義します。
ここまでくれば、Joinとターゲットを接族してターゲット側のEditボタンを選択して、前回同様の設定を行って行けばOKです。テーブル定義もこの場所で自動的にSQL文を生成してくれますので、問題が無ければ確認してそのまま利用できますが、今回の検証では事前定義したテーブルに着地させる事にします。
この状態で、前回の検証同様に上流側のデータソースにPythonで自動的にデータを連続挿入し(2つのテーブルにそれぞれ1秒間隔で)、その結果をストリーミング処理しながら下流側のデータソースのテーブルに反映させます。(シンプル&力技でのJOINですので、出来上がりは美しくないかもしれませんが・・・そこは基本機能の検証という事でご容赦の程。。)
データ数が少なかったので、上流側のテーブルに挿入が始まってから終わるまでの時間が一瞬で終了し、ほぼ同時に下流側のストリーミングJOIN処理も出来上がってしまいましたので呆気なく検証は終了です。
たぶん一番使いそうなTransformを検証
次にTransformを検証してみます。
この検証では、シナリオとして消費税のカラムを現状のデータフローに対して「後付け」で設定して下流側のテーブルに反映させてみる事にします(その位の準備は事前に・・・という話もありますが・・・)
まずは、最上流のデータソースの準備をいつも通りに行い、OperatorからTransformを選択してFlowを接続します。
次に「+」ボタンを選択し
取り扱うフィールドを追加します。
基本的にこの設定で新たなカラムが「この段階で設定される」事になります。
カラムの順番は右側の上下ボタンで調整が可能です。
これで右下のOKボタンを選択し、ターゲットのデータソース(この場合もFlow設定すると上流側である今回のTransform情報をベースにプロトタイプを作成してくれますので、その情報を活用してテーブルを生成する事が可能です)を設定し、今まで同様に1秒毎にデータを自動生成して上流側に挿入すれば、そのアクションを自動検知して今回設定した手順の処理を行い、下流側のターゲットテーブルを即時生成していく形になります。
上流側に自動挿入されたデータはこんな感じになります。
Tax項目を途中追加して生成された下流側のテーブルはこんな感じになります。
今回のまとめ
駆け足になりましたが、今回はJOINとTRANSFORMの検証を行いました。
複雑なkafka系コーディングや、Spark連携等の作業を考える必要なく、かなり高度なリアルタイム・データストリーミングをデザイン出来る可能性は感じて頂けたかと思いますが、次回の検証ではさらに複雑(?)な流れ
の作成に挑戦してみたいと思います。
ゼロコーディングで高度なkafka/Spark連携のストリーミング環境を構築!
専用の最適化・専用実装を行ったDeepなkafkaの世界には負けるかもしれませんが、誰でもかなり早いkafkaストリーミングでのデータ連携・活用環境が作れる!という点においては、非常に可能性を秘めた環境であると言えるでしょう。
バッチ処理しか選択肢が無い時代は過去の話になりました。
今をデータ活用で変えるのであれば、その選択肢は必然的にリアルタイム・ストリーミングになると思います。
データで今を変えて未来を創る!!
これがDxにおけるデータ・ドリブンの真骨頂なのだと思います・・・謝辞
本検証は、Equalum社の特別の許可を得て実施しています。この貴重な機会を設定して頂いたEqualum社に対して感謝の意を表すると共に、本内容とEqualum社の公式ホームページで公開されている内容等が異なる場合は、Equalum社の情報が優先する事をご了解ください。
- 投稿日:2020-06-23T11:48:33+09:00
【MySQL】MySQL 8 でユーザー作成しGRANTで権限追加する際にエラーが発生
ターミナル## MySQLに root で接続 $ mysql -uroot -p ## ユーザー作成 > CREATE USER 'homestead'@'localhost' IDENTIFIED BY 'XXX'; ## ユーザーに全権限追加 > GRANT ALL ON *.* TO 'homestead'@'localhost' IDENTIFIED BY 'XXX'; >> エラー発生 ## 権限の変更をデータベースに反映 FLUSH PRIVILEGES;
GRANT
でエラー発生
原因:MySQL8.0ではGRANT構文でユーザを作成できない
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
解決策ターミナル## MySQLに root で接続 $ mysql -uroot -p ## ユーザー作成 > CREATE USER 'homestead'@'localhost' IDENTIFIED BY 'XXX'; ## ユーザーに全権限追加 > GRANT all ON *.* TO 'homestead'@'localhost'; ## 権限の変更をデータベースに反映 > FLUSH PRIVILEGES;log## MySQLに root で接続 $ mysql -uroot -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 19 Server version: 8.0.19 Homebrew Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. ## ユーザー作成 mysql> mysql> CREATE USER 'homestead'@'localhost' IDENTIFIED BY 'XXX'; Query OK, 0 rows affected (0.00 sec) ## ユーザーに権限追加 mysql> GRANT ALL ON *.* TO 'homestead'@'localhost' IDENTIFIED BY 'XXX'; ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'IDENTIFIED BY 'XXX'' at line 1 >> エラー発生
- 投稿日:2020-06-23T04:52:48+09:00
(自分用)Flask_7(Flaskからデータベースを開く)
項目
- Flaskからデータベースを開く
(今日は疲れてるのでこれだけで)1.Flaskからデータベースを開く
pythonfrom flask import Flask, render_template import pymysql app = Flask(__name__) def getConnection(): return pymysql.connect( host='localhost', db='mydb', user='root', password='', charset='utf8', cursorclass=pymysql.cursors.DictCursor ) @app.route('/') def select_sql(): connection = getConnection() sql = "SELECT * FROM players" cursor = connection.cursor() cursor.execute(sql) players = cursor.fetchall() cursor.close() connection.close() return render_template('view.html', players = players)
- python側に関しては基本的には今までの組み合わせ
- 前回やった
import pymysql
でPython内でMySQLを使えるようにしているdef getConnection():return pymysql.connect()
で、getConnection()
を呼び出した時に、dbを呼び出す材料が手に入るようになっているconnection = getConnection()
でconnection
に呼び出す情報を入れて- 下の幾つかは前回と同じ動き
- そんでFlaskの手順で
return
に代入した変数を入れてhtml側でも使えるようにしているview.html{% for player in players %} <p>{{ player }}</p> {% endfor %}
- なんの変哲もないpy側から渡された変数をfor文で表示する儀式
- これ入れればとりあえずOK
あとは普通にFlaskを起動すれば完了(一応下に起動のあれも載せておく)
ターミナルとか$ cd <作業ディレクトリが入ってるフォルダ名とか> $ FLASK_APP=<作業pyディレクトリ名> FLASK_ENV=development flask run2.終わりに
- かなり短い
- 48時間で3時間しか寝てないぽいのでちょっと今日は休む
- SQLでデータ削除とかAWS本格的に借りて動かすのとかは明日(今日?)にお預け
- 投稿日:2020-06-23T02:03:51+09:00
リモートデバッグ可能なNginx, Spring Boot, MySQLの開発環境をDockerで作った
前置き
最近、WebサイトをSpring Bootで開発しています。以前に投稿した記事のような開発環境が欲しくなってきましたので調査しました。前回とほぼ同じ形式で執筆します。
動作環境
OS macOS Catalina 10.15.5 Docker docker desktop community 2.3.0.3 (45519) Spring Tool Suite Version: 4.5.1.RELEASE Spring Bootプロジェクト
InteliJ + Kotlin + gradleとしたいところですが、現在携わっている環境に近い構成でやっていこうと思います。
モダンJavaだとこの組み合わせ減ってると思います
- Spring Boot 2.2
- Java OpenJDK 11
- STS 4
- Maven 3.6.3
構築イメージ
以下のコンテナを作成します。
- MySQL
- ホストOSのMySQL Workbenchでアクセスできる(localhost:3306)
- Spring Boot
- ホストOSのブラウザでアクセスできる(localhost:8080)
- STS(Eclipse)からリモートデバッグできる(localhost:5005)
- Nginx
- HTTPSでアクセスできる(https://devnokiyo.example.com)
- ただし、GitHubにソースコードを公開する関係で自己署名SSL証明書)
もちろん、コンテナ間も通信を行います。
構成
GitHubに公開しています。併せてご覧ください。
前述の記事同様にDocker周りだけを管理したいディレクトリと永続化だけを管理したいディレクトリに分けました。
以降、粛々とファイルとその説明が続きます。「とにかくGitHubのコードを動かしたい」方はこちらまで飛んでください$ tree ├── README.md ├── docker # DockerやDocker Compose │ ├── containers # 各コンテナ(イメージ) │ │ ├── mysql # MySQL 5.7 │ │ │ ├── Dockerfile # MySQL 5.7のDockerファイル │ │ │ ├── initialize_data.sql # 初期セットアップでユーザとサンプルデータを作成するスプリプト │ │ │ └── my.cnf # 初期セットアップで反映するmy.cnf │ │ ├── nginx # Nginx 1.19.0 │ │ │ ├── Dockerfile # NginxのDockerファイル │ │ │ └── nginx.conf # 初期セットアップで反映するnginx.conf │ │ └── spring # OpenJDK 11 (Spring Boot構築用) │ │ └── Dockerfile # Spring Boot構築用のDockerファイル │ ├── docker-compose.yml # Docker Composeファイル │ └── environments # 環境変数定義 │ ├── common.env # 各コンテナ共通 │ └── db.env # DB接続用MySQL関連 └── volumes # 永続化するリソース ├── app # Spring Bootのプロジェクト (以下、特筆点するディレクトリ/ファイルのみコメント) │ ├── .m2 # Mavenのローカルリポジトリ │ ├── mvnw # Maven Wrapper 今回はこれを使ってSpring Bootを起動する │ └── src # ソースコード │ └── main │ └── resources # この配下にstaticディレクトリを作成しない (静的ファイルはNginxで返す) ├── db # MySQLのデータ このディレクトリは最初は無し └── web # Nginxのファイル ├── ssl # SSL証明書 │ ├── privkey.pem # 秘密鍵 │ └── server.crt # サーバー証明証 └── static # 静的ファイル置き場Composeファイル
docker/docker-compose.ymlversion: '3' services: # 各コンテナ(サービス) db: # MySQLのコンテナ 「db」と命名 build: containers/mysql # Dockerファイルのパス env_file: # 環境変数 - ./environments/common.env # 各コンテナ共通 - ./environments/db.env # DB接続用MySQL関連 volumes: # 永続化 - ../volumes/db/data:/var/lib/mysql # MySQLのデータ ports: # 開放ポート - 3306:3306 # ホストOSのWorkBenchでDBを参照する目的 app: # Spring Bootのコンテナ 「app」と命名 build: containers/spring # Dockerファイルのパス env_file: # 環境変数 - ./environments/common.env # 各コンテナ共通 - ./environments/db.env # DB接続用MySQL関連 # 実行するコマンド(後述) command: ./mvnw clean spring-boot:run -Dspring-boot.run.jvmArguments="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=*:5005" volumes: # 永続化 - ../volumes/app:/app # Spring Bootのプロジェクト - ../volumes/app/.m2:/root/.m2 # Mavenのローカルリポジトリ ports: # 開放ポート - 8080:8080 # ホストOSからNginxを通さずTomcatを直接参照する目的 - 5005:5005 # IDEでリモートデバッグする目的 depends_on: # 起動する順番 - db # 「db」の後で起動 web: # Nginxのコンテナ 「web」と命名 build: containers/nginx # Dockerファイルのパス env_file: # 環境変数 - ./environments/common.env # 各コンテナ共通 volumes: # 永続化 - ../volumes/web/static:/usr/share/nginx/www/ # 静的ファイル (Spring Bootプロジェクトのresouce/staticには配置しない) - ../volumes/web/ssl:/etc/nginx/cert/ # SSL証明書 - ../volumes/web/log:/var/log/nginx/ # Nginxのログ ports: # 開放ポート - 443:443 # HTTPS この開発環境はHTTPSのみ想定 depends_on: # 起動する順番 - app # 「app」の後で起動db(MySQL)コンテナ
Dockerファイル
docker/containers/mysql/Dockerfile# MySQL 5.7 FROM mysql:5.7 # 初期セットアップで利用するmy.cnfをイメージへコピー # アーカイブを展開する必要などが無ければADDで無くてCOPYで良い。 COPY my.cnf /etc/mysql/conf.d # 初期セットアップで実行したいスクリプトをイメージへコピー COPY initialize_data.sql /docker-entrypoint-initdb.dコピーするファイルの概要
ホスト イメージ 概要 docker/containers/mysql/my.cnf /etc/mysql/conf.d/ 文字コード docker/containers/mysql/initialize_data.sql /docker-entrypoint-initdb.d/ Spring Bootアプリ向けDBアカウント/サンプルデータ Docker Comopseから設定される環境変数
docker/environments/common.envTZ=Asia/Tokyodocker/environments/db.envMYSQL_ROOT_PASSWORD=root MYSQL_USER=spring MYSQL_PASSWORD=springDocker Comopseから設定される永続化
ホスト コンテナ 概要 volumes/db/data /var/lib/mysql MySQLのデータ app(Spring Boot)コンテナ
Dockerファイル
docker/containers/spring/DockerfileFROM openjdk:11 # 永続化でマウントされるパスをワーキングディレクトリに指定 WORKDIR /appDocker Comopseから設定される環境変数
docker/environments/common.envTZ=Asia/Tokyodocker/environments/db.envMYSQL_ROOT_PASSWORD=root MYSQL_USER=spring MYSQL_PASSWORD=springDocker Comopseから設定される永続化
ホスト コンテナ 概要 volumes/app/ /app Spring Bootのプロジェクト
GitHubに公開しているものは予めサンプルアプリが入っています)volumes/app/.m2 /root/.m2 Mavenのローカルリポジトリ
./mvnw cleanを実行するとプラグイン/ライブラリなどを毎回ダウンロードしてしまうことを防ぎます。Docker Comopseのcommand
こちらのコマンドについて少し補足します。
./mvnw clean spring-boot:run -Dspring-boot.run.jvmArguments="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=*:5005"
コマンド 概要 ./mvnw Java -jar
による起動は開発中のコードが更新されたときの自動リロードが無効になってしまうので、Mavenで起動することにしました。Maven WrapperがあればMavenをインストールする必要がないので、mvnw
を採用しました。address=*:5005 JDWPのポートを指定しますが、 ホストOSからコンテナへアクセスするには *:5005
とする必要があります。ポート番号しか書いていないネット情報が多いのでご注意くださいweb(Nginx)コンテナ
Dockerファイル
docker/containers/nginx/DockerfileFROM nginx:1.19.0 # 初期セットアップで反映するファイルをコピー COPY nginx.conf /etc/nginx/conf.d/app.conf CMD /usr/sbin/nginx -g 'daemon off;' -c /etc/nginx/nginx.confコピーするファイルの概要
ホスト イメージ 概要 docker/containers/nginx/nginx.conf /etc/nginx/conf.d/app.conf 後述 WEBサーバーの設定
トリッキーな設定は無いと思いますが簡単に補足します。
GitHubに公開しているものはSSL証明書については「*.example.com」の自己署名SSL証明書(所謂「オレオレ証明書」)を利用しています。筆者の環境ではLet's EncryptのSSL証明書を利用しています。docker/containers/nginx/nginx.confserver { listen 443 ssl; server_name devnokiyo.example.com; ssl_certificate /etc/nginx/cert/server.crt; ssl_certificate_key /etc/nginx/cert/privkey.pem; ssl_prefer_server_ciphers on; access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; root /app/public; try_files $uri /; client_max_body_size 10m; error_page 404 /404.html; error_page 505 502 503 504 /500.html; location / { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_set_header X-CSRF-Token $http_x_csrf_token; proxy_set_header X-Forwarded-Proto $scheme; proxy_pass http://app:8080; } # Spring Bootの静的ファイルはNginxで返す。 location ~* .*\.(jpg|gif|png|css|js|ico|svg) { root /usr/share/nginx/www; access_log off; } }Docker Comopseから設定される環境変数
docker/environments/common.envTZ=Asia/TokyoDocker Comopseから設定される永続化
ホスト コンテナ 概要 volumes/web/static/ /usr/share/nginx/www/ 静的ファイル volumes/web/ssl/ /etc/nginx/cert/ SSL証明書 volumes/web/log/ /var/log/nginx/ ログ 実行してみましょう!
Docker Composeで起動
だいぶ簡単でしたが各ファイルの説明が終わりましたので実行して確認します。
- GitHubから一式ダウンロードします。
dockerディレクトリへ移動します。
$ cd dockerビルドします。(初回なので起動でも構いません)
$ docker-compose build --no-cache Building db Step 1/3 : FROM mysql:5.7 ---> 9cfcce23593a Step 2/3 : COPY my.cnf /etc/mysql/conf.d ---> 4af29808e20c : : Successfully built b074e2d8831d Successfully tagged docker_web:latest起動します。
$ docker-compose up Creating network "docker_default" with the default driver Creating docker_db_1 ... done Creating docker_app_1 ... done Creating docker_web_1 ... done Attaching to docker_db_1, docker_app_1, docker_web_1 db_1 | 2020-06-22 23:04:49+09:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.30-1debian10 started. : : db_1 | Version: '5.7.30' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server (GPL) : : app_1 | [INFO] Scanning for projects... app_1 | Downloading from central: https://repo.maven.apache.org/maven2/org/springframework/boot/spring-boot-starter-parent/2.2.8.RELEASE/spring-boot-starter-parent-2.2.8.RELEASE.pom app_1 | Downloading from central: https://repo.maven.apache.org/maven2/org/springframework/boot/spring-boot-dependencies/2.2.8.RELEASE/spring-boot-dependencies-2.2.8.RELEASE.pom : : app_1 | [INFO] Attaching agents: [] app_1 | Listening for transport dt_socket at address: 5005 app_1 | app_1 | . ____ _ __ _ _ app_1 | /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ app_1 | ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ app_1 | \\/ ___)| |_)| | | | | || (_| | ) ) ) ) app_1 | ' |____| .__|_| |_|_| |_\__, | / / / / app_1 | =========|_|==============|___/=/_/_/_/ app_1 | :: Spring Boot :: (v2.2.8.RELEASE) app_1 | app_1 | 2020-06-22 23:07:31.526 INFO 74 --- [ restartedMain] com.example.demo.DemoApplication : Starting DemoApplication on e5dd9a4954d8 with PID 74 (/app/target/classes started by root in /app) : : app_1 | 2020-06-22 23:07:37.683 INFO 74 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path '' app_1 | 2020-06-22 23:07:37.686 INFO 74 --- [ restartedMain] com.example.demo.DemoApplication : Started DemoApplication in 6.781 seconds (JVM running for 8.41)ブラウザからアクセス
hostsファイルにdevnokiyo.example.comをループバックIPで設定して
https://devnokiyo.example.com
にアクセスします。不正な証明書ということでエラーが出ると思いますが便宜上例外を許可してください。以下はChromeの例ですが表示自体はされています。
Nginxを経由でWebサイトにアクセスできています
なお、ポポデザイン様のテンプレートを利用させて頂きました。感謝申し上げます。前述のとおり筆者専用環境ではLet's EncryptのSSL証明書を利用しています。ご参考までに正常な証明書扱いの画像も載せておきます。独自ドメインを所有しておりhoge.devnokiyo.comで取得した例になります。
Tomcatへアクセス
Nginxの設定の誤りで動作不良になることもあると思いますので、Tomcatへの直接アクセスも許可しています。念のためアクセスできるか確認します。
http://localhost:8080
にアクセスします。レイアウトが崩れています
しかし、静的ファイルはNginxから返されるように設定しているので問題ありません
ホストOSからMySQLへ接続を確認
ホストOSのMySQL Workbenchから以下にアクセスします。
ホスト名 127.0.0.1 ポート 3306 ユーザー spring パスワード spring TomcatからMySQLへ接続を確認
Docker Composeで定義したコンテナ間でMySQLへ接続できるか確認します。
https://devnokiyo.example.com/form
へアクセスしてお問い合わせしてみます。
送信ボタンを押下します。
再度MySQL Workbenchでテーブルを参照するとレコードが1行増えていますね
リモートデバッグする
Spring BootをDockerでコンテナ化しましたが、ブレークポイントを利用できないと不便です。STS(Eclipse)からTomcatのコンテナをアタッチしてデバッグできるようにします。
準備
STS(Eclipse)のメニューから
Run
->Debug Configurations...
を選択します。Remote Java Applicaion
でdemo
プロジェクトをDebugします。
ブレークポイントを設定
RootControllerの29行目にブレークポイントを設定しました。
http://devnokiyo.example.com/form
へアクセスするとブレークポイントで処理が止まります。
自動リロード
ソースコードを修正したときに毎回ビルドするのは面倒なので、Spring Boot Devtoolsの自動リロードを利用します。前述のとおり
Java -jar
による起動は開発中のコードが更新されたときの自動リロードが無効になってしまいますが、Maven WrapperでSpring Bootを起動しているので自動リロードできます。ソースコード修正
以下のアクションメソッドを追加してみます。コントローラークラスのファイルを保存するとリロードされます。
RootController.java@GetMapping("/hoge") public String hoge() { return "root/index"; }自動リロード中
コンソールをみるとリロードの状況がわかります。1行目が初回起動時の日時で2行目以降が自動リロードの挙動になります。
app_1 | 2020-06-23 00:09:00.911 INFO 40 --- [ restartedMain] com.example.demo.DemoApplication : Started DemoApplication in 6.459 seconds (JVM running for 8.092) app_1 | 2020-06-23 00:21:51.379 INFO 40 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet' app_1 | 2020-06-23 00:21:51.379 INFO 40 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet' app_1 | 2020-06-23 00:21:51.389 INFO 40 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 9 ms app_1 | 2020-06-23 00:36:13.585 INFO 40 --- [ Thread-5] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor' app_1 | 2020-06-23 00:36:13.588 INFO 40 --- [ Thread-5] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default' app_1 | 2020-06-23 00:36:13.651 INFO 40 --- [ Thread-5] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated... app_1 | 2020-06-23 00:36:13.755 INFO 40 --- [ Thread-5] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed. app_1 | app_1 | . ____ _ __ _ _ app_1 | /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ app_1 | ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ app_1 | \\/ ___)| |_)| | | | | || (_| | ) ) ) ) app_1 | ' |____| .__|_| |_|_| |_\__, | / / / / app_1 | =========|_|==============|___/=/_/_/_/ app_1 | :: Spring Boot :: (v2.2.8.RELEASE) app_1 | app_1 | 2020-06-23 00:36:14.036 INFO 40 --- [ restartedMain] com.example.demo.DemoApplication : Starting DemoApplication on e5dd9a4954d8 with PID 40 (/app/target/classes started by root in /app) app_1 | 2020-06-23 00:36:14.037 INFO 40 --- [ restartedMain] com.example.demo.DemoApplication : No active profile set, falling back to default profiles: default app_1 | 2020-06-23 00:36:14.500 INFO 40 --- [ restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode. : : app_1 | 2020-06-23 00:36:15.884 INFO 40 --- [ restartedMain] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729 app_1 | 2020-06-23 00:36:15.907 INFO 40 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path '' app_1 | 2020-06-23 00:36:15.908 INFO 40 --- [ restartedMain] com.example.demo.DemoApplication : Started DemoApplication in 1.965 seconds (JVM running for 1644.96) app_1 | 2020-06-23 00:36:15.911 INFO 40 --- [ restartedMain] .ConditionEvaluationDeltaLoggingListener : Condition evaluation unchanged app_1 | 2020-06-23 00:36:30.177 INFO 40 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet' app_1 | 2020-06-23 00:36:30.178 INFO 40 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet' app_1 | 2020-06-23 00:36:30.183 INFO 40 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 5 ms修正後の確認
https://devnokiyo.example.com/hoge
にアクセスしてトップページと同じページが表示されることを確認します。
終わりに
前回同様に基礎的なコマンドの説明よりは「筆者はこうやった」的なことをメインに記事を書いてみました。JVM系はRubyやGoと比較するとDocker周りの情報が少ない印象です。(点々とした情報はあるのですが、線になっている情報は少ない雰囲気です。)
ひととおりの手順を習得できたので、どのくらい開発環境として使っていけるか運用してみようと思います。