endokのブログ

IT・プログラミングネタ

ディープラーニングG検定(JDLA Deep Learning for GENERAL 2018 #1)を受験した

JDLAのディープラーニングG検定を2018/06/16に受験したので、勉強方法や出題傾向、感想などを書いてみる。
公式サイトはこちら。
協会活動 | 一般社団法人 日本ディープラーニング協会 Japan Deep Learning Association

きっかけ、事前知識

インフラ勉強会(https://wiki.infra-workshop.tech/)のディープラーニング回にて、発表者の方がこの検定取得を目指していることを知る。
申し込み受付中かつ試験まで丸々3週間というところだったので、これは間に合うのでは?ということで申し込み。

大学時代に機械学習/統計解析の研究室にいたので、ある程度の下地はあり。
研究にはニューラルネットワーク&強化学習を利用していたので、その辺りはそこそこわかるつもり。
ただその頃はディープラーニングが流行る直前くらい(2006年~2010年あたりかな)の時期だったので、最近の手法は知らない状態。

どんな試験か

推薦図書は下記の3冊。

小問が228問と聞くとかなり多く感じるが、文章の穴埋め1つで1問という数え方なので、実際に解くとそこまで時間はツラくない。

勉強方法

試験まで3週間とそこそこ期間があったので、推薦図書は一通りなめる形で勉強を進めた。

  1. 推薦図書を一通り読む。順番は「人工知能は人間を超えるか」→「AI白書」→「深層学習」
  2. シラバスに沿って各推薦図書から要点を抜き出した資料作成(Word)
  3. ネット上の受験記を探して情報収集+公式の例題をもとに資料を肉付け
  4. 作成した資料を覚える

推薦図書ごとのおすすめの読み方、出題傾向は下記の通り。

人工知能は人間を超えるか
内容的にディープラーニング学習の導入にぴったり、ボリュームも手頃で読みやすいため、最初に読むことをおすすめ。
シラバスとの対応としては、「人工知能(AI)とは(人工知能の定義)」「人工知能をめぐる動向」「人工知能分野の問題」あたりに相当する。
範囲的にはAI白書と被る部分もあるが、用語の説明はこちらの方がわかりやすい。
将来的な話も後半多いが、その辺りは置いておいて人工知能の歴史とキーワード、ディープラーニングの概要、何がすごいのか、をこの本でおさえるとよい。
直接的に問題として聞かれる内容はそんなに多くはないという印象であった。

・AI白書
白書という名前だけあって網羅的な内容になっており、すべてを覚えるというのは難しい。
最初から最後まで一応目を通したが、途中から文字列を脳に流し込むだけの状態になっていたので、通し読みする価値があるかは疑問。
試験対策としてはシラバスと対応する箇所を探し、用語や重要そうな事例に絞って覚えるという使い方がよいだろう。
シラバスとの対応としては、ディープラーニングの具体的な手法を除いたほぼ全範囲に関連している。
ディープラーニングの研究や応用、法律、倫理や現行の議論といった話はこの本にしか無いので、そこは重点的に読み込むとよい。
扱う範囲が広いこともあり、ここからの出題比率は高い印象であった。(問題文にこの本を出典としている旨が書いてあるものもあった)

・深層学習
ディープラーニングの具体的な手法や計算方法、テクニックについての本。
数式が結構出てくるが、試験にはほぼ出てこないので、文章や図から読み取れる考え方だけ理解しておけばよい。
シラバスとの対応としては、「ディープラーニングの概要」「ディープラーニングの手法」あたりに相当する。
計算問題(順伝播の計算と偏微分とCNNのパディング、ストライド後画像サイズ)やディープラーニングにおけるテクニックについてはこの本から出ているという印象であった。

試験を終えて

問題量が多いとの評判だったため、わからない問題は悩まずにチェックして次に進むという方法で解いたところ、70分程度で1週目の回答が終わった。その後チェックを付けた問題の2週目を解いて回って時間いっぱいという感じであった。
参考図書には無かったと思われる問題もそこそこあり、機械学習や統計解析の手法のあたりで特に多く感じた。(参考図書はあくまで"参考"ということなんでしょう・・)
全然わからんなーとなった問題で覚えているのは下記の通り。

  • アーサー・サミュエルによる人工知能の定義(参考図書にあったかも?)
  • SVMとスラック変数、カーネル法カーネルトリック
  • ロジスティック回帰
  • 交差検証の方法
  • 汎化誤差のバリアンス、バイアス、ノイズ
  • カプセルネットワーク
  • 後半の法律、倫理、現行の議論の問題全般

機械学習/統計解析手法のところは、1つの話題で数問聞かれるので、全然知らない話題だと結構ショックを受ける。
法律、倫理、現行の議論のところは、「上記はいずれもあてはまらない」のような選択肢が大体最後に付いていて、正確に覚えていないと回答は困難であった。しかしこのあたりの話題を自信持って答えられるほど勉強はしていないので、適当に回答。

自宅での受験という受験形式は初だったが、選択問題ということもあり環境的には特に問題なし。
前回と問題がどのくらい変わっているかわからないが、この受験方式だと過去問出回った途端に合格率が跳ね上がりそうなものだが、大丈夫なんだろうかと心配になる。
受験後の感触は、大問の中の小問が全部合ってて正解方式だと厳しいかもしれないが、小問単独で得点がもらえるなら十分合格していそうというところ。
結果は1週間とわりとすぐに出るようなので、期待して待ちましょう。

まとめ

急に受けることにした試験だったが、ここ数年のAI技術の概要は掴めたと思うし、ジェネラリストという名前の通り、これに受かる知識があればビジネスでAIの話をするレベルになれる良試験だと感じた。
受験料が高いという話もあるが、G検定ならまだ個人でも手が出る程度だし、E検定もベンダー系の資格と思えばそんなに高くはない・・・かも(私は受けない)。
ディープラーニング検定といいつつ実態は人工知能検定なので、名前を変えたほうが受験者増えるんじゃないのという気はする。
開始して間もない試験で、持ってると少なくとも話のネタにはなると思うので、人工知能気になるけどなかなかきっかけが無いという方におすすめの試験です。

Windows10でnslookupするとQuery refusedになる

簡単なトラブルシュートメモ。
環境はWindows10 Pro。

DNSの勉強でもしようとwww.yahoo.co.jpにnslookupしようとしたところ、下記のように名前解決に失敗した。

PS C:\Users\endok> nslookup www.yahoo.co.jp
サーバー:  UnKnown
Address:  2404:1a8:7f01:b::3

*** UnKnown が www.yahoo.co.jp を見つけられません: Query refused

インターネットには繋がっており、ブラウザからであれば表示できるため、nslookup時にうまくいかないだけの様子。
また、digは成功する。

PS C:\Users\endok> dig www.yahoo.co.jp

; <<>> DiG 9.11.2 <<>> www.yahoo.co.jp
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 17486
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;www.yahoo.co.jp.               IN      A

;; ANSWER SECTION:
www.yahoo.co.jp.        311     IN      CNAME   edge.g.yimg.jp.
edge.g.yimg.jp.         14      IN      A       182.22.24.124

;; Query time: 7 msec
;; SERVER: 192.168.11.1#53(192.168.11.1)
;; WHEN: Sat Jan 20 23:57:10 ???? (?W???) 2018
;; MSG SIZE  rcvd: 86

ググってみると、下記の質問に状況が近い。
answers.microsoft.com

ということで、現在特にIPv6は必要ないため、IPv6を無効にしたところ無事解決。
具体的には、
コントロール パネル > ネットワークとインターネット > ネットワークと共有センター
を開き、対象の接続を選択してプロパティを開く。
そしてインターネットプロトコルバージョン6(TCP/IPv6)のチェックを外してOKすればよい。
f:id:endok:20180121000743p:plain

PS C:\Users\endok> nslookup www.yahoo.co.jp
サーバー:  ap-endo
Address:  192.168.11.1

権限のない回答:
名前:    edge.g.yimg.jp
Address:  182.22.25.124
Aliases:  www.yahoo.co.jp

しかし今はIPv6関連で何かあったらとりあえず無効にして回避してるけど、本格的に使わないといけなくなってきたらちゃんと対応しなきゃいけないんだろうなぁ・・・。

ITカンファレンス個人的まとめ2018

2018年は時間を作って参加や視聴したいと思うので、開催時期などまとめてみる。
(2018/01/03時点情報)
企業やユーザーグループが主催している大きめのもので、自分が行こうかなと思っているもの中心。
偏りあると思うので、追加等あればコメントください。
また、日本の技術系カンファレンスまとめ - Qiitaの記事も参考にさせていただきました。

国内

企業主催

AWS Summit Tokyo

http://www.awssummit.tokyo/
AWSの開発者向けイベント。
2018年の日程は未発表。去年は5月末に開催。

Microsoft de:code

https://www.microsoft.com/ja-jp/events/decode/2018
Microsoftの開発者向けイベント。
2018年は5/22-5/23開催。

Microsoft Tech Summit

https://www.microsoft.com/ja-jp/events/techsummit/
Microsoftの企業や組織のIT技術者向けイベント。
2018年の日程は未発表。去年は11月に開催。

楽天テクノロジーカンファレンス

https://tech.rakuten.co.jp/
楽天の技術イベント。
2018年の日程は未発表。去年は10月末に開催。

Cookpad TechConf

https://techconf.cookpad.com
Cookpadの技術イベント。
2018年は2/10開催。

NTT Tech Conference

https://ntt-developers.github.io/ntt-tech-conference/
NTTグループの技術イベント。
2018年の日程は未発表(不定期?)。去年は1月と8月に開催。

全般

オープンソースカンファレンス

https://www.ospn.jp/
オープンソースがテーマのイベント。
日本各地で開催されている。
2018年の東京は2/23-2/24で開催。

Developers Summit

http://event.shoeisha.jp/devsumi
「技術者コミュニティとの連携から生まれた総合ITコンファレンス」とのこと。
同僚で行く人が多い。
2018年は2/15-2/16で開催。

CEDEC

http://cedec.cesa.or.jp/
コンピュータエンターテインメント関連の技術者向けイベント。
個人的にゲーム好きなので行ってみたい。けど個人で行くにはちょっと高いかな。
2018年は8/22-8/24で開催。

iOS

iOSDC Japan

https://iosdc.jp/
iOS開発者向けイベント。
2018年の日程は未発表。去年は9月に開催。

try!Swift

https://www.tryswift.co/events/2018/tokyo/en/
Swift開発者向けイベント。
2018年は3/1-3/2開催。

Android

Android ABC

http://abc.android-group.jp/
Android Bazaar and Conference。
2018年は2/3開催。秋/冬にも開催する年がある。

Droid Kaigi

https://droidkaigi.jp/
Androidカンファレンス。
2018年は2/8-2/9開催。

フロントエンド

FRONTEND CONFERENCE

http://kfug.jp/
関西のフロントエンド技術者向けイベント。
2018年の日程は未発表。去年は3月開催。

HTML5 Conference

http://events.html5j.org
Web技術者向けイベント。
2018年の日程は未発表。去年は9月開催。

Java

JJUG CCC

http://www.java-users.jp
Java技術者向けイベント。
SpringとFallの年2回開催。
2018年の日程は未発表。去年は5月と11月開催。

Scala

ScalaMatsuri

http://2018.scalamatsuri.org/
Scala技術者向けイベント。
2018年は3/16-3/18開催。

Ruby

RubyKaigi

http://rubykaigi.org/
Ruby技術者向けイベント。
2018年は5/31-6/2開催。

海外

企業主催

F8 Facebook Developer Conference

https://www.f8.com/
Facebookの開発者向けイベント。
2018年は5/1-5/2開催。

Microsoft Build

https://build.microsoft.com/
Microsoftの開発者向けイベント。
2018年の日程は未発表。去年は5月に開催。

Google I/O

https://events.google.com/io/
Googleの開発者向けイベント。
2018年は5/16という情報ありだが未確定?

Apple WWDC

https://developer.apple.com/wwdc/
Appleの開発者向けイベント。
2018年の日程は未発表。去年は6月に開催。

AWS re:Invent

https://reinvent.awsevents.com/
AmazonAWS開発者向けイベント。
2018年は11/26-11/30開催。

.NETの各種DBアクセス方法を試す(DataSet,EntityFramework,Dapperなど)

はじめに

.NET使って何か作ろうと思ったのだが、仕事では独自Frameworkばかり使っていて標準的な方法を触ったことがないので、有名所のDBアクセス方法を試してみたいと思う。

サンプルコードの全体は下記。
GitHub - endok/sample-dotnetdb: .NETのDBアクセスサンプルコード。

対象

試す対象は、

環境

データ準備

下記状態を前提とする。

下記テーブル、データを作成しておく。

CREATE TABLE member
(
	id int PRIMARY KEY,
	name nvarchar(20) NOT NULL,
	age int NOT NULL
)

INSERT INTO member (id, name, age) VALUES (1, 'Alice', 20)
INSERT INTO member (id, name, age) VALUES (2, 'Bob', 25)
INSERT INTO member (id, name, age) VALUES (3, 'Carol', 30)

このような状態になる。
f:id:endok:20171230161433p:plain

ADO.NET SqlClient

たぶん一番シンプルにADO.NETを使うパターン。
System.Data.SqlClientあたりをusingするだけで使える。
SQLServerに接続するためのクライアントで、ODBCだったりOracleの場合は別のクラスを利用する。

今回は、DataReaderでの参照、UPDATE文の発行を試した。
DataReaderは、前方参照専用、読み取り専用だがパフォーマンスに優れるとのこと。

サンプルコード

        private static void SqlCommandSample(string connectionString)
        {
            using (SqlConnection connection = new SqlConnection())
            {
                connection.ConnectionString = connectionString;
                connection.Open();

                // SqlCommandによる参照
                string selectquery = "SELECT id, name, age FROM member WHERE age >= @age ";

                SqlCommand selectcommand = new SqlCommand(selectquery, connection);
                selectcommand.Parameters.AddWithValue("@age", 25);

                SqlDataReader reader = selectcommand.ExecuteReader();
                while (reader.Read())
                {
                    Console.WriteLine("id={0},name={1},age={2}", reader[0], reader[1], reader[2]);
                }
                reader.Close();

                // SqlCommandによる更新
                string updatequery = "UPDATE member SET age = 40 WHERE id = @id";

                SqlCommand updatecommand = new SqlCommand(updatequery, connection);
                updatecommand.Parameters.AddWithValue("@id", 3);

                updatecommand.ExecuteNonQuery();
            }
        }

ADO.NET DataSet

こちらもADO.NET標準の仕組み。
データソースに依存せず、メモリ上でリレーショナルデータを扱うための仕組み。DBなど既存のデータソースとのやり取りにはDataAdapterを介する。
テーブルなど一つのデータのまとまり単位でDataAdapterを定義して、CRUD操作するSQLを設定。その後はDataSetを操作した結果をDBに同期するという使い方となる模様。

今回はDataSetでの参照、データ更新を試した。

データソースに依存しないで操作できること、細かいことを考えずにデータ取得、同期できるという良さがある。しかしDataAdapterの定義がやや面倒そうという印象。

サンプルコード

        private static void DataSetSample(string connectionString)
        {
            using (SqlConnection connection = new SqlConnection())
            {
                connection.ConnectionString = connectionString;
                connection.Open();

                // DataSetによる参照、更新
                string selectQuery = "SELECT id, name, age FROM member";
                string updateQuery = "UPDATE member SET age = @age WHERE id = @id";

                SqlDataAdapter adapter = new SqlDataAdapter();

                // 主キー情報をDBから取得
                adapter.MissingSchemaAction = MissingSchemaAction.AddWithKey;

                // クエリの設定
                adapter.SelectCommand = new SqlCommand(selectQuery, connection);
                adapter.UpdateCommand = new SqlCommand(updateQuery, connection);

                // Updateパラメータの設定
                SqlParameter ageParam = new SqlParameter();
                ageParam.ParameterName = "@age";
                ageParam.SourceColumn = "age";
                adapter.UpdateCommand.Parameters.Add(ageParam);
                SqlParameter idParam = new SqlParameter();
                idParam.ParameterName = "@id";
                idParam.SourceColumn = "id";
                adapter.UpdateCommand.Parameters.Add(idParam);

                DataSet dataset = new DataSet();
                adapter.Fill(dataset, "memberTable");
                DataTable datatable = dataset.Tables["memberTable"];

                // データの参照
                foreach (DataRow row in datatable.Rows)
                {
                    Console.WriteLine("id={0},name={1},age={2}", row["id"], row["name"], row["age"]);
                }

                // データの更新
                DataRow carolRow = datatable.Rows.Find(3);
                carolRow["age"] = 50;

                adapter.Update(dataset, "memberTable");
            }

        }

EntityFramework

ADO.NETに含まれるデータアクセスフレームワーク。いわゆるORMで、データソースとオブジェクトをマッピングして取り扱う。
DBマイグレーションの仕組みも備えている。

VisualStudio2012以上でないとEntityFrameworkToolsが利用できない。

導入方法

NuGetでインストールする。
プロジェクトを右クリックして[NuGetパッケージの管理...]の参照で"EntityFramework"を検索してインストールする。
※Dapperも同じプロジェクトに導入する場合、v6.1.3をインストールする。

EntityFrameworkのワークフロー

Entity Framework (EF) Documentation の概要

EntityFramewokでは概念モデルを作成するにあたり、「コードファースト」「モデルファースト」「データベースファースト」という方式がある。

コードファースト・・・ソースコード上にModelクラスをまず作成。その情報を元にDBスキーマを作成するという方式。スキーマの変更は、マイグレーション機能で管理する。
モデルファースト・・・EFデザイナを利用してVisualStudio上でモデルを追加。その情報をDBスキーマに反映するという方式。
データベースファースト・・・DBスキーマSQLでまず作成。その情報をVisualStudioのモデル(ソースコード、EFデザイナ)に反映するという方式。

今回はDBスキーマ作成済のため、データベースファースト方式を試す。

モデルのリバースエンジニアリング

プロジェクトを右クリックして[追加]→[新しい項目]でデータカテゴリの"ADO.NET Entity Data Model"を追加する。
f:id:endok:20180101120234p:plain

"データベースからEF Desginger"を選ぶ。
f:id:endok:20180101021221p:plain

データ接続を選択し、App.Configに保存する。
f:id:endok:20180101120342p:plain

接続の設定は適当なものを選ぶまたは新規作成する。
対象のデータベースオブジェクト(今回はmemberテーブル)を選択する。
f:id:endok:20180101120452p:plain

下記のようにDBの情報をもとに抽出されたモデル情報がデザイナに表示される。
f:id:endok:20180101115134p:plain

クエリの方式

いくつか方法があるが、基本的にはLINQtoEntitiesでアクセスするのが主流の模様。複雑なクエリを発行する際には、EntitySQLというSQLに似た言語を利用することもできる(HybernateのHQLのようなものと思われる)。また、SQLを直接発行することもできる。
今回はLINQtoEntitiesでの参照、EntitySQLでの参照、EntityFrameworkでの更新を試した。

サンプルコード

        private static void EntityFrameworkSample()
        {
            // Entity SQLでの参照
            Console.WriteLine("-- Entity SQL");
            using (EntityConnection connection = new EntityConnection("name=SampleContext"))
            {
                connection.Open();

                string query1 = "SELECT m.id, m.name, m.age FROM SampleContext.member AS m WHERE m.age >= @age";

                using (EntityCommand cmd = new EntityCommand(query1, connection))
                {
                    cmd.Parameters.AddWithValue("age", 25);

                    using (DbDataReader rdr = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
                    {
                        while (rdr.Read())
                        {
                            Console.WriteLine("id={0},name={1},age={2}", rdr["id"], rdr["name"], rdr["age"]);
                        }
                    }
                }

            }

            using (var db = new SampleContext())
            {
                // LINQ to Entitiesでの参照
                Console.WriteLine("-- LINQ to Entities");
                var query1 = from m in db.member
                             where m.age >= 25
                             select m;

                foreach (var member in query1)
                {
                    Console.WriteLine("id={0},name={1},age={2}", member.id, member.name, member.age);
                }

                // 別の書き方での参照
                Console.WriteLine("-- LINQ to Entities 2");
                var query2 = db.member.Where(m => m.age >= 25);

                foreach (var member in query2)
                {
                    Console.WriteLine("id={0},name={1},age={2}", member.id, member.name, member.age);
                }

                // Entity Framewokでの更新
                var carol = db.member.Find(3);
                carol.age = 60;
                db.SaveChanges();
            }
        }

Dapper

シンプルなORM(Micro-ORM)で、StackOverflowの中の人が作ったらしい。
Commandの作成やオブジェクトへのマッピングなど、定型的で面倒な部分を補ってくれる。重厚なORMはいらないけど生ADO.NETもちょっと・・・というケースに。

導入方法

NuGetで"Dapper"をインストールする。
EntityFramework6.2が入っている状態ではインストールできなかったので、EntityFrameworkは6.1.3にしておく。

サンプルコード

マッピング先のクラスはEntityFrameworkが作成した下記クラスを流用。

    public partial class member
    {
        public int id { get; set; }
        public string name { get; set; }
        public int age { get; set; }
    }

実際の処理は下記。

        private static void DapperSample(string connectionString)
        {
            using (SqlConnection connection = new SqlConnection())
            {
                connection.ConnectionString = connectionString;
                connection.Open();

                // Dapperによる参照
                string selectquery = "SELECT id, name, age FROM member WHERE age >= @age";
                var members = connection.Query<member>(selectquery, new { age = 25 });

                foreach (var member in members)
                {
                    Console.WriteLine("id={0},name={1},age={2}", member.id, member.name, member.age);
                }

                // Dapperによる更新
                string updatequery = "UPDATE member SET age = 30 WHERE id = @id";
                connection.Execute(updatequery, new { id = 3 });
            }
        }

その他

気になって調べた事柄をメモ。

LINQ to EntitiesとLINQ to SQLの違い

下記がわかりやすかった。
c# - What is the difference between "LINQ to Entities", "LINQ to SQL" and "LINQ to Dataset" - Stack Overflow

引用すると、下記の通り。

・すべてLINQ(Language Integrated Query)であるため、共通点は多い。これらの"方言"は、異なるデータ元に対するクエリの書き方を提供する。
・LINQtoSQLはMicrosoftの最初のORMへの試みだが、SQLServerにしか対応していない。SQLServerのテーブルと.NETオブジェクトのマッピングを行う。
・LINQtoEntitiesは同じMicrosoftによるORMだが、EntityFrameworkを背景に利用し、複数のDBMSに対応している。

まとめ

ADO.NET周りは(たぶん歴史的な経緯のためと思われるが)似たような用語、概念が多く、最新の技術セットが何なのか把握するのが難しく感じた。
今回の理解としてはMS的にはEntityFramework(LINQ to Entities)で、他の選択肢としてOSSを考えるという形なのだけど合っているのだろうか・・。
Dapperも簡単に使えて良さそうだが、MS系ではなんとなくMS流儀に乗っかりたくなるので、まずはEntityFrameworkを使ってみようかな。

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)で作成したサンプルプロジェクトを引き続き利用する。

続きを読む