Coding Gun

ติดต้ัง Sql Server ด้วย Docker

การติดต้ัง SQL Server ลงใน docker จะมีวิธีการที่แตกต่างจากการติดต้ัง server ด้วย VM อยู่พอสมควรดังนั้นในบทความนี้เราจะพาคุณไปดูวิธีการติดตั้ง SQL Server แบบ step by step

ข้อดีของการใช้ docker

ก่อนจะเข้าสู่วิธีการติดต้ังเราต้องขายให้ได้ก่อนว่าทำไมเราถึงต้องใช้ docker

  1. สามารถเปลี่ยน version ของ SQL Server ได้งง่าย
  2. สามารถจำลอง database server บนเครื่อง dev ได้ง่าย
  3. เราสามารถจัดการกับ version ของ database ได้ง่ายขึ้น
  4. นำไป deploy ลงใน Kubernetes cluster ต่อได้
  5. สามารถนำเข้าไปใส่ใน CI/CD Pipeline ได้ง่าย

Docker กับ Database

การทำงานกับ database ใน docker นั้นเราต้องเข้าใจ 2 สิ่งนี้ก่อน

  1. การทำงานของ docker นั้นจะแบ่งเป็น layer ซึ่งในการทำงานกับ database นั้นเราจะแยกออกเป็น 4 layers ดังนี้

    • Database ตัวฐานข้อมูลที่เราจะนำมาใช้งาน เราจะใช้ไฟล์ SQL ในการนำเข้า
    • SQL Server Engine เป็น database server ที่นำมาใช้งาน
    • Engine Dependencies เครื่องมือหรือ services ต่างๆ ที่ติดตั้งเข้าไปเพิ่มเติม
    • Base OS Image Database ไม่สามารถ run ได้ด้วยตัวเองต้องนำไปติดตั้งลงใน OS สำหรับ SQL Server ตอนนี้ official image จะใช้ Ubuntu เป็น base image

    บน production เราต้องใช้ Linux-based container เพราะ Microsoft ไม่ support การใช้ windows-based container บน production อีกแล้ว

  2. เราต้องใช้ Volume เพราะเราไม่สามารถเก็บข้อมูลไว้ใน container ได้ เนื่องจากเราต้องการให้ SQL Server ของเราสามารถลบทิ้งแล้วสร้างใหม่ได้ตลอดเวลา

สิ่งที่คุณต้องมีก่อนติดต้ัง

  1. Docker Desktop
  2. Azure Data Studio หรือ SQL Server Management Studio(SSMS)

ขั้นตอนการติดต้ัง SQL Server

การติดตั้ง SQL Server ลงใน docker container เราจะเริ่มจากการ run SQL Server container ด้วย docker run command ก่อน หลังจากนั้นเราจะเปลี่ยนจาก docker run command ไปเป็น service ใน docker compose

ขั้นตอนที่ 1. สร้าง SQL Server

ในตัวอย่างแรก เราจะใช้ docker image จาก microsoft โดยที่ใช

1
2
3
4
5
docker run --name testdb -d \
           -p 1433:1433 \
           -e sa_password=$qlServerD0cker \
           -e ACCEPT_EULA=Y \
           mcr.microsoft.com/mssql/server:2022-latest

ความหมายของ parameters ที่เรากำหนดให้กับคำสั่ง docker run มีดังนี้

สำหรับคนที่ใช้ windows ตัวิย่าง docker command นี้จะต้อง run ใน powershell เพราะผมใช้ \ แต่ถ้าจะเอาไป run ใน command prompt คุณต้องลบ \ ออกแล้ววางไว้ในบรรทัดเดียวกัน

เราสามารถใช้งาน SQL Server ผ่านทาง docker แบบนี้ได้ก็จริงแต่ปัญหาที่เราต้องเจอคือ

  1. ยังไม่มี database และต้องนำเข้าด้วยมือหลังจาก container start ขึ้นมาแล้ว
  2. data ยังอยู่ภายใน container ซึ่งหมายความว่า เมื่อเราลบ container ทิ้ง data ทั้งหมดจะหายไปทันที ซึ่งไม่น่าจะดีแน่นอน

ดังนั้นในขึ้นตอนต่อไปเราจะมาไล่แก้ปัญหา 2 ข้อนี้

SQL Server Password Policy

การจะตั้ง password ของ user ใน SQL Server ต้องทำตามนี้

ขั้นตอนที่ 2. สร้าง Docker Volume

เราจะต้องสร้าง volume ขึ้นมาเพื่อแยก data ออกไปอยู่ยอก container ถ้าเราสร้าง container ด้วย docker run เราจะใช้ paraneter -v แบบนี้

1
2
3
4
5
6
7
8
docker run --name testdb -d \
           -p 1433:1433 \
           -v weatherdb/data:/var/opt/mssql/data
           -v weatherdb/log:/var/opt/mssql/log
           -v weatherdb/secrets:/var/opt/mssql/secrets
           -e sa_password=$qlServerD0cker \
           -e ACCEPT_EULA=Y \
           mcr.microsoft.com/mssql/server:2022-latest

ในการ map volume เราจะ map ข้อมูล 3 ชุดด้วยกัน

  1. data เป็น folder ที่เก็บ data ใน container จะอยู่ที่ /var/opt/mssql/data
  2. log เป็น folder ที่จัดเก็บ log ของ sql server ใน container จะอยู่ที่ /var/opt/mssql/log
  3. secrets เป็น folder ที่จัดเก็บความลับต่างๆ เช่น keytab, certificates และ machine key ซึ่งใน container จะอยู่ที่ /var/opt/mssql/secrets

เนื่องจาก application ของจริงจะต้องมีหลาย services เช่น api, database และ log server เราจึงจะแปลงจาก docker command ไปเป็น docker compose เพื่อให้ง่ายต่อการนำไปใช้งาน ซึ่งเราจะได้ docker-compose.yml ออกมาแบบนี้

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
version: '3.8'

services:
  sql_server:
    build:
        context: .
        dockerfile: sql.dockerfile
    restart: always
    ports:
        - "1433:1433"
    environment:
        - ACCEPT_EULA=Y
        - SA_PASSWORD=$qlServerD0cker
    volumes:
        - weatherdb:/var/opt/mssql/data
        - weatherlog:/var/opt/mssql/log
        - weathersecrets:/var/opt/mssql/secrets
volumes:
  weatherdb:
  weatherlog:
  weathersecrets:

ขั้นตอนที่ 3 สร้าง Schema ของ Database

ขั้นตอนนี้เราต้องการให้สร้าง SQL Server ขึ้นมาแล้วมี database มาพร้อมสำหรับการใช้งานเลย เวลานำไปทำ Automate deploy หรือ Automated testing จะได้ง่าย

ในตัวอย่างนี้เราจะสร้าง database ชื่อ CarvedRock และใน databaes นี้จะมี table ชื่อ Product โดยจะตั้งชื่อไฟล์ว่า initializeDatabase.sql

CREATE DATABASE CarvedRock
GO 
USE CarvedRock
GO 
----------------------------------------------------------------------------
--- TABLE CREATION
----------------------------------------------------------------------------
CREATE TABLE [dbo].[Product](
	[Id] [INT] NOT NULL,
	[Name] [NVARCHAR](100) NOT NULL,
	[Description] [NVARCHAR](MAX) NULL,
	[Price] [NUMERIC](14, 2) NOT NULL,
	[Category] [NVARCHAR](30) NOT NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO

หลังจากนั้นเราจะนำ InitializeDatabase.sql เข้าไปใส่ไว้ใน dockerfile ที่เราจะตั้งชื่อว่า sql.dockerfile

FROM mcr.microsoft.com/mssql/server:2022-latest

ARG PROJECT_DIR=/tmp/devdatabase
RUN mkdir -p $PROJECT_DIR
WORKDIR $PROJECT_DIR
COPY sql/InitializeDatabase.sql ./
COPY sql/wait-for-it.sh ./
COPY sql/entrypoint.sh ./
COPY sql/setup.sh ./

USER root
RUN sh -c "chmod +x ./*.* && chown mssql ./*.*"

USER mssql
EXPOSE 1433
CMD ["/bin/bash", "entrypoint.sh"]

เราต้อง copy file เข้าไปใน /tmp เพื่อให้สามารถ execute ได้

ในตัวอย่างนี้เราจะต้องเขียน shell script เพื่อให้ IntialDatabase.sql ถูก execute เมื่อ SQL Server อยู่ในสถานะที่พร้อมใช้งานแล้ว โดยจะไล่ไปตามขั้นตอนดังนี้

  1. entrypoint.sh จะถูก run เป็นตัวแรกเมื่อเราสร้าง container ใน shell script ตัวนี้จะทำ

    • start SQL Server
    • เรียก setup.sh เพื่อสร้าง CarvedRock database
    • sleep และ wait เพื่อให้ process ทำงานเป็น background service
    1
    
    /opt/mssql/bin/sqlservr & ./setup.sh & sleep infinity & wait
    
  2. setup.sh จะเป็น shell script ที่เขียนขึ้นมาเพื่อสร้าง database โดยมีเงื่อนไขว่าเราจะ import database เข้าไปได้ก็ต่อเมื่อ SQL Server อยู่ในสถานะพร้อมใช้งาน ดังนั้นเราจึงต้องใช้ wait-for-it ซึ่งเป็น opensource ที่ใช้ในการรอจนกว่า service ที่เราต้องการนั้นพร้อมใช้งาน

    1
    2
    3
    4
    
    ./wait-for-it.sh localhost:1433  --timeout=0 --strict -- sleep 10s && \
    /opt/mssql-tools/bin/sqlcmd -S localhost \
        -i InitializeDatabase.sql \
        -U sa -P "$SA_PASSWORD"
    

    หลังจากนั้นในบรรทัดที่ 2 เราจะใช้ sqlcmd ในการ import database เมื่อทำครบทั้ง 2 บรรทัดนี้แล้วเราจะได้ SQL Server ที่มี โครงสร้าง database พร้อมทั้ง data มาให้เราใช้งานเรียบร้อย

ขั้นตอนที่ 4 จัดการกับ SQL Server ด้วย Azure Data Studio

ขั้นตอนนี้เราสามารถใช้ SQL Server Management Studio(SSMS) หรือ Azure Data Studio ก็ได้ ในตัวอย่างนี้เราจะใช้ Azure Data Studio เพราะสามารถติดต้ังได้ทุก OS แต่ความสามารถก็อาจยังสู้กับ SQL Server Management Studio ไม่ได้

Create new connection to SQL Server
การสร้าง Connection ใน Azure Data Studio

หลังจากนั้นกำหนดค่า

ถ้าทุกอย่างถูกต้องเรียบร้อยเราจะได้หน้าสำหรับจัดการกับ database

ข้อแนะนำ การเปลี่ยนแปลงโครงสร้างของ Database ควรจะทำใน InitializeDatabase.sql เพื่อให้ถูกจัดการ Version หรือใช้ Migration tools อย่าง Flyway หรือ Liquibase

Phanupong Permpimol
Follow me