1. manymanyuni

    No comment

    manymanyuni
Changes in body
Source | HTML | Preview
@@ -1,335 +1,336 @@
# 前置き
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 で接続可能です。
+ユーザ sa/password で接続可能です。
+接続先は docker run しているマシンの IP アドレスになります。
+
というわけで簡単にですが SQL Server on Linux 2017 の Docker についての紹介でした。