endokのブログ

IT・プログラミングネタ

DockerForWindowsで開発用SQLServerを利用する

はじめに

.NETアプリケーションを作るのにSQLServerを利用しようと思ったが、
クライアント環境を汚さないように、勉強も兼ねてDockerで稼働させることにした。
今回はSQLServer Developer 2017を稼働させる。
Docker体験も兼ねてるので、Docker知ってる人なら当たり前・・という内容も含まれているので注意。

なお、このページの内容は下記ページに基づいています。
https://hub.docker.com/r/microsoft/mssql-server-windows-express/

環境

  • Windows10 Professional
  • SQL Server Management Studio 17.3(クライアント環境を汚さないようにと思うが、やはりSSMSは欲しい)
  • Docker CommunityEdition 17.09.1-ce-win42 (14687)

DockerForWindowsの導入

本題ではないが簡単に記載。Windows10の場合、Professional以上のエディションが必要。

  1. Windowsの機能の有効化より、「Hyper-V」、「コンテナー」をインストール
  2. Docker for windowsをインストールする。(https://docs.docker.com/docker-for-windows/install/)
  3. DockerをWindowsContainerモードにしておく(タスクトレイを右クリックしてSwitch to Windows containers...)
  4. PowerShellタブ補完のインストール(任意)
    • PowerShellで>Install-Module posh-dockerする
    • "Import-Module posh-docker"をprofile.ps1に追加する。

imageの取得

サイズも大きいので、一旦imageを取得しておく。サイズは11.6GBとなかなか大きい。
expressの場合はmicrosoft/mssql-server-windows-expressをpullする。

docker pull microsoft/mssql-server-windows-developer

コンテナの起動

環境変数として下記を指定する。

ACCEPT_EULA・・・利用許諾契約に同意するかどうか。Yで指定。
sa_password・・・管理ユーザー(saユーザー)のパスワードを指定。複雑性の要件あり。
attach_dbs (任意)・・・dbName(DB名)、dbFiles(mdf,ldfファイル)を指定。

docker run -d -p 1433:1433 -e sa_password=P@ssw0rd -e ACCEPT_EULA=Y microsoft/mssql-server-windows-developer

オプションの意味は下記。
d・・・デタッチドモード。ルートプロセスが終了したらコンテナも終了する。
p・・・[ホスト側ポート]:[コンテナ側ポート]でポートフォワードする。
e・・・[変数名]=[値]で環境変数を指定。
SQLServerインスタンスは通常1433ポートを利用する。

この段階で、localhost:1433にsaユーザーで接続可能となる。

コンテナの停止・終了

コンテナの停止は、docker stop。(32fad42ed443は"docker ps -a"で確認可能なコンテナID)
数分かかかる。

docker stop 32fad42ed443

コンテナの再開は、

 docker start 32fad42ed443

停止、再開であればデータは保持される。

コンテナの削除は停止後に、

docker rm 32fad42ed443

コンテナ内のデータが消えるため、データを永続化したい場合は注意。

データの永続化

システムDBなどは、コンテナ側の下記フォルダに保存される。
C:\Program Files\Microsoft SQL Server\MSSQL14.MSSQLSERVER\MSSQL\DATA

新しいDBを作成する場合もコンテナ内のフォルダパスを指定する。
f:id:endok:20171229144029p:plain

ただしこのままでは、上記の通りコンテナ削除時にデータが消えてしまう。
永続化するには、ホスト側のフォルダをvオプションでコンテナにマウントする。
下記のようにすると、ホスト側のc:/Users/hoge/work/docker-mssql/dataをコンテナ側のC:/DATAにマウントする。C:\Data以下にmdf,ldfファイルを作成することでコンテナを削除してもデータが消えなくなる。
Windowsのボリューム指定方法はぐぐると色々書き方があったが、私の環境では下記の書き方で通った。)

docker run -d -p 1433:1433 -e sa_password=P@ssw0rd -e ACCEPT_EULA=Y  -v "c:/Users/hoge/work/docker-mssql/data:C:/DATA" microsoft/mssql-server-windows-developer

作成したmdf,ldfファイルを読み込んだ状態でコンテナを起動するには、下記のようにattach_dbs環境変数を指定する。

docker run -d -p 1433:1433 -e sa_password=P@ssw0rd -e ACCEPT_EULA=Y -e attach_dbs="[{'dbname':'testDB','dbFiles':['C:\\DATA\\testdb.mdf','C:\\DATA\\testdb_log.ldf']}]"  -v "c:/Users/hoge/work/docker-mssql/data:C:/DATA" microsoft/mssql-server-windows-developer

デフォルトのC:\Program Files\Microsoft SQL Server\MSSQL14.MSSQLSERVER\MSSQL\DATAにマウントできたらいいなぁと思ったが、思ったようにマウントできず断念。半角スペースの前を\でエスケープしたらコンテナ起動はできたが、何か違う場所をマウントしてしまっているのか、DB作成してもファイルができなかった。
もともとシステムDBのファイルなどあるので、だめなのかも??よくわからず。

その他

パスワード複雑性要件

saパスワードを簡単なもので起動してみる。
→コンテナ起動はするが、SSMSからログインできず(認証NGぽいエラー)。おそらく8文字以上、英数大小記号から3種などが必要。

docker run -d -p 1433:1433 -e sa_password=pass -e ACCEPT_EULA=Y microsoft/mssql-server-windows-developer

ACCEPT_EULAをY以外にする

ACCEPT_EULAをY以外にしてみる。
→コンテナ起動はするが、SSMSから接続できず。SQLServerのサービスが起動していないような雰囲気。

docker run -d -p 1433:1433 -e sa_password=P@ssw0rd -e ACCEPT_EULA=N microsoft/mssql-server-windows-developer

まとめ

Windows環境でのパス指定の方法がわからず少し試行錯誤した。Docker操作に慣れるとコンテナの作成、削除がサクサクできて、コンテナ起動も想像より早く、環境を作ったり壊したりがここまで簡単にできるのはかなり新鮮だった。
若干気になるのが、パフォーマンスはどのくらいDocker越し(Hyper-V越し?)で変わるんだろうか。IISもDocker起動したら結構重いのかな。あとはイメージサイズで、自宅PCならまだしも社用PCは潤沢とは言えないディスク容量なので、実用できそうなのはちょっと先かなー。

PowerShellでフォルダ比較を行う

PowerShellの中でフォルダの中身を再帰的に比較したいことがあったため、調べた結果をメモ。

diffコマンドがあればこんな苦労はないのだが、PowerShellWindows標準のコマンドだとかゆいところに手が届かない感じ。
GUIならWinMergeがあるが、今回はPowerShellスクリプトから利用したい。

ググると、下記情報が出てくる。
stackoverflow.com

コードとしては下記の通り。

$d1 = get-childitem -path $dir1 -recurse
$d2 = get-childitem -path $dir2 -recurse
compare-object $d1 $d2

Get-ChildItemで比較する2フォルダを取得して、そのままCompare-Objectに渡している。
このやり方を試してみると特徴は、

  • ファイルの有無を比較できる
  • ファイルの内容の比較はできない
  • 同一ファイル名が別階層に存在していると差分なし扱いになってしまう

といったところ。
同一ファイル名の別階層を差分なし扱いにするため、今回は下記のように改変して使ってみた。

$d1 = (Get-Childitem -Path $dir1 -Recurse | % { $_.FullName.Replace(("$dir1" + "\"), "") })
$d2 = (Get-Childitem -Path $dir2 -Recurse | % { $_.FullName.Replace(("$dir2" + "\"), "") })

compare-object $d1 $d2

ファイルリストの比較はこれで問題なさそう。
本当はファイル内容の比較も行いたかったがそちらは簡単な書き方が結局見つけられず、普通にループしながらCompare-Objectをひたすら実行することに・・・。

Spring Boot触ってみる その5 ープロファイルを利用した環境ごと設定の切り替えー

Spring Boot触ってみる その4 ーSQLServerへの接続ー - endokのブログ
の続き。

DB接続設定など、実行する環境に応じて切り替えたいパラメータがある。
Springでは"Profile"という仕組みで切り替えることができる。

その1(http://endok.hatenablog.com/entry/2016/06/04/124011)で作成したサンプルプロジェクトを引き続き利用する。

続きを読む

Spring Boot触ってみる その4 ーSQLServerへの接続ー

Spring Boot触ってみる その3 ーThymeleaf Layout Dialectでレイアウトを共通化ー - endokのブログ
の続き。

SpringBootでのSQLServerへの接続方法を確認する。
SpringBoot特有の設定ということはなく、Springであれば同じような設定となるだろう。

その1(http://endok.hatenablog.com/entry/2016/06/04/124011)で作成したサンプルプロジェクトを引き続き利用する。

続きを読む

Springで定義済のBean名一覧を出力する

SpringBootはSpringのBean設定を隠蔽してくれているのだが、SpringBoot側で定義しているBeanをInjectionしたいときにはどういったBeanが定義済なのかわからず困る。
定義済のBean名をすべて出力する方法を調べたのでメモ。

方法は下記の通り。

1. BeanFactoryAwareをimplementsして、BeanFactoryを取得する。
2. BeanFactoryをDefaultListableBeanFactoryにキャストして、getBeanDefinitionNamesメソッドを利用する。

Controllerで実装した場合の例はこのようになる。

@Controller
public class HelloController implements BeanFactoryAware {

	private DefaultListableBeanFactory beanFactory;
	
	@Override
	public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
		this.beanFactory = (DefaultListableBeanFactory)beanFactory;
		
	}

	@RequestMapping(value = "/page1")
	public String page1() {
		
		for (String name : beanFactory.getBeanDefinitionNames()) {
			System.out.println(name);
		}
		
		return "page1";
	}
	
}

Spring Boot触ってみる その3 ーThymeleaf Layout Dialectでレイアウトを共通化ー

Spring Boot触ってみる その2 ーController,テンプレートエンジン(Thymeleaf)ー - endokのブログ
の続き。

Thymeleafにもincludeなどを使った共通化の仕組みはあるが、
各ページごとにincludeは書きたくない・・・。
Tilesのように共通レイアウトを定義する仕組みはないものかと調べたところ、
Thymeleaf Layout Dialect(https://github.com/ultraq/thymeleaf-layout-dialect)というものがあったため試してみる。

その1(http://endok.hatenablog.com/entry/2016/06/04/124011)で作成したサンプルプロジェクトを引き続き利用する。

続きを読む

SpringBootの開発に自動リロード(ホットデプロイ)を導入する

目次

  • 目次
  • はじめに
  • SpringLoaded
    • 特徴
    • 導入方法
  • Spring Boot Dev Tools
    • 特徴
    • 導入方法
  • まとめ

はじめに

SpringBootの開発の流れは、

1. コードを書く
2. [Run As]→[Spring Boot App]で起動
3. 動作確認する
4. コードを書く
5. Consoleから起動中のアプリをTerminate
6. [Run As]→[Spring Boot App]で起動
7. 3に戻る

としていたが、

いちいち修正を反映するのに停止して起動するのは煩わしい。
1つ処理を書くたびに動作確認したいタイプなので、開発効率が悪くなってしまう。

S2Containerにはホットデプロイあって楽だったなぁ・・・と思ったので同様の仕組みを調べてみた。

Springという名前が付いているし、JRebelは商用(myJRebelというフリー版もあるようだが)なので、SpringLoadedとSpringBootDevToolsを試してみる。

続きを読む