6.1 KiB
title, type, tags, sources, updated
| title | type | tags | sources | updated | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| MSSQL контейнер с восстановленными production data — паттерн | concept |
|
|
2026-05-19 |
MSSQL container с production data
Проблема
Восстановить MSSQL базу в Docker-контейнере на Windows-хосте из:
- Готовых
.mdf/.ldfфайлов production (взяты из tar/var/opt/mssql/source-контейнера) -
- 5 user-databases + системные (master/model/msdb/tempdb)
Что НЕ работает: bind-mount production data
volumes:
- ./production-data/mssql:/var/opt/mssql
Не работает на Windows Docker Desktop. MSSQL-контейнер требует:
master.mdfowned bymssqluser (UID 10001) или rootchmodна файлах внутри/var/opt/mssql/log/(логи, .xel, .trc)
На Windows DD bind-mount через WSL2-слой не позволяет:
- Файлы видятся как owned by root or other UID — MSSQL отказывается:
Your master database file is owned by root. chmodвнутри контейнера фейлится:Operation not permitted
Симптом: MSSQL стартует, в логах ругается на chmod, потом стартует ещё раз и зависает.
Что работает: named volume + chown через temp container
Идея: создать named volume, скопировать данные внутрь с правильным chown, потом примонтировать к MSSQL.
# docker-compose.yml — финальная версия
services:
mssql:
image: mcr.microsoft.com/mssql/server:2019-latest
container_name: mssql
environment:
ACCEPT_EULA: "Y"
MSSQL_SA_PASSWORD: ${SA_PASSWORD}
MSSQL_PID: Developer
ports:
- "1433:1433"
volumes:
- mssql_data:/var/opt/mssql
networks:
- proxy
restart: unless-stopped
volumes:
mssql_data:
networks:
proxy:
external: true
Заполнение volume (один раз перед docker compose up -d):
docker volume create mssql_mssql_data
docker run --rm \
-v mssql_mssql_data:/dest \
-v <local-path-to-production-data>/mssql:/src:ro \
alpine cp -a /src/. /dest/
docker run --rm -v mssql_mssql_data:/dest \
alpine chown -R 10001:0 /dest
docker compose up -d
После этого MSSQL стартует с production data, делает crash recovery в master.mdf, поднимается за 30-60 секунд (если CU контейнера == CU source) или 5-30 минут (если CU source старше — script upgrade mode).
sqlcmd "$( var-substitution" pitfall
Альтернативный путь — restore из .sql script (export через "Generate Scripts" в SSMS). Файл 547 MB с CREATE+INSERT'ами всей БД.
Не запустить через sqlcmd -i file.sql без флага -x. Потому что:
- В данных встречаются jQuery JS-сниппеты типа
INSERT ... VALUES (N'$(function(){ ... })') - sqlcmd по умолчанию интерпретирует
$(varname)как переменную для подстановки. - На
$(function(){парсер ломается → "Syntax error near command '('" в середине файла.
Фикс: sqlcmd -x (disable variable substitution).
docker exec mssql /opt/mssql-tools18/bin/sqlcmd \
-S localhost -U sa -P '<pw>' -C -x \
-i /var/opt/mssql/backup/MoreThenCms.sql
SA-аккаунт disabled в production
Production SQL Server конфигурации часто отключают sa (security best practice). Пароль может быть прав, но account disabled → Login failed for user 'sa'. Reason: The account is disabled.
Фикс: mssql-conf set-sa-password в offline-mode (server stopped) под root:
# Stop running container
docker compose stop
# Run offline mssql-conf in temp container с тем же volume
docker run --rm --user 0:0 \
-e ACCEPT_EULA=Y \
-e MSSQL_SA_PASSWORD='<new-pw>' \
-v mssql_mssql_data:/var/opt/mssql \
mcr.microsoft.com/mssql/server:2019-latest \
/opt/mssql/bin/mssql-conf set-sa-password
# Запуск нормального container
docker compose start
mssql-conf set-sa-password сбрасывает пароль И enables sa. Если env-pw совпадает с тем что ожидает приложение — приложение продолжает работать.
Production passwords reuse
Замеченный паттерн: у пользователя один пароль fXkH4@8O%3pc используется как:
- SA password (MSSQL)
- Connection string password для user
snolla(CMS DB user) - Возможно где-то ещё
Лучше: rotate after recovery, разделить.
CU mismatch warning
Если master.mdf был из старой CU (например 2019 CU14), а контейнер 2019-latest (например CU32-GDR), MSSQL после старта войдёт в script upgrade mode на 10-30 минут:
Server is in script upgrade mode. Only administrator can connect at this time.
Видно в логах сотни строк spid9s ... Deleting AlwaysOnAgReplicas... — это нормальный msdb-upgrade. Подождать. Один раз. После завершения — никаких задержек на следующих стартах.
Healthcheck path для 2019-latest image
В современных image SQL Server инструменты лежат в /opt/mssql-tools18/bin/sqlcmd (с TLS-флагом -C), а не /opt/mssql-tools/bin/sqlcmd:
healthcheck:
test: ["CMD-SHELL", "/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P \"$$MSSQL_SA_PASSWORD\" -C -Q 'SELECT 1' -b -o /dev/null || exit 1"]
Связано: snolla-recovery-vm (Web.config указывает на 10.0.2.2:1433 = host из VM-NAT), windows-recovery-host.