Flywayを触ってみる(コマンドライン)
はじめに
データベースマイグレーションツールの一つであるFlywayを触ってみます。
業務で使用しているものの、私がやっていることはDBに変更があった際のマイグレーションファイルを作成する程度なので、改めて使用方法などを整理できればと思います。
なお、私の仕事上ではSpring boot
と併用していますが、今回はSpring
プロジェクトを作成するほどのことでもないので、コマンドライン上でのお試しとします。
Spring
との併用はそのうちやります・・。
マイグレーションとは
データベースの変更を記録することで、データベースの変更を容易にするためのもの・・と理解しています。
やってみる
Flywayも、他のツールに漏れず公式ドキュメントが充実しているので、そちらを参考に実施していきます。
インストール
先述したように、今回はコマンドツールを用いてFlyway
を利用していきます。
また、今回は学習用ですので、Community Edition(無料)をインストールします。
こちらから、適宜環境にあったものをダウンロードしましょう。
FlywayをPATHに通す
Flyway
をPATHに通します。私はfish
というシェルを使用しているため、~/.config/fish/config.fish
に以下の記述を追記しました。
set PATH /Users/ochiaisho/devTools/flyway-7.8.2 $PATH
zsh
や、bash
など、各自の環境に合わせてPATHを通すようにしましょう。
flyway.confの修正
データベース接続情報をconf/flyway.conf
に記述します。
私の場合は以下のようになります。
flyway.url=jdbc:mysql://localhost:3306/flyway flyway.user=root flyway.password=password
マイグレーションファイルの作成
実際にデータベースへ反映するためのマイグレーションファイルを作成します。
今回は、新しくUser
というテーブルを作成するDDLを追加します。
create table USER ( ID int not null, NAME varchar(100) not null );
ここまでで、準備はあらかた終了です。
flyway migrate
それでは実際にflyway migrate
を実行してみましょう。
$ flyway migrate
成功すると、以下のようなレスポンスとなります。
(バージョンやデータベース名などは適宜読み替えてください。)
Flyway Community Edition 7.8.2 by Redgate Database: jdbc:mysql://localhost:3306/flyway (MySQL 8.0) Successfully validated 1 migration (execution time 00:00.017s) Creating Schema History table `flyway`.`flyway_schema_history` ... Current version of schema `flyway`: << Empty Schema >> Migrating schema `flyway` to version "1 - create user" Successfully applied 1 migration to schema `flyway`, now at version v1 (execution time 00:00.040s)
成功すると、User
テーブルと、flyway_schema_history
というテーブルが作成されます。
mysql> show tables; +-----------------------+ | Tables_in_flyway | +-----------------------+ | flyway_schema_history | | USER | +-----------------------+ 2 rows in set (0.00 sec)
User
テーブルは自分で作成したテーブルなのでいいとして、flyway_schema_history
というテーブルはなんなのでしょうか?
ということで、もう少し続けます。
flyway_schema_historyとは
平たく言うと、flyway_schema_history
はテーブルのマイグレーション(変更)の記録を保持するテーブルとなります。
見てみる方が早いと思いますので、とりあえず作成されたテーブルの中身を調べてみることにしましょう。
mysql> select * from flyway_schema_history; +----------------+---------+-------------+------+---------------------+------------+--------------+---------------------+----------------+---------+ | installed_rank | version | description | type | script | checksum | installed_by | installed_on | execution_time | success | +----------------+---------+-------------+------+---------------------+------------+--------------+---------------------+----------------+---------+ | 1 | 1 | create user | SQL | V1__create_user.sql | 1761476051 | root | 2021-05-09 14:48:27 | 10 | 1 | +----------------+---------+-------------+------+---------------------+------------+--------------+---------------------+----------------+---------+ 1 row in set (0.00 sec)
今回、User
というテーブルを作成した履歴が残っているのがわかるかと思います。
履歴が残るということを確認したいので、試しに別のテーブルを作成してみましょう。
マイグレーションファイルを追加する
今回も、テーブル追加のためのマイグレーションファイルを作成しようと思います。
sql
ディレクトリ配下に、V2__create_second_table.sql
というファイル名で、適当なテーブルを作成しようと思います。
create table SECOND_TABLE( ID int not null, );
ファイルが作成できたら、再度flyway migrate
を実行してみます。
$ flyway migrate
成功すると以下のようなメッセージが返ってきます。
Flyway Community Edition 7.8.2 by Redgate Database: jdbc:mysql://localhost:3306/flyway (MySQL 8.0) Successfully validated 2 migrations (execution time 00:00.018s) Current version of schema `flyway`: 1 Migrating schema `flyway` to version "2 - create second table" Successfully applied 1 migration to schema `flyway`, now at version v2 (execution time 00:00.050s)
この状態で再度データベースの状態を確認してみましょう。
mysql> show tables; +-----------------------+ | Tables_in_flyway | +-----------------------+ | flyway_schema_history | | SECOND_TABLE | | USER | +-----------------------+ 3 rows in set (0.00 sec)
show tables
で確認すると、SECOND_TABLE
が作成されていることがわかりますね。
次に、flyway_schema_history
の中身も確認してみましょう。
mysql> select * from flyway_schema_history; +----------------+---------+---------------------+------+-----------------------------+------------+--------------+---------------------+----------------+---------+ | installed_rank | version | description | type | script | checksum | installed_by | installed_on | execution_time | success | +----------------+---------+---------------------+------+-----------------------------+------------+--------------+---------------------+----------------+---------+ | 1 | 1 | create user | SQL | V1__create_user.sql | 1761476051 | root | 2021-05-09 14:48:27 | 10 | 1 | | 2 | 2 | create second table | SQL | V2__create_second_table.sql | 942681622 | root | 2021-05-09 15:17:43 | 15 | 1 | +----------------+---------+---------------------+------+-----------------------------+------------+--------------+---------------------+----------------+---------+ 2 rows in set (0.00 sec)
レコードが追加されていますね。
このような形で、Flywayが実行したマイグレーションの履歴がどんどん積み重なっていくことになります。
おまけ
実はSECOND_TABLE
を追加しようとしたところ、sql syntax error
が発生したため、マイグレーションに失敗した、という事象が発生していました。
そこで、SQLを修正し、再度flyway migrate
を実行したところ、さらに別のエラーが発生・・ということも発生したんですね。つまり、
という流れです。この時のエラー解消方法を念のため記録しておこうと思います。
エラー内容
まずは実際のエラー内容から。
(なお、実際はsql syntax error
も出ていましたが、直接Flyway
とは関係ないので割愛しています。)
ERROR: Validate failed: Migrations have failed validation Detected failed migration to version 2 (create second table). Please remove any half-completed changes then run repair to fix the schema history. Need more flexibility with validation rules? Learn more: https://flywaydb.org/custom-validate-rules
Please remove any half-completed changes then run repair to fix the schema history.
ということなので、不完全な状態の変更を削除してから再実行するのが正しいようです。
ここで、上記の1.
でエラーが発生した直後のflyway_schema_history
を確認してみます。
+----------------+---------+---------------------+------+-----------------------------+------------+--------------+---------------------+----------------+---------+ | installed_rank | version | description | type | script | checksum | installed_by | installed_on | execution_time | success | +----------------+---------+---------------------+------+-----------------------------+------------+--------------+---------------------+----------------+---------+ | 1 | 1 | create user | SQL | V1__create_user.sql | 1761476051 | root | 2021-05-09 14:48:27 | 10 | 1 | | 2 | 2 | create second table | SQL | V2__create_second_table.sql | -371576338 | root | 2021-05-09 15:15:48 | 17 | 0 | +----------------+---------+---------------------+------+-----------------------------+------------+--------------+---------------------+----------------+---------+
実は、マイグレーションに失敗しても、flyway_schema_history
にレコードは追加されます。
ここでさらにレコードの内容をみてみると、success
というカラムがマイグレーションの成否を表すカラムであることに気づくと思います。
1が成功、0が失敗ですね。
そこで、マイグレーションに失敗しているレコードであるsuccess=0
のレコードを削除してから再度flyway migrate
を実行することでエラーが解消され、マイグレーションが成功しました。
終わりに
マイグレーションツールを使用すれば、データベースに対する変更が正しい順序で反映されるので、ちゃんと使用できれば便利ですね。今回はやりませんでしたが、例えばカラムの削除・カラム定義の変更など、テーブルの初期状態からの変化を正しい順序で実行していくというのは手作業ではどうしても難しいシーンもあると思いますので、そういったことへの対策にもなりそうです。
Dockerを学ぶ(第3回)
はじめに
今回は、アプリケーションを修正してイメージの再作成を行います。
アプリケーションの修正
前回cloneしたアプリについて、TODOが0件の場合のメッセージを修正します。
修正後、最後イメージの作成とアプリケーションの開始を行います。 前回と同様のコマンドを実行しましょう。
- ビルド
$ docker build -t getting-started .
- コンテナスタート
$ docker run -dp 3000:3000 getting-started
前回の続きを実施している場合、この時点でエラーが発生します。
前回docker run
したコンテナが現在も動いているためです。これは、前回docker run
したコンテナと今回docuer run
するコンテナとでリッスンするPORTが重複しているためです。
今回は、前回スタートしたコンテナを削除することでこの問題を解決します。
コンテナの削除
コンテナを削除するためには、以下の手順を踏む必要があります。
- コンテナIDの取得
- コンテナの停止
- コンテナの削除
それでは、順に実施していきましょう。
コンテナIDの取得
まずはじめに、docker ps
を使用して、コンテナのIDを取得します。
$ docker ps
すると結果が以下のようになると思います。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 88c0598817c1 5b0fd87f541d "docker-entrypoint.s…" 32 minutes ago Up 32 minutes 0.0.0.0:3000->3000/tcp jovial_merkle 5261b924c97e docker/getting-started "/docker-entrypoint.…" 2 hours ago Up 2 hours 0.0.0.0:80->80/tcp unruffled_hopper
1番左端のCONTAINER IDがコンテナのIDとなりますので、このIDをメモなりしておきましょう。
コンテナの停止
先ほどの手順で取得したIDを使用して、コンテナを停止します。
$ docker stop <docker-id>
コンテナの削除
$ docker rm <docker-id>
ここまで出来たら、再度docker ps
を実施してみましょう。コンテナが削除されていることがわかると思います。
コンテナの起動
古いコンテナが削除できましたので、最初に再作成したイメージを使用してコンテナを開始しましょう。
$ docker run -dp 3000:3000 getting-started
もう一度http://localhost:3000にアクセスしてみましょう。
タスクが0件のときのメッセージが変更されているはずです!!
Dockerを学ぶ(第2回)
はじめに
今回もDocker公式ドキュメントを実施してみます。
お次はどうやらNode.js
を使用したサンプルアプリケーションを使ったチュートリアルになるようです。
とはいえ、JavaScript
の経験がなくとも問題ないようですよね、安心して実施していきます。(?)
サンプルアプリケーションの取得
以下のコマンドを実行します。
なお、こちらのリポジトリはgetting-startedで使用する全てのコードが含まれていますが、今回使用するのは/app
ディレクトリとなります。
$ git clone https://github.com/docker/getting-started.git
コンテナイメージのビルド
ここから、/app
をコンテナ化するためのイメージを作成していきます。
Dockerfileの作成
アプリケーションをビルドするために、まずはDockerfile
を作成します。
Dockerfile
には、コンテナイメージで使用される手順(指示)スクリプトをテキストベースで記述します。
それでは実際に作成していきましょう。
Dockerfile
をpackage.json
があるディレクトリと同じディレクトリに作成します。(/app
ディレクトリ内に作成する)
# syntax=docker/dockerfile:1 FROM node:12-alpine RUN apk add --no-cache python g++ make WORKDIR /app COPY . . RUN yarn install --production CMD ["node", "src/index.js"]
この時、.txt
などの拡張子がつかないように注意します。ファイル名は単にDockerfile
としてください。
docker build
Dockerfile
が作成できたら、ターミナルからdocker build
を実行します。
ターミナルで、app
ディレクトリへ移動するのを忘れずに。
完全なコマンドは以下となります。
$ docker build -t getting-started .
(最後のピリオドを忘れずに!!)
今回もコマンドについて解説します。
フラグ | 解説 |
---|---|
-t getting-started | -t をつけると、イメージにタグ名をつけることができます。 |
. (最後のピリオド) | Dockerfileがカレントディレクトリにあることを表します。 |
Dockerfile
に記述されている内容についてはいずれまとめます・・・。
コンテナの開始(docker run)
イメージが完成したので、アプリケーションを実行してみます。
$ docker run -dp 3000:3000 getting-started
(コマンド中の-dp
は-d -p
と同じ意味です)
コマンド実行が成功しましたら、ブラウザでhttp://localhost:3000 を見てみましょう。
以下のようになれば成功です!!
終わりに
今回はここまでとなります。次回はアプリケーションの更新を行います。
Dockerを学ぶ
はじめに
正直何もわかっていないので、Dockerを学ぼうと思います。 とりあえず何はともあれ公式ドキュメントを見てみるのが1番だろう、ということで公式ドキュメントのget-startedを参考にしています。
なお、実際に使用してみることを第一目標にしているので、Dockerが解決する問題や、Dockerを使用することのメリットは本稿では扱いません。
(とはいえこの辺りを見れば大体書いています。)
Dockerのダウンロード
こちらを参考に。
初めてのdocker run
以下のコマンドを実行します。
$ docker run -d -p 80:80 docker/getting-started
一応、フラグについて解説します。
フラグ | 解説 |
---|---|
-d | バックグラウンドでの実行 |
-p 80:80 | ポート80をコンテナーの80ポートにマッピング |
docker/getting-started | 使用するイメージの指定 |
Docker Dashboard
Docker Dashboardを使用すると、先ほどdocker run
したコンテナーが起動しているのが分かります。(下記参照)
コンテナとは?
ローカルマシンの持つ他のプロセスから独立しているプロセスです。
コンテナイメージとは?
先ほどdocker run -d -p 80:80 docker/getting-started
で指定したdocker/getting-started
がそれにあたります。
コンテナは、独立したファイルシステムを持ちます。そのファイルシステム自体はdocker image
から提供されるものであり、docker image
はコンテナのファイルシステムおよびアプリケーション(コンテナ)の実行に必要な依存性・スクリプト・バイナリなどの含んでいます。
詰まるところ、コンテナを起動するために必要なもの全てが揃っている、という解釈をしています。
terraformでGCPにインフラ環境を構築する
これをやりました。
Cloud run へデプロイする
Google Cloud Platformの1サービスであるCloud Runを使用してJavaアプリケーションをデプロイします。
手順についてはこちらを参考にしていますので、興味のある方は参照してください。
0. 事前準備
1. プロジェクトの作成
GCPのコンソールに移動してプロジェクトを作成します。
プロジェクト名は任意ですが、とりあえず「example java project deploy」とでもしておきましょう。
2. サンプルアプリケーションの作成
実際にデプロイするサンプルアプリケーションを作成します。
こちらも手順通りに、適当なディレクトリにSpringアプリケーションを構築しましょう。
curl https://start.spring.io/starter.zip \ -d dependencies=web \ -d javaVersion=1.8 \ -d bootVersion=2.3.3.RELEASE \ -d name=helloworld \ -d artifactId=helloworld \ -d baseDir=helloworld \ -o helloworld.zip unzip helloworld.zip cd helloworld
次に、作成されたアプリケーションがリクエストを処理することができるようにします。HellloworldApplication.java
を修正します。
3. アプリのコンテナ化
Dockerfile
と.dockerignore
ファイルを作成します。
ファイルの内容についてはこちらをご確認ください。
4. Container Registryへのアップロード
Container RegistryはGCPのサービスの1つで、コンテナを登録することができます。
のちに実施するCloud RunへのデプロイはContainer Registryに登録されているコンテナをデプロイする、ということになります。
それでは、以下のコマンドを実行します。この時、Dockerfile
が存在しているディレクトリでコマンド実行することに注意してください。
gcloud builds submit --tag gcr.io/{PROJECT-ID}/helloworld
{PROJECT_ID}には手順で作成したプロジェクトのIDを入れてください。 完全なコマンドは以下のようになります。
gcloud builds submit --tag gcr.io/example-java-project-deploy/helloworld
さて、ここまでできるとコンソール上から実際にContainer Registryへコンテナが登録されているはずですので確認してみます。
できました!!
5. Cloud Runへのデプロイ
さて、ここまでできればあとはデプロイするだけですね。
以下のコマンドを実行します。
gcloud run deploy --image gcr.io/example-java-project-deploy/helloworld --platform managed
コマンドを実行すると、実行中に
- サービス名
- リージョン
- 未認証の呼び出し許可
について入力を求められますので適宜入力してください。
実行が完了するとアクセスするためのURLがターミナルに表示されますので、ブラウザで開くと画面にHelloWorld!
が表示されます。
6. 補足
デプロイしたアプリケーションにアクセスがある場合など、課金が発生しますので、不要であればプロジェクトごと削除してしまってください。
終わりに
手順通りに実施すればなんてことはなく簡単にできました。
コンテナ技術もクラウドサービス技術も知識がほぼないのでこれから学習していければと思います。
とりあえずDockerあたり勉強するかなー。
react-collapsibleを使ってアコーディオンを作成する
アコーディオン、Webでよく見かけますよね。
今回はreact-collapsible
を使用してFAQのようなアコーディオンを作成してみようと思います。
完成形
最初に完成形だけ置いときます。
とりあえずソースを見せろという方はこちらをご覧ください。
準備
まずは必要なパッケージのインストール
yarn add react-collapsible
簡単な例
1番単純な例を作成します。
import Collapsible from "react-collapsible"; export function AccordionSample() { return <Collapsible trigger={"click me!!"}> This is easiest Accordion!! </Collapsible> }
上記のようなコンポーネントを作成することで、click me!!!
の文字をクリックするとその下部にhello, collapsible!
が出力されるのがわかると思います。
Collapsibleのオプション
Collapsible
はアコーディオンの開閉を制御するtrigger
オプションが必須になりますが、それ以外にもいくつかのオプションがあります。
すでに使用したtrigger
オプションも含めていくつか紹介しようと思います。
アコーディオンの開閉動作に関わるオプション
trigger
アコーディオンの開閉のトリガー(契機)となる文字列またはReactNode
を指定します。前述した例では文字列を指定しましたが、ReactNode
を渡せるので、任意のコンポーネントも使用できます。
<Collapsible trigger={<AnyComponent/>}> </Collapsible>
transitionTime
アコーディオンの開閉にかかる時間を指定します。単位はミリ秒です。
transitionTime={1000}
transitionCloseTime
アコーディオンが閉じる時の時間を指定します。transitionTimeと同様に単位はミリ秒です。
transitionCloseTime={1000}
アコーディオンのスタイルに関わるオプション
className
アコーディオンが閉じている時に適用されるCSSスタイルを指定します。なお、
openedClassName
アコーディオンが開いている時に適用されるCSSスタイルを指定します。
感想
かなり簡単にアコーディオンが実現できるので、今回作成したようなアコーディオンを作るには便利に感じました。