1. manymanyuni

    Posted

    manymanyuni
Changes in title
+Microsoft SQL Server on Linux 2017 の Docker を作成する
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,335 @@
+# 前置き
+
+SQL Server on Linux 2017 が公開されたので、早速 Docker を作成していきます。
+intra-mart の検証用として利用したいので、Dockerfile の最後で検証用ユーザの作成も行います。
+([権限の付与や、intra-mart が要求する照合順序も設定します](https://www.intra-mart.jp/download/product/iap/setup/iap_setup_guide/texts/install/common/database.html#microsoft-sql-server))
+これによって、MS 公式の Docker イメージと異なり、docker run 後何も考えずにすぐに検証用として利用できるような SQL Server の環境が作れるようになります。
+
+# 注意
+
+SQL Server on Linux は DTC に対応していないので DTC が必要となる分散トランザクションは利用できません。
+[SQL Server Linux: Distributed transactions requiring the Microsoft Distributed Transaction Coordinator service are not supported on SQL Server running on Linux. SQL Server to SQL Server distributed transactions are supported. – CLARIFIED!!!](https://blogs.msdn.microsoft.com/bobsql/2017/12/11/sql-server-linux-distributed-transactions-requiring-the-microsoft-distributed-transaction-coordinator-service-are-not-supported-on-sql-server-running-on-linux-sql-server-to-sql-server-distributed-tr/)
+
+
+# タイムゾーンに関する脱線
+
+Postfix の Docker の記事で述べましたが自分が Docker を作成した段階ではタイムゾーンの設定方法により SQL Server のタイムゾーンに差異がでました。(やり方によっては Asia/Tokyo にならなかった)
+詳しくは[こちら](https://qiita.com/manymanyuni/items/9ccf1c4ea76813c806a3#%E3%82%BF%E3%82%A4%E3%83%A0%E3%82%BE%E3%83%BC%E3%83%B3%E3%81%AB%E9%96%A2%E3%81%99%E3%82%8B%E8%84%B1%E7%B7%9A)を参照してください。
+本記事ではちゃんと Asia/Tokyo になるように Dockerfile を作成します。
+
+# Docker ベースイメージ(CentOS 7.4)
+
+いつものようにベースイメージから作ります。
+本記事執筆時点ではベースは CentOS のバージョン 7.4 です。
+OS のバージョンを固定したければ centos:7.4.1708 などのタグがあるのでそちらを使う手もあります。
+
+```dockerfile:Dockerfile
+FROM centos:centos7
+
+EXPOSE 22
+
+ENV DEBIAN_FRONTEND noninteractive
+
+# yum
+RUN yum -y update && yum clean all
+RUN yum -y install dbus systemd
+
+# locale
+RUN yum reinstall -y glibc-common
+RUN localedef -i ja_JP -f UTF-8 ja_JP.utf8
+RUN touch /etc/sysconfig/i18n
+RUN echo 'LANG="ja_JP.UTF-8"' >> /etc/sysconfig/i18n
+ENV LANG ja_JP.UTF-8
+ENV LC_ALL ja_JP.UTF-8
+ENV LANGUAGE ja_JP:ja
+
+# timezone
+RUN yum install -y tzdata
+RUN echo 'ZONE="Asia/Tokyo"' > /etc/sysconfig/clock
+RUN echo 'UTC=false' >> /etc/sysconfig/clock
+RUN ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
+
+# tools
+RUN yum groupinstall -y 'Development Tools'
+RUN yum install -y --enablerepo centosplus wget curl vim emacs tar unzip mlocate perl ssh openssh-server openssl-devel
+
+# root passwd
+RUN bash -c 'echo "root:password" | chpasswd'
+
+# ssh
+RUN sed -i -e "s/#PasswordAuthentication yes/PasswordAuthentication yes/g" /etc/ssh/sshd_config
+RUN sed -i -e "s/#PermitRootLogin yes/PermitRootLogin yes/g" /etc/ssh/sshd_config
+RUN sed -i -e "s/UsePAM yes/UsePAM no/g" /etc/ssh/sshd_config
+
+RUN updatedb
+
+CMD /sbin/init
+```
+
+locate コマンドが便利なので Dockerfile の最後に必ず入れるようにしてます。
+やってるのはロケールとタイムゾーンと ssh を設定しているだけです。
+
+# Docker SQL Server on Linux 2017
+
+さて次は SQL Server on Linux 2017 の Docker です。
+先ほどの CentOS 7 をベースイメージとして利用します。
+
+Dockerfile 以外にも以下のファイルを用意します。
+
+* create_user.sh
+* create_user.sql
+* Dockerfile
+* drop_user.sh
+* drop_user.sql
+* run_server.sh
+* setup_sqlserver.sh
+
+まずは Dockerfile から。
+
+```dockerfile:Dockerfile
+FROM mycentos:7.4
+
+RUN yum -y update && yum clean all
+RUN yum -y upgrade && yum -y update && yum clean all
+RUN yum -y install --setopt=protected_multilib=false epel-release
+RUN yum -y install sudo multitail ncurses-devel ncurses-static ncurses-term
+
+ADD create_user.sql /create_user.sql
+ADD drop_user.sql /drop_user.sql
+
+ADD create_user.sh /create_user.sh
+ADD drop_user.sh /drop_user.sh
+RUN chmod +x /create_user.sh
+RUN chmod +x /drop_user.sh
+RUN ln -s /create_user.sh /root/create_user.sh
+RUN ln -s /drop_user.sh /root/drop_user.sh
+
+ADD run_server.sh /run_server.sh
+RUN chmod +x /run_server.sh
+
+# SQL Server on 2017 セットアップ
+ADD setup_sqlserver.sh /setup_sqlserver.sh
+RUN chmod +x /setup_sqlserver.sh
+RUN /setup_sqlserver.sh
+RUN rm -f /setup_sqlserver.sh
+
+RUN updatedb
+
+CMD /run_server.sh
+```
+
+SQL Server のセットアップ等、複雑な物はシェルスクリプトに逃がし、Dockerfile からはそれを実行するようにします(Dockerfile がシンプルになる、かつイメージ容量の削減にもつながります)
+ログを tail するのに multitail を利用するため、yum install しています。
+
+続いて、SQL Server のセットアップです。
+セットアップ手順やシェルスクリプト内で設定している変数は[こちら](https://docs.microsoft.com/ja-jp/sql/linux/sql-server-linux-configure-environment-variables)を参考にしました。
+docker build 内では systemctl が使えないので pkill でプロセスを殺したりと苦労してます。
+いい方法ないですかね・・・。
+
+```shell:setup_sqlserver.sh
+#!/bin/sh
+
+curl -o /etc/yum.repos.d/msprod.repo https://packages.microsoft.com/config/rhel/7/prod.repo
+curl -o /etc/yum.repos.d/mssql-server.repo https://packages.microsoft.com/config/rhel/7/mssql-server-2017.repo
+yum update -y && yum clean all
+yum install -y mssql-server
+
+# サイレントインストールするためにいくつか設定
+# ライセンス同意
+export ACCEPT_EULA='Y'
+# sa ユーザのパスワード
+export MSSQL_SA_PASSWORD='password'
+# Developer エディション
+export MSSQL_PID='Developer'
+# 言語は日本語
+export MSSQL_LCID=1041
+# デフォルトの照合順序
+export MSSQL_COLLATION='Japanese_XJIS_100_CS_AS_KS_WS'
+# メモリ上限
+export MSSQL_MEMORY_LIMIT_MB=2048
+# 使用するポート
+export MSSQL_TCP_PORT=1433
+# リッスンアドレス
+export MSSQL_IP_ADDRESS='0.0.0.0'
+# 可用性グループを有効
+export MSSQL_ENABLE_HADR=1
+# SQL Server エージェントを利用
+export MSSQL_AGENT_ENABLED=true
+/opt/mssql/bin/mssql-conf setup
+# カスタマーフィードバックを OFF
+/opt/mssql/bin/mssql-conf set telemetry.customerfeedback false
+
+# systemctl restart mssql-server.service が使えないので pkill と /bin/sqlserver で代用
+pkill sqlservr
+sudo -EH -u mssql /bin/bash -c "/opt/mssql/bin/sqlservr >> /var/opt/mssql/log/sqlservr.log 2>&1 &"
+
+yum remove unixODBC-utf16 unixODBC-utf16-devel
+export ACCEPT_EULA='Y'
+yum install -y mssql-tools unixODBC-devel
+echo 'export PATH="$PATH:/opt/mssql-tools/bin"' >> /root/.bash_profile
+echo 'export PATH="$PATH:/opt/mssql-tools/bin"' >> /root/.bashrc
+source /root/.bashrc
+
+# intra-mart 検証用の DB, ユーザを作成。不要であればコメントアウトするだけで OK です
+/create_user.sh
+# systemctl stop mssql-server.service が使えないので pkill で代用
+pkill sqlservr
+```
+
+続いて docker run 時に実行する SQL Server on Linux 2017 を起動するためのスクリプトです。
+愚直に docker run した場合 systemctl が使えないため、sshd や SQL Server の起動を直接行っています。
+
+```shell:run_server.sh
+# systemctl restart sshd.service
+# systemctl restart mssql-server.service
+ssh-keygen -A
+/usr/sbin/sshd
+sudo -EH -u mssql /bin/bash -c "/opt/mssql/bin/sqlservr >> /var/opt/mssql/log/sqlservr.log 2>&1 &"
+
+touch /var/opt/mssql/log/sqlservr.log
+touch /var/opt/mssql/log/errorlog
+
+multitail -M 0 --follow-all --retry-all /var/opt/mssql/log/sqlservr.log -I /var/opt/mssql/log/errorlog
+# multitail を利用したくない場合、以下で代用可
+# tail -F /var/opt/mssql/log/sqlservr.log /var/opt/mssql/log/errorlog
+```
+
+続いて、intra-mart 用 DB とユーザの作成です。
+これを docker build 時に行っておくことで、docker run 後にすぐ利用できるようになります。
+
+以下のユーザを作成しています。
+ユーザ名:imart
+パスワード:imart
+
+以下の DB を作成しています。
+
+* imart
+* iap_db
+* default
+
+すべての DB の照合順序は [Japanese_XJIS_100_CS_AS_KS_WS](https://www.intra-mart.jp/download/product/iap/setup/iap_setup_guide/texts/install/common/database.html#microsoft-sql-server) です。
+すべての DB に対して [acceldocuments](https://www.intra-mart.jp/download/product/iad/im_acceldocuments_setup_guide/texts/setup_guide/database/index.html#microsoft-sql-server) スキーマも作成しています。
+すべての DB に対して [READ_COMMITTED_SNAPSHOT](https://www.intra-mart.jp/download/product/iap/setup/iap_setup_guide/texts/install/common/database.html#microsoft-sql-server) を設定しています。
+
+```shell:create_user.sh
+#!/bin/sh
+
+sqlcmd -S localhost -U sa -P 'password' -i /create_user.sql
+```
+
+```sql:create_user.sql
+-- imart user
+USE [master]
+GO
+CREATE LOGIN [imart] WITH PASSWORD=N'imart', DEFAULT_DATABASE=[master], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF
+GO
+
+-- imart
+CREATE DATABASE [imart]
+ CONTAINMENT = NONE
+ ON PRIMARY
+( NAME = N'imart', FILENAME = N'/var/opt/mssql/data/imart.mdf' , SIZE = 8192KB , FILEGROWTH = 65536KB )
+ LOG ON
+( NAME = N'imart_log', FILENAME = N'/var/opt/mssql/data/imart_log.ldf' , SIZE = 8192KB , FILEGROWTH = 65536KB )
+ COLLATE Japanese_XJIS_100_CS_AS_KS_WS
+GO
+ALTER DATABASE [imart] SET READ_COMMITTED_SNAPSHOT ON;
+GO
+
+USE [imart]
+GO
+EXEC dbo.sp_changedbowner @loginame = N'imart', @map = false
+GO
+
+-- iap_db
+CREATE DATABASE [iap_db]
+ CONTAINMENT = NONE
+ ON PRIMARY
+( NAME = N'iap_db', FILENAME = N'/var/opt/mssql/data/iap_db.mdf' , SIZE = 8192KB , FILEGROWTH = 65536KB )
+ LOG ON
+( NAME = N'iap_db_log', FILENAME = N'/var/opt/mssql/data/iap_db_log.ldf' , SIZE = 8192KB , FILEGROWTH = 65536KB )
+ COLLATE Japanese_XJIS_100_CS_AS_KS_WS
+GO
+ALTER DATABASE [iap_db] SET READ_COMMITTED_SNAPSHOT ON;
+GO
+
+USE [iap_db]
+GO
+EXEC dbo.sp_changedbowner @loginame = N'imart', @map = false
+GO
+
+-- imart default database
+ALTER LOGIN [imart] WITH DEFAULT_DATABASE=[iap_db], DEFAULT_LANGUAGE=[日本語], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF
+GO
+
+-- default
+CREATE DATABASE [default]
+ CONTAINMENT = NONE
+ ON PRIMARY
+( NAME = N'default', FILENAME = N'/var/opt/mssql/data/default.mdf' , SIZE = 8192KB , FILEGROWTH = 65536KB )
+ LOG ON
+( NAME = N'default_log', FILENAME = N'/var/opt/mssql/data/default_log.ldf' , SIZE = 8192KB , FILEGROWTH = 65536KB )
+ COLLATE Japanese_XJIS_100_CS_AS_KS_WS
+GO
+ALTER DATABASE [default] SET READ_COMMITTED_SNAPSHOT ON;
+GO
+
+USE [default]
+GO
+EXEC dbo.sp_changedbowner @loginame = N'imart', @map = false
+GO
+
+-- acceldocuments
+USE [imart]
+GO
+CREATE SCHEMA [acceldocuments] AUTHORIZATION [db_owner]
+GO
+
+USE [iap_db]
+GO
+CREATE SCHEMA [acceldocuments] AUTHORIZATION [db_owner]
+GO
+
+USE [default]
+GO
+CREATE SCHEMA [acceldocuments] AUTHORIZATION [db_owner]
+GO
+```
+
+続いて、ユーザを drop する処理です。
+docker run し直せばいい話ですが、docker は起動したままでユーザを作り替えたいという場合にご利用ください。
+
+```shell:drop_user.sh
+#!/bin/sh
+
+sqlcmd -S localhost -U sa -P 'password' -i /drop_user.sql
+```
+
+```sql:drop_user.sql
+USE [master]
+GO
+
+DROP DATABASE [default]
+GO
+DROP DATABASE [iap_db]
+GO
+DROP DATABASE [imart]
+GO
+```
+
+# 起動
+
+docker run -it -p 0.0.0.0:1433:1433 -p 0.0.0.0:2222:22 mysqlserver_on_linux:2017
+
+# データ永続化
+
+データを永続化したい場合、docker volume を使えば OK です。
+named volume であれば docker run 時に docker コンテナ内のデータが docker volume にコピーされてマウントされるため、次のように起動してください。
+
+docker run -v sqlserver:/var/opt/mssql/data -it -p 0.0.0.0:1433:1433 -p 0.0.0.0:2222:22 mysqlserver_on_linux:2017
+
+# SQL Server Management Studio
+
+sa/password で接続可能です。
+
+というわけで簡単にですが SQL Server on Linux 2017 の Docker についての紹介でした。