Контейнеризуємо MS SQL у парі з SQL Server Data Tools (SSDT)
Усі статті, обговорення, новини про DevOps — в одному місці. Підписуйтеся на DOU | DevOps!
Привіт, мене звати Степан Чубанян, наразі займаю посаду Senior Software Engineer (.NET) в Grid Dynamics. Але не дотнетом єдиним, також захоплююсь всілякими DevOps-практиками. Ця стаття буде цікава .NET розробникам (або тим, хто використовує MS SQL) та, можливо, трошечки девопсам.
Навіщо взагалі нам контейнеризувати базу даних SQL? Будемо її запускати в контейнері на production оточенні? О ні, не будемо. Так-так, ми знаємо, що це цілком можливо, хоча й не без складнощів, але наразі не про це. Тож нащо нам ця авантюра?
Звичайно, що для розробки та тестування. Це може бути дуже корисно, зручно та досить легко для втілення, особливо якщо в нас MS SQL, а також SQL Server Data Tools (далі SSDT), яка дозволить нам легко керувати змінами та ініціалізацією бази даних.
У нашому випадку база буде запускатися в контейнері більше для того, щоб зручним чином передати базу даних QA-спеціалісту, який просто затягне образ контейнера та запустить, наприклад, у Docker Compose ваш застосунок, що буде дивитися в сусідній контейнер з БД. Таким чином, QA-спеціаліст може тестувати ваш застосунок на окремій та ізольованій БД, причому кожну таску можна тестувати окремо зі своєю версією БД.
Для чого SSDT
Сама SSDT дозволяє зручно керувати змінами в БД, це як контроль версії, так і застосування цих змін (публікація БД). Все це робиться більше в підході Database First, себто ми працюємо з БД більше як в SQL Server Management Studio. Це така альтернатива, що може бути до вподоби тим, хто хоче більше контролю над БД та не задоволений підходом Code First.
Створимо проєкт бази даних в SSDT
Для початку треба створити простий проєкт SSDT (наразі Visual Studio працює з SSDT найкращим чином)
Далі додамо трошки табличок.
Я намагався зберегти структуру БД якомога простішою, тому тут лише 2 таблички: Users та UserRoles
Насправді цього достатньо для того, щоб опублікувати нашу БД на екземпляр SQL Server. Тицяємо правою кнопкою по проєкту та обираємо відповідний пункт меню Publish.
У наступному віконці потрібно вказати рядок підключення до нашого сервера БД (Target database connection). Також, якщо є необхідність, можна більш точно вказати налаштування публікації, натиснувши на кнопку Advanced. Всі ці налаштування з рядком підключення, назвою БД, налаштуваннями тощо можна зберегти в профіль публікації (Save Profile As...) та потім просто завантажувати під час публікації (Load Profile).
Після того, як ви вкажете усі необхідні налаштування, можете згенерувати скрипт публікації (Generate Script) для створення/оновлення БД вручну або можете це зробити прямо через Visual Studio (Publish).
Як це працює? SSDT порівнює наш опис в проєкті та фактичну структуру БД, після чого генерує скрипт для синхронізації стану, щоб реальність в нашій БД відповідала очікуванням, що ми зазначили в проєкті.
Автоматизуємо процес за допомогою Docker на Windows
Окей, окей, чому на Windows, ваше питання я вже чую. Я згодний, що це може для когось здатися якимось збоченням, але насправді буває так, що тільки такий варіант є можливим. Наприклад, якщо ваш проєкт десь на .NET Framework 4.8 та перелізти на .NET 5 здається неможливим або керівництво не бачить в цьому сенсу, але вам все ж хочеться спробувати запхати той застосунок разом із БД до контейнерів, щоб відчути смак тих докерів та докер-компоузів. Принаймні в мене так було) Якщо буде попит — пишіть, я можу адаптувати це для Linux, без проблем, там навіть ще простіше все.
Тож розберімося, що ми автоматизуємо:
- Build проєкту бази даних, щоб отримати .dacpac файл, який є артефактом і необхідний для публікації
- Опублікувати базу даних використовуючи .dacpac файл
- Запустити БД в контейнері
Звучить досить просто. В реалізації воно в принципі так сам просто, але це не точно)
Build проєкту бази даних
Для того, щоб зібрати проєкт бази даних, msbuild — це все, що нам потрібно:
msbuild AwesomeDB.sqlproj
Ця команда на виході створить .dacpac файл.
Опублікувати базу даних
Для публікації БД нам потрібен sqlpackage. Скоріш за все, у вас його нема і потрібно буде його встановити:
Download and install SqlPackage — SQL Server | Microsoft Docs
Після встановлення запустимо команду для публікації:
sqlpackage.exe /a:Publish /sf:"db.dacpac" /tsn:. /tdn:AwesomeDb
Трохи поясню аргументи:
/a:Publish - action Publish
/sf:"db.dacpac" - source file db.dacpac
/tsn:. - Target Server Name . (this PC)
/tdn:AwesomeDb - Target Database Name AwesomeDb
Такий output маємо на виході:
Publishing to database 'AwesomeDB' on server '.'.
Initializing deployment (Start)
Initializing deployment (Complete)
Analyzing deployment plan (Start)
Analyzing deployment plan (Complete)
Updating database (Start)
Creating database AwesomeDB...
Creating SqlTable [dbo].[UserRoles]...
Creating SqlTable [dbo].[Users]...
Creating SqlForeignKeyConstraint [dbo].FK_Users_UserRoles_UserRoleId]...
Update complete.
Updating database (Complete)
Successfully published database.
Time elapsed 0:01:32.53:
Запустити БД в контейнері
Всередині контейнеру нам потрібно встановити усі залежності: такі як SSDT Build Tools, msbuild, sqlpackage, — після чого виконати те саме, що ми тільки-но робили вручну.
Ось наш Dockerfile (gist):
FROM mcr.microsoft.com/dotnet/framework/sdk:4.8-windowsservercore-ltsc2019 AS builder
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
# add SSDT build tools
RUN nuget install Microsoft.Data.Tools.Msbuild -Version 10.0.61804.210
# add SqlPackage tool
ENV download_url="https://download.microsoft.com/download/6/E/4/6E406E38-0A01-4DD1-B85E-6CA7CF79C8F7/EN/x64/DacFramework.msi"
RUN Invoke-WebRequest -Uri $env:download_url -OutFile DacFramework.msi ; \
Start-Process msiexec.exe -ArgumentList '/i', 'DacFramework.msi', '/quiet', '/norestart' -NoNewWindow -Wait; \
Remove-Item -Force DacFramework.msi
COPY /AwesomeDB .
RUN msbuild AwesomeDB.sqlproj \
/p:SQLDBExtensionsRefPath="C:\Microsoft.Data.Tools.Msbuild.10.0.61804.210\lib\net46" \
/p:SqlServerRedistPath="C:\Microsoft.Data.Tools.Msbuild.10.0.61804.210\lib\net46"
FROM octopusdeploy/mssql-server-windows-express:latest
# Install SQLPackage
RUN Invoke-WebRequest -Uri https://go.microsoft.com/fwlink/?linkid=2157302 -OutFile sqlpackage.zip; Expand-Archive -Path sqlpackage.zip -DestinationPath sqlpackage
# Add the DACPAC to the image
COPY --from=builder ["C:/bin/Debug/AwesomeDB.dacpac", "/db.dacpac"]
# Configure external build arguments to allow configurability.
ARG DBNAME=AwesomeDB
ARG PASSWORD
# Configure the required environmental variables
ENV ACCEPT_EULA=
ENV SA_PASSWORD=$env:PASSWORD
RUN "C:\sqlpackage\sqlpackage.exe" /a:Publish /sf:"db.dacpac" /tsn:. /tdn:$env:DBNAME
Покладіть цей файл у папку з вашим solution та насолоджуйтесь) Білдіть образ, використовуйте його на локальній машині або запуште в Container Registry та можете ділитися цим із вашою командою.
Висновок
Такий підхід допоможе нам знизити до мінімуму кількість проблем, що виникають при розгортанні БД у процесі розробки/тестування шляхом автоматизації.
На одному з проєктів ми виконали таку автоматизацію білда образу контейнеру, після чого пушили його у приватний реєстр. Далі будь-який член команди міг спулити образ нової версії БД — і це було супер зручно для QA спеціалістів в команді, тому що вони мали можливість протестити конкретну фічу на ізольованому локальному оточенні, включаючи БД.
Також можете подивитися на бонусний приклад автоматизації цього добра в Gitlab CI(.gitlab-ci.yml gist):
stages:
- build
.shared_windows_runners:
tags:
- shared-windows
- windows
- windows-1809
build-job:
stage: build
extends:
- .shared_windows_runners
script:
- docker build -t awesomedb:1.0 .
Тож автоматизуйте, але не просто так, а якщо в цьому є реальний профіт)
14 коментарів
Додати коментар Підписатись на коментаріВідписатись від коментарів