Всем контейнеризированный привет!
Недавно на площадке увидел публикацию про установку SQL Server. Хммм, подумал я. И это в 2К25 году. Банально проклацать кнопку "далее" - ну это такое себе. Тем более, что только ленивый не ставил SQL Server. И тут мне пришла идея поделиться с сообществом более технической статьей, так сказать, под современные тренды в айтишке.
Здесь будет полный гайд по созданию и использованию SQL Server в Docker-контейнере.
Если кто вдруг не в курсе, что такое Docker, то расскажу вкратце. Docker - это набор специализированного системного программного обеспечения, позволяющее упаковать в отдельный контейнер вашу программу со всем её окружением и со всеми её зависимостями, и в дальнейшем изолированно запускать вашу программу в своей собственной "песочнице", ресурсы которой будут независимо использоваться от вашей основной системы и от присутствующих в ней программ. Отличие контейнеризации от виртуализации в том, что последняя тратит ресурсы на обслуживание полноценной операционной системы внутри себя. А Docker-контейнер использует ядро текущей операционной системы для управления процессами, дисковыми и сетевыми ресурсами, которые разграничены с основной хост-системой.
Родная система для Докера, это, конечно же, Linux. Но Microsoft прилагает немалые усилия по интеграции Linux в Windows. Поэтому сейчас стало возможно использовать виндовые контейнеры, почти так же, как и линуксовые.
Здесь я покажу виндовую контейнеризацию. В качестве подопытного скуля возьму SQL Server 2019, так как он пока ещё актуален и будет поддерживаться до 2030 года. А также он совместим с новыми и достаточно старыми платформами 1С. Вы же для повторения можете взять любую версию.
Не спешите сразу кидаться помидорами, мол, у нас импортозамещение. Это да. Но MS SQL стоит ещё у многих. А если кто и перевёл на Постгрес свой основной продуктив, то смежные базы, вероятно, на MS SQL.
Поплыли Поехали !
Если у вас на виндовой машине нет докера, то установим его:
Перед установкой убедитесь, что у вас включена аппаратная виртуализация (VT или AMD-V в настройках UEFI/BIOS). Переходим на страницу Install Docker Desktop on Windows и скачиваем инсталлятор "Docker Desktop Installer.exe" и запускаем его. Всё оставляем по умолчанию, проходим шаги инсталлятора, в конце инсталлятор предложит перезагрузиться. После перезагрузки запускаем Docker Desktop - это графическая оболочка над Докером.
Можно управлять докером и через консоль.
docker -v
отобразит текущую версию.
Т.к. я больше уважаю консоль, чем графическую оболочку, то мы будем вводить команды в cmd, а некоторые результаты смотреть в десктопном приложении.
Для начала нам нужно скачать стартовый образ Windows Server 2019. Делается это следующей командой:
docker pull mcr.microsoft.com/windows/servercore:ltsc2019
Я взял за основу Core редакцию Windows Server 2019, вы же можете взять и более новые (или старые).
Забегая наперед, скажу, что контейнеры построены как бы послойно. Т.е. за основу берется какой-либо готовый образ, потом на него накатывают различные обновления, ПО, команды. И получается по аналогии со слоеным пирогом. Это экономит место и время для сборки похожих и/или наследственных контейнеров.
После скачивания на вашу машину проверим существующие образы:
docker images
В ответе будет что-то подобное:
Аналогичную картину можем увидеть и через ГУЙ:
Отлично. У нас есть основа. От неё будем далее создавать свой образ.
Для этого создадим пустой текстовый файл и назовём его Dockerfile без расширения. (Выделите у себя на компе отдельный рабочий каталог, в котором будем сохранять всю работу). В этом Докер-файле будем описывать логику построения нашего образа.
Первой строкой пропишем, от какого образа мы будем плясать:
FROM mcr.microsoft.com/windows/servercore:ltsc2019
А пока нам надо раздобыть инсталлятор скуля. Будем брать Developer-версию для разрабов. Она для разработки и тестирования бесплатна, а по функциональности аналогична Enterprise версии.
По ссылке SQL 2019 DEV качаем онлайн инсталлятор. Запускаем его. Выбираем 3-й пункт "Download Media":
Далее переставляем переключатель на "CAB", ниже выбираем нашу рабочую папку и нажимаем кнопку "Download".
Через *цать секунд у нас в нашем рабочем каталоге появятся 2 файла: "SQLServer2019-DEV-x64-ENU.exe" и "SQLServer2019-DEV-x64-ENU.box". Это инсталлятор и дата-файл для стокового SQL Server 2019 Developer Edition.
Ещё один служебный файл надо скачать с официального репозитория Microsoft. Он нужен для присвоения пароля и присоединения существующих баз данных. Положите его тоже в нашу рабочую папку.
Т.к. скуль-сервер стоковый, надо еще скачать последнее кумулятивное обновление. Переходите на страницу и скачивайте самый свежий на данный момент KBxxxxxxx. Переименуем этот новый скачанный файл из "SQLServer2019-KBххххххх-x64.exe" в "SQLServer2019-CU-x64.exe" для дальнейшего удобства.
У нас всё готово для создания образа скуля. Вернёмся к нашему Dockerfile. Далее в нём прописываем переменные окружения:
ENV sa_password="_" \ attach_dbs="[]" \ ACCEPT_EULA="_" \ sa_password_path="C:\ProgramData\Docker\secrets\sa-password"
Пропишем поведение скрипта при различных обстоятельствах:
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
Затем копируем в образ в корень файловой системы необходимые файлы:
COPY start.ps1 / COPY SQLServer2019-DEV-x64-ENU.exe / COPY SQLServer2019-DEV-x64-ENU.box / COPY SQLServer2019-CU-x64.exe /
Задаем текущую рабочую директорию для контейнера:
WORKDIR /
Запускаем процесс установки SQL-сервера:
RUN Start-Process -Wait -FilePath .\SQLServer2019-DEV-x64-ENU.exe -ArgumentList /qs, /x:setup ; \ .\setup\setup.exe /q /ACTION=Install /INSTANCENAME=MSSQLSERVER /FEATURES=SQLEngine /UPDATEENABLED=0 /SQLSVCACCOUNT='NT AUTHORITY\NETWORK SERVICE' /SQLSYSADMINACCOUNTS='BUILTIN\ADMINISTRATORS' /TCPENABLED=1 /NPENABLED=0 /IACCEPTSQLSERVERLICENSETERMS ; \ Remove-Item -Recurse -Force SQLServer2019-DEV-x64-ENU.exe, SQLServer2019-DEV-x64-ENU.box, setup
Далее останавливаем службу SQL-сервера и меняем некоторые настройки:
RUN stop-service MSSQLSERVER ; \ set-itemproperty -path 'HKLM:\software\microsoft\microsoft sql server\mssql15.MSSQLSERVER\mssqlserver\supersocketnetlib\tcp\ipall' -name tcpdynamicports -value '' ; \ set-itemproperty -path 'HKLM:\software\microsoft\microsoft sql server\mssql15.MSSQLSERVER\mssqlserver\supersocketnetlib\tcp\ipall' -name tcpport -value 1433 ; \ set-itemproperty -path 'HKLM:\software\microsoft\microsoft sql server\mssql15.MSSQLSERVER\mssqlserver\' -name LoginMode -value 2 ;
Накатываем поверх кумулятивное обновление:
RUN Start-Process -Wait -FilePath .\SQLServer2019-KB5054833-x64.exe -ArgumentList '/Action=Patch /InstanceName=MSSQLSERVER /quiet /IAcceptSQLServerLicenseTerms' ; \ Remove-Item -Recurse -Force SQLServer2019-KB5054833-x64.exe
Проверяем, работает ли сервак, выполнит ли он SQL-запрос?:
HEALTHCHECK CMD [ "sqlcmd", "-Q", "select 1" ]
Стартуем сервер с нашими входными параметрами, которые будем задавать при старте контейнера:
CMD .\start -sa_password $env:sa_password -ACCEPT_EULA $env:ACCEPT_EULA -attach_dbs \"$env:attach_dbs\" -Verbose
Кажется сложно, но нет. Выше мы описали примитивные действия. Далее будет самое интересное.
Проводя аналогии, можно сказать следующее: если представить образ (image) в качестве слоёного пирога, то Dockerfile является рецептом этого пирога; если образ - это инсталлятор для программы, то контейнер - это уже запущенная программа.
На данном шаге у нас всё готово для сборки нашего образа! Запускаем билд:
docker build --memory 4g --tag=microsoft/mssql-server-windows-developer-2019:latest .
Вместо четвёрки в 4g вы можете выделить любой размер оперативки, который вам не жалко для сборки, но и этого объема хватает. Ключ tag задаёт имя образа; по данному имени в дальнейшем будем запускать контейнеры.
Ждем *цать секунд, пока образ соберется. Имя у него будет "microsoft/mssql-server-windows-developer-2019", как мы задали в команде.
Теперь мы можем запустить контейнер из нашего образа! Прелесть Докера в том, что из одного образа мы можем запустить множество контейнеров, в каждом из которых будет "крутиться" свежий SQL Server 2019 Developer Edition, независимый от серверов в других контейнерах.
Запустим:
docker run -d -p 1444:1433 -e sa_password=Aa123456! -e ACCEPT_EULA=Y microsoft/mssql-server-windows-developer-2019
Обратите внимание, что в данной команде мы мапим (делаем соответствие) наш порт на компе 1444 на порт sql-сервера в контейнере 1433. (по дефолту у ms sql server порт 1433, но у меня он занят основным скулём, вы же можете назначить любой доступный порт, даже 1433, если он у вас не занят). Пароль ставьте свой, этот приведён для примера.
Смотрим в Docker Desktop:
или в консоли:
docker ps
У нас запущен полноценный SQL Server в контейнере! Подключимся к нему через SSMS:
Обратите внимание: порт указывается через "," (через ЗАПЯТУЮ, Карл!), а не как мы все привыкли - через ":" .
Полноценный (* почти) сервер для разработки и тестирования в строю!
Мы можем интерактивно зайти в контейнер и посмотреть, что там и как происходит:
или то же самое консолью:
docker exec -it XXXXXXXX cmd
где вместо XXXXXXXX надо указать ID контейнера
Зачем я всё это читаю? А где же тут 1С ? А вот она. Ради этого всё и затевалось )
Создадим серверную базу данных 1С (не забываем про порт через запятую):
И оно работает! В контейнере! Невероятно, но факт!
Для чего это всё надо, можете спросить вы?
Во первых, вы НЕ захламляете и НЕ утяжеляете свой ПэКа. Достаточно 1 раз запустить сборку образа, а потом из этого образа запускать серваки для своих целей. Вы можете передать Dockerfile другу, который по аналогии соберет у себя образ и будет запускать скуль для работы/учёбы/развлечений/прочее. Во вторых, можете у себя поднять SQL-кластер из нескольких серверов. И всё это на одной машине. С минимальным потреблением ресурсов (образ занимает всего около 10 Гиг дискового пространства). С большим удобством/скоростью запуска/остановки сервера.
Представьте ситуацию: нам передали файлы базы данных sql-сервера. (мы же все знаем, что это *.mdf и *.ldf файлы). Нет ничего проще, чем пробросить их в наш контейнер и далее работать с предоставленной базой:
docker run -d -p 1455:1433 -v D:/PROJECT/Docker/win_sql/FileStorage1C:C:/temp/ -e sa_password=Aa123456! -e ACCEPT_EULA=Y -e attach_dbs="[{'dbName':'FileStorage1C','dbFiles':['C:\\temp\\FileStorage1C.mdf','C:\\temp\\FileStorage1C_log.ldf']}]" microsoft/mssql-server-windows-developer-2019
Здесь мы мапим нашу папку с файлами базы данных на папку внутри сервера, а скрипт для старта приаттачит файлы базы к запускаемому серверу:
Удобно? Очень удобно!
Также с помощью виртуальных томов (volumes) мы можем прописать при запуске контейнера пути, чтобы файлы создаваемых баз данных записывались в нашу файловую систему, чтобы при повторном старте контейнера продолжить работать с существующими данными. Можно создавать виртуальные сети и объединять контейнеры в независимые локальные сети, где внутри подобной сети контейнеры будут "видеть" друг друга. А ещё существуют специализированные ПО для оркестрации контейнеров, где оркестратор "рулит" контейнерами, например, может перезапускать упавшие контейнеры, может масштабировать нагрузку, поднимая или прибивая контейнеры и много чего другого, выходящего за рамки данной статьи.
И много много всего интересного можно делать с контейнеризацией. Это современный тренд, и используется он в современной разработке и ДевОпсе повсеместно.
* Microsoft не рекомендует использовать SQL Server в контейнере на продуктиве, т. к. перезагрузка контейнера Windows приводит к изменению ключа машины, и, следовательно, если у вас настроено какое -либо шифрование, перезагрузка SQL в контейнерах Windows порвёт цепочку ключей шифрования в SQL Server. Поэтому не существует официальных Docker-образов для скуля. Но в целях разработки вполне подходит собранный нами контейнер.
Надеюсь, что статья кому-то будет полезной и кто-то может подчерпнёт для себя что-то новое.
А если вам зашёл контент, то ставьте лайки плюсы. Наберётся много, напишу ещё что-нить про докер, например, 1С в докере (Win / Lin) или Постгрес в докере (на Линуксе).
Также не забывайте заходить на мой гитхаб. Выложу материалы по статье туда.
Всем творческих успехов и до скорого!