Themenseite · SQL Server unter Linux und Docker

SQL Server in Docker: Was im Container schiefgeht

Sie stoppen den Container mit docker stop. Zehn Sekunden passiert nichts, dann ist er weg, Exitcode 137. Beim nächsten Start läuft eine Recovery, als wäre der Strom ausgefallen. In unserem Lab war das bei SQL Server 2022 und 2025 bei jedem einzelnen Stopp so.

Stand 12.11.2026 · ca. 12 Minuten

Teil 3 · ContainerSQL-Abfrage 2Lab SQL Server 2017–2025
SQL Server 2022 und 2025 im Containerdocker stopSIGTERM kommt nicht anSIGKILL10,3 s · Exit 137 · Recovery beim nächsten Startkill -TERM an sqlservr1,1 s · Exit 0 · sauber beendet0 s5 s10 sFrist

SQL Server läuft im Container mit derselben Engine wie überall. Was sich ändert, ist alles drumherum: wer Signale bekommt, welche CPUs und wie viel Speicher die Engine zu sehen glaubt, wem die Dateien gehören. Die Schnellstarts von Microsoft zeigen, wie man den Container startet. Diese Seite zeigt sechs Stellen, an denen es danach schiefgeht, gemessen auf SQL Server 2017, 2019, 2022 und 2025.

In 60 Sekunden

  • docker stop beendet SQL Server 2022 und 2025 nicht sauber. Das Startskript im Image gibt das Stoppsignal nicht weiter. Docker wartet zehn Sekunden und bricht dann hart ab. --init macht es schlimmer. Sauber endet SQL Server nur, wenn das Signal direkt an den sqlservr-Prozess geht.
  • Eine CPU-Quote (--cpus) sieht SQL Server nicht. Er plant mit allen CPUs des Hosts. Feste CPUs (--cpuset-cpus) beachten erst SQL Server 2022 und 2025.
  • SQL Server 2017 und 2019 sehen das Speicherlimit des Containers nicht (auf Hosts mit cgroup v2). In einem 4-GB-Container planten sie mit 60 GB. Begrenzen Sie den Speicher immer selbst und lassen Sie Kopfraum.
  • Volumes: Ab 2019 läuft SQL Server im Container nicht als root. Ab 2022 muss das Datenverzeichnis dem Benutzer mit der ID 10001 gehören, sonst startet SQL Server nicht.
  • Images: latest wandert mit jedem Update. Für reproduzierbare Umgebungen gehört der CU-Stand in den Tag. Bei 2025 ergibt MSSQL_PID=Developer die Enterprise Developer Edition.
  • Bereit ist SQL Server, wenn er auf eine Abfrage antwortet, nicht wenn der Container läuft. Im Lab dauerte das 7 bis 14 Sekunden.

1 · Herunterfahren: docker stop ist kein Shutdown

docker stop schickt dem Prozess mit der Nummer 1 im Container das Signal SIGTERM, wartet eine Frist (Standard zehn Sekunden) und beendet den Container danach mit SIGKILL. Das funktioniert nur, wenn Prozess 1 das Signal versteht oder weitergibt.

In den Images von SQL Server 2022 und 2025 ist Prozess 1 nicht SQL Server, sondern ein Startskript (/opt/mssql/bin/launch_sqlservr.sh), das SIGTERM weder verarbeitet noch an sqlservr weiterreicht. Das ist bei Microsoft als Fehler bekannt (mssql-docker #968, betrifft die Images seit 2022 CU18 und 2025-latest); eine Korrektur ist für kommende CUs angekündigt, ohne Nummer. In 2022 CU27 und 2025 CU10 war sie im Lab noch nicht enthalten.

SQL Server 2022 und 2025 · Prozess 1 ist das Startskriptdocker stop10,3 s · Exit 137 · Recoverydocker stop -t 3030,3 s · Exit 137 · Recoverymit --init0,2–0,3 s · Exit 143 · Recoverykill -TERM an sqlservr0,7–1,1 s · Exit 0 · sauberSQL Server 2017 und 2019 · Prozess 1 ist sqlservrdocker stop10,3–10,4 s · Exit 137 · Frist zu knappdocker stop -t 3010,3–10,4 s · Exit 0 · sauberFrist 10 sFrist 30 s0 s10 s20 s30 sabgebrochen, Recovery beim nächsten Startabgebrochen, ohne Recoverysauber beendet
SQL Server 2022 und 2025 · Prozess 1 ist dasStartskriptdocker stop10,3 s · Exit 137 · Recoverydocker stop -t 3030,3 s · Exit 137 · Recoverymit --init0,2–0,3 s · Exit 143 · Recoverykill -TERM an sqlservr0,7–1,1 s · Exit 0 · sauberSQL Server 2017 und 2019 · Prozess 1 istsqlservrdocker stop10,3–10,4 s · Exit 137 · Frist zu knappdocker stop -t 3010,3–10,4 s · Exit 0 · sauberFrist 10 sFrist 30 s0 s10 s20 s30 sabgebrochen, Recovery beim nächsten Startabgebrochen, ohne Recoverysauber beendet
Wie lange der Container bis zum Ende brauchte und wie er endete, je ein Lauf je Fall; kleine Datenbank ohne offene Transaktion. Die genauen Werte je Version stehen in der Tabelle.
VersionProzess 1docker stop (Frist 10 s)docker stop -t 30--initSIGTERM direkt an sqlservr
2017, 2019sqlservr10,3 s, Exit 13710,4 s, Exit 010,3 s, Exit 13710,3 s, Exit 0
2022 CU27Startskript10,3 s, Exit 137, Recovery30,3 s, Exit 137, Recovery0,3 s, Exit 143, Recovery1,1 s, Exit 0, sauber
2025 CU9 und CU10Startskript10,3 s, Exit 137, Recovery30,3 s, Exit 137, Recovery0,2–0,3 s, Exit 143, Recovery0,7 s, Exit 0, sauber

„Recovery“ heißt: Im Errorlog des beendeten Laufs fehlt SQL Server is terminating in response to a 'stop' request, und beim nächsten Start stehen Zeilen wie … transactions rolled forward in database …. Bestätigte Transaktionen gehen dabei nicht verloren; SQL Server holt sie aus dem Log nach. Aber jeder Stopp ist ein Abbruch, und mit großen offenen Transaktionen dauert der nächste Start entsprechend länger.

Warum --init nicht hilft: Mit --init setzt Docker einen kleinen Init-Prozess als Nummer 1 ein, der Signale weitergibt. Gemessen haben wir: Der Container ist nach 0,2 bis 0,3 Sekunden weg, ohne Stop-Meldung, und beim nächsten Start läuft die Recovery. Unsere Vermutung, nicht geprüft: Der Init-Prozess gibt das Signal an das Startskript weiter, nicht an SQL Server; das Skript endet sofort, und SQL Server endet mit ihm ohne geordnetes Herunterfahren.

Was hilft (2022 und 2025): SIGTERM direkt an den SQL-Server-Prozess schicken und warten, bis der Container endet:

# Prozessnummern von sqlservr im Container anzeigen (es gibt zwei)
docker exec mein-sql sh -c '
  for p in /proc/[0-9]*; do
    [ "$(cat $p/comm 2>/dev/null)" = sqlservr ] && echo ${p#/proc/}
  done'

# Eine der beiden genügt (hier 9 als Beispiel); im Lab endeten beide Varianten sauber
docker exec mein-sql kill -TERM 9
docker wait mein-sql

Im Lab war SQL Server danach in 0,7 bis 1,1 Sekunden beendet, mit Stop-Meldung und ohne Recovery beim nächsten Start. Dasselbe Prinzip gilt für Orchestrierungen: Ein preStop-Schritt, der das Signal an sqlservr schickt, ersetzt das fehlende Weiterreichen. Das haben wir unter Kubernetes nicht gemessen.

SQL Server 2017 und 2019 haben das Problem nicht: Dort ist sqlservr selbst Prozess 1 und fährt auf SIGTERM geordnet herunter. Er braucht dafür aber gut zehn Sekunden, also genau die Standardfrist von Docker. Mit docker stop ohne Zusatz endete es im Lab deshalb trotzdem mit Exit 137. Geben Sie mehr Zeit: docker stop -t 30 oder beim Start --stop-timeout 30.

2 · CPU: Die Quote sieht SQL Server nicht

Docker kennt zwei Arten, CPUs zu begrenzen: eine Quote (--cpus=2, der Container bekommt Rechenzeit für zwei CPUs, verteilt auf alle) und feste CPUs (--cpuset-cpus=22-23, der Container läuft nur auf diesen beiden). Wir haben gemessen, was SQL Server jeweils sieht, auf einem Host mit 24 logischen CPUs:

Versionohne Grenze--cpus=2--cpuset-cpus2017, 2019sieht 24, hat 24sieht 24, bekommt 2sieht 24, läuft auf 22022, 2025sieht 24, hat 24sieht 24, bekommt 2sieht 2, hat 2Ein Punkt je logischer CPU des Hosts (24). Gefüllt: Scheduler, die SQL Server anlegt. Orange: mehr, alsder Container an CPU bekommt.
2017, 20192022, 2025ohne Grenzesieht 24, hat 24sieht 24, hat 24--cpus=2sieht 24, bekommt 2sieht 24, bekommt 2--cpuset-cpussieht 24, läuft auf 2sieht 2, hat 2Ein Punkt je logischer CPU des Hosts (24).Gefüllt: Scheduler, die SQL Server anlegt.Orange: mehr, als der Container an CPU bekommt.
Was SQL Server von den CPUs sieht, gemessen auf einem Host mit 24 logischen CPUs, Container mit zwei CPUs als Quote (--cpus) oder als feste CPUs (--cpuset-cpus).
Versionohne Grenze--cpus=2--cpuset-cpus (2 CPUs)
2017, 201924 CPUs, 24 Scheduler24 CPUs, 24 Scheduler24 CPUs, 24 Scheduler
2022, 202524 CPUs, 24 Scheduler24 CPUs, 24 Scheduler2 CPUs, 2 Scheduler
  • Die Quote sieht keine Version. Microsoft beschreibt das so; im Lab bestätigt. SQL Server legt für jede Host-CPU einen Scheduler an und plant Parallelität danach, obwohl der Container nur zwei CPUs Rechenzeit bekommt.
  • Feste CPUs beachten erst 2022 und 2025. Dazu fanden wir keine Quelle; 2017 und 2019 sehen trotz Pinning alle 24.
  • Die Folge ist messbar: Eine Tabellensperre mit TABLOCKX belegte bei 24 sichtbaren CPUs 24 Lock-Partitionen, bei zwei sichtbaren eine. Und mit der Voreinstellung max degree of parallelism = 0 darf eine Abfrage so viele Threads nutzen, wie SQL Server CPUs sieht. Wie stark das die Laufzeit unter einer Quote verschlechtert, haben wir nicht gemessen.

Was hilft: Auf 2022 und 2025 feste CPUs statt einer Quote verwenden, wenn der Host das zulässt. Auf allen Versionen MAXDOP passend zu den tatsächlich verfügbaren CPUs setzen. Microsoft nennt für Quoten zusätzlich ALTER SERVER CONFIGURATION SET PROCESS AFFINITY zusammen mit Trace Flag 8002; das haben wir nicht geprüft. CPU-Limits unter Kubernetes sind in der Regel Quoten in diesem Sinn; unter Kubernetes haben wir nicht gemessen.

3 · Speicher: Drei Grenzen, die man auseinanderhalten muss

  • --memory begrenzt den ganzen Container. Wird es überschritten, beendet der Kernel den Prozess (OOM-Kill).
  • MSSQL_MEMORY_LIMIT_MB sagt SQL Server, wie viel Speicher er insgesamt als vorhanden betrachten soll.
  • max server memory begrenzt innerhalb davon den Speicher der Engine.

Ohne Einstellung nimmt SQL Server laut Microsoft 80 Prozent des kleineren Werts aus Host-Speicher und Container-Grenze. Was wir auf einem Host mit cgroup v2 (dem Standard aktueller Linux-Distributionen) gemessen haben:

Nur --memory=4g2017Ziel 60.480 MB · sieht 64.417 MB2019Ziel 61.037 MB · sieht 64.417 MB2022Ziel 2.617 MB · sieht 3.277 MB2025Ziel 2.721 MB · sieht 3.277 MBContainer-Grenze 4 GB0 GB16 GB32 GB48 GB64 GB--memory=4g und MSSQL_MEMORY_LIMIT_MB=60002017Ziel 4.935 MB · sieht 6.000 MB2019Ziel 5.112 MB · sieht 6.000 MB2022Ziel 3.433 MB · sieht 4.096 MB2025Ziel 3.618 MB · sieht 4.096 MBContainer-Grenze 4 GB0 GB2 GB4 GB6 GB8 GBBalken: Speicherziel von SQL Server. Strich: Speicher, den SQL Server als vorhanden meldet. Orange: Zielüber der Container-Grenze.
Nur --memory=4g2017 · Ziel 60.480 MB · sieht 64.417 MB2019 · Ziel 61.037 MB · sieht 64.417 MB2022 · Ziel 2.617 MB · sieht 3.277 MB2025 · Ziel 2.721 MB · sieht 3.277 MBContainer-Grenze 4 GB0 GB16 GB32 GB48 GB64 GB--memory=4g und MSSQL_MEMORY_LIMIT_MB=60002017 · Ziel 4.935 MB · sieht 6.000 MB2019 · Ziel 5.112 MB · sieht 6.000 MB2022 · Ziel 3.433 MB · sieht 4.096 MB2025 · Ziel 3.618 MB · sieht 4.096 MBContainer-Grenze 4 GB0 GB2 GB4 GB6 GB8 GBBalken: Speicherziel von SQL Server. Strich:Speicher, den SQL Server als vorhanden meldet.Orange: Ziel über der Container-Grenze.
Speicherziel (committed_target_kb) und gemeldeter Speicher (physical_memory_kb) im Container mit 4 GB, gemessen auf SQL Server 2017 bis 2025. 64.417 MB sind 80 Prozent des Host-Speichers.
Version--memory=4g4g und MSSQL_MEMORY_LIMIT_MB=32004g und MSSQL_MEMORY_LIMIT_MB=6000
2017sieht 64.417 MB, Ziel 60.480 MB3.200 MB, Ziel 2.297 MB6.000 MB, Ziel 4.935 MB
2019sieht 64.417 MB, Ziel 61.037 MB3.200 MB, Ziel 2.506 MB6.000 MB, Ziel 5.112 MB
20223.277 MB, Ziel 2.617 MB3.200 MB, Ziel 2.573 MB4.096 MB, Ziel 3.433 MB
20253.277 MB, Ziel 2.721 MB3.200 MB, Ziel 2.641 MB4.096 MB, Ziel 3.618 MB

„Sieht“ ist der Speicher, den SQL Server als vorhanden meldet (physical_memory_kb), „Ziel“ das Speicherziel (committed_target_kb). 64.417 MB sind 80 Prozent des Host-Speichers.

  • 2017 und 2019 erkennen die Container-Grenze unter cgroup v2 nicht. In einem Container mit 4 GB planen sie mit 60 GB. Sobald der Puffer-Pool wächst, endet das mit einem OOM-Kill. Microsoft nennt die Unterstützung für cgroup v2 ab SQL Server 2022 CU20.
  • Ein zu hohes MSSQL_MEMORY_LIMIT_MB ist gefährlich. 2017 und 2019 übernehmen es ungeprüft. 2022 und 2025 kappen es auf die Container-Grenze, lassen dann aber keinen Kopfraum mehr für alles, was außerhalb der Engine Speicher braucht.

Was hilft: Immer beides setzen, Container-Grenze und MSSQL_MEMORY_LIMIT_MB, und dazwischen 10 bis 20 Prozent Kopfraum lassen, wie Microsoft empfiehlt. Auf 2017 und 2019 ist das Pflicht. Den OOM-Kill selbst haben wir nicht provoziert.

4 · Volumes und Rechte: Wem gehört das Datenverzeichnis?

Ab SQL Server 2019 läuft SQL Server im Container als Benutzer mssql mit der ID 10001, nicht als root. Wer ein Verzeichnis des Hosts als Datenverzeichnis einhängt, muss es diesem Benutzer zugänglich machen. Wir haben vier Varianten probiert:

Eigentümer des Verzeichnisses auf dem Host2017201920222025
root, Rechte 755startetscheitertscheitertscheitert
ID 10001, Gruppe 0, Rechte 770startetstartetstartetstartet
fremder Benutzer (4000), Rechte 700startetscheitertscheitertscheitert
root, Gruppe 0 schreibbar (770)startetstartetscheitertscheitert

SQL Server 2017 läuft als root und startet mit jedem Verzeichnis. Die Variante „Gruppe 0 schreibbar“, die Microsoft für Plattformen mit zufälligen Benutzer-IDs nennt, funktionierte nur bei 2019; dort läuft mssql in der Gruppe 0, bei 2022 und 2025 in der eigenen Gruppe 10001. Beim Scheitern endet der Container sofort, und docker logs zeigt:

ERROR: Setup FAILED copying system data file 'C:\templatedata\master.mdf' to '/var/opt/mssql/data/master.mdf':  5(Access is denied.)
ERROR: BootstrapSystemDataDirectories() failure (HRESULT 0x80070005)

Der Windows-Pfad und der Windows-Fehlercode 5 sind kein Druckfehler: SQL Server läuft unter Linux auf einer Abstraktionsschicht, die ihm Windows-Pfade zeigt.

Was hilft:

sudo install -d -o 10001 -g 0 -m 770 /srv/sql/data/mein-sql
docker run … -v /srv/sql/data/mein-sql:/var/opt/mssql/data …

5 · Images, Tags und Editionen

  • latest wandert. 2025-latest zeigte bei uns noch auf CU9, als CU10 schon als eigener Tag bereitstand; nach dem nächsten docker pull zeigt er woanders hin. Für Tests, die morgen dasselbe Ergebnis liefern sollen, gehört der CU-Stand in den Tag (zum Beispiel 2025-CU10-ubuntu-24.04) oder das Image wird über seinen Digest festgelegt.
  • Ein Update ist ein neues Image. Die Datenbanken liegen auf dem Volume; der Container wird mit dem neuen Tag neu erstellt.
  • Editionen bei 2025: MSSQL_PID=Developer ergab im Lab die Enterprise Developer Edition, obwohl die Tabelle in der Dokumentation diesen Wert nicht mehr nennt. Wer realistisch gegen Standard testen will, setzt MSSQL_PID=StandardDeveloper (meldet Standard Developer Edition).
  • Nur x86-64: Die Images laufen laut Microsoft nur auf x86-64-Hosts; Emulation über Rosetta oder QEMU, etwa auf Apple Silicon, ist nicht unterstützt.

6 · Entwicklung und CI

  • Startzeit: Bis SQL Server auf eine Abfrage antwortete, vergingen im Lab 7 bis 8 Sekunden (2017, 2019) bzw. 9 bis 14 Sekunden (2022, 2025). Ein laufender Container heißt noch nicht, dass SQL Server bereit ist; Tests sollten auf ein erfolgreiches SELECT 1 warten.
  • Das Kommandozeilenwerkzeug liegt je Version woanders: in den Images 2022 und 2025 unter /opt/mssql-tools18/bin/sqlcmd (mit -C, weil das Zertifikat selbst ausgestellt ist), in 2017 und 2019 unter /opt/mssql-tools/bin/sqlcmd.
  • Sporadische Startabstürze: Microsoft hat einen seltenen Absturz kurz nach dem Start bestätigt, der vor allem in CI-Umgebungen mit vielen gleichzeitigen Starts auffiel (mssql-docker #974); behoben laut Microsoft in 2022 CU29 und 2025 CU12. Wir haben ihn nicht beobachtet.
  • Das Errorlog liegt unter /var/opt/mssql/log/errorlog und war in allen geprüften Images einfacher Text (die Dokumentation nennt UTF-16).

Lagebild: Was sieht meine Instanz?

Die folgende Abfrage zeigt, was SQL Server von seiner Plattform hält: Betriebssystem, Edition, CPUs und Scheduler, Speicher, wichtige Einstellungen. Vergleichen Sie das Ergebnis mit den Grenzen, die Sie dem Container gegeben haben.

Abfrage: Lagebild Container

Abfrage 2: Lagebild Container · nur lesend · im PSG-Lab geprüft, Versionen im Kopf
/* PSG Stack · SQL Server unter Linux und Docker · Abfrage 2   Was sieht diese Instanz von ihrer Plattform? Betriebssystem, Edition, CPUs und Scheduler,   Speicherziel, wichtige Einstellungen, Pfade und ob der SQL Server Agent läuft.    !!! WARNUNG — bitte vor dem Ausführen lesen !!!   - Nur lesend. Die Abfrage ändert keine Daten und keine Einstellung.   - Rechte: VIEW SERVER STATE (ab SQL Server 2022 genügt VIEW SERVER PERFORMANCE STATE).   - MAXDOP 1: Jede Teilabfrage läuft seriell und belegt keine weiteren Kerne.   - Ab SQL Server 2017. Spalten, die eine Version nicht kennt, erscheinen als n/a; die Abfrage     prüft dazu, ob die Spalte existiert. Geprüft im PSG-Lab auf 2017, 2019, 2022 und 2025 in     Linux-Containern, als sa und ohne sysadmin (11.11.2026); unter Windows nicht geprüft.   - container_type_desc meldet einen Linux-Container, sofern die Version die Spalte kennt.     Vergleichen Sie cpu_count und physical_memory_mb mit den Grenzen, die Sie dem Container     gegeben haben: Eine CPU-Quote (--cpus) sieht keine Version, ein CPU-Pinning (--cpuset-cpus)     erst SQL Server 2022 und 2025; das Speicherlimit unter cgroup v2 sehen 2017 und 2019 nicht.*/SET NOCOUNT ON; DECLARE @sql nvarchar(max), @spalten nvarchar(max) = N''; /* 1 · Plattform */SET @sql = N'SELECT ' +  CASE WHEN OBJECT_ID(N'sys.dm_os_host_info') IS NULL THEN N'N''n/a'' AS host_platform, N''n/a'' AS host_distribution, N''n/a'' AS host_release'       ELSE N'h.host_platform, h.host_distribution, h.host_release' END +  N', CONVERT(nvarchar(20), SERVERPROPERTY(''ProductVersion'')) AS version,     CONVERT(nvarchar(30), SERVERPROPERTY(''ProductUpdateLevel'')) AS update_level,     CONVERT(nvarchar(60), SERVERPROPERTY(''Edition'')) AS edition   FROM ' + CASE WHEN OBJECT_ID(N'sys.dm_os_host_info') IS NULL THEN N'(SELECT 1 AS x) AS h' ELSE N'sys.dm_os_host_info AS h' END +  N' OPTION (MAXDOP 1);';EXEC sys.sp_executesql @sql; /* 2 · CPU und Speicher, wie SQL Server sie sieht */SELECT @spalten = @spalten + N', ' + CASE WHEN EXISTS (SELECT 1 FROM sys.all_columns                                                        WHERE object_id = OBJECT_ID(N'sys.dm_os_sys_info') AND name = v.n)                                         THEN N'CONVERT(nvarchar(60), i.' + v.n + N')' ELSE N'N''n/a''' END + N' AS ' + v.nFROM (VALUES (1, N'socket_count'), (2, N'cores_per_socket'), (3, N'numa_node_count'),             (4, N'sql_memory_model_desc'), (5, N'container_type_desc')) AS v(k, n)ORDER BY v.k;SET @sql = N'SELECT i.cpu_count, i.scheduler_count, i.hyperthread_ratio, i.affinity_type_desc' + @spalten + N',       i.physical_memory_kb / 1024 AS physical_memory_mb,       i.committed_target_kb / 1024 AS committed_target_mbFROM sys.dm_os_sys_info AS i OPTION (MAXDOP 1);';EXEC sys.sp_executesql @sql; SELECT COUNT(*) AS scheduler_sichtbar_onlineFROM sys.dm_os_schedulersWHERE status = N'VISIBLE ONLINE'OPTION (MAXDOP 1); /* 3 · Einstellungen, TempDB, Agent, Pfade */SELECT    (SELECT CONVERT(int, value_in_use) FROM sys.configurations WHERE name = N'max server memory (MB)') AS max_server_memory_mb,    (SELECT CONVERT(int, value_in_use) FROM sys.configurations WHERE name = N'max degree of parallelism') AS maxdop,    (SELECT CONVERT(int, value_in_use) FROM sys.configurations WHERE name = N'cost threshold for parallelism') AS cost_threshold,    (SELECT COUNT(*) FROM tempdb.sys.database_files WHERE type = 0) AS tempdb_datendateien,    CASE WHEN EXISTS (SELECT 1 FROM sys.dm_exec_sessions WHERE program_name LIKE N'SQLAgent%') THEN N'läuft' ELSE N'läuft nicht oder unsichtbar' END AS sql_server_agent,    CONVERT(nvarchar(260), SERVERPROPERTY('InstanceDefaultDataPath')) AS standard_datenpfad,    CONVERT(nvarchar(260), SERVERPROPERTY('InstanceDefaultLogPath')) AS standard_logpfad,    CONVERT(nvarchar(260), SERVERPROPERTY('ErrorLogFileName')) AS errorlogOPTION (MAXDOP 1);

Beispielausgabe

Aus dem Lab: SQL Server 2022 CU27 in einem Container mit zwei festen CPUs (--cpuset-cpus) und 4 GB Speichergrenze, Agent eingeschaltet:

Beispielausgabe
host_platform  host_distribution  host_release  version     update_level  edition
-------------  -----------------  ------------  ----------  ------------  --------------------------
Linux          Ubuntu             22.04         16.0.4295.3 CU27          Developer Edition (64-bit)

cpu_count  scheduler_count  affinity_type_desc  container_type_desc  physical_memory_mb  committed_target_mb
---------  ---------------  ------------------  -------------------  ------------------  -------------------
2          2                AUTO                LINUX CONTAINER      3277                2551

max_server_memory_mb  maxdop  tempdb_datendateien  sql_server_agent  standard_datenpfad    errorlog
--------------------  ------  -------------------  ----------------  --------------------  ---------------------------
2147483647            0       2                    läuft             /var/opt/mssql/data/  /var/opt/mssql/log/errorlog

Spalten gekürzt. So lesen Sie das: Zwei CPUs und 3.277 MB entsprechen den Container-Grenzen (80 Prozent von 4 GB); max server memory und MAXDOP stehen noch auf der Voreinstellung. Zeigt cpu_count bei Ihnen die CPU-Zahl des Hosts, obwohl der Container begrenzt ist, oder physical_memory_mb mehr als die Container-Grenze, dann trifft Sie Abschnitt 2 oder 3.

Methode und Grenzen

Gemessen am 11.11.2026 auf einer Linux-VM (Ubuntu, cgroup v2, 24 logische CPUs, 78 GB Speicher, Docker 29.8) mit den Microsoft-Images SQL Server 2017 CU31, 2019 CU32, 2022 CU27, 2025 CU9 und CU10 (Ubuntu-Varianten), Developer Edition; je Fall ein frischer Container ohne Netzwerk, je Fall ein Lauf, kleine Datenbanken. Das Herunterfahren auf 2022 und 2025 hatten wir am 21.10.2026 bereits einmal gemessen; die Ergebnisse stimmen überein. Was wir nicht selbst gemessen haben, stammt aus Microsoft Learn und dem GitHub-Repository der Images. Grenzen:

  • Neuere CU-Images als 2022 CU27 und 2025 CU10 haben wir nicht geprüft; ob die angekündigte Korrektur des Startskripts dort enthalten ist, ist offen.
  • Recovery-Dauer nach einem harten Ende, Laufzeitwirkung zu vieler Scheduler unter einer Quote und der OOM-Kill sind nicht gemessen.
  • Nur Ubuntu-Images, nur Docker auf einem Host mit cgroup v2. RHEL-Images, Podman, Kubernetes und Hosts mit cgroup v1 haben wir nicht geprüft; unter cgroup v1 kann die Speichererkennung von 2017 und 2019 anders ausfallen.
  • Zeiten sind Einzelmessungen und zeigen Größenordnungen.

Weiterlesen

  • Microsoft Learn: Quickstart „Run SQL Server Linux container images with Docker“; „Configure SQL Server container images on Docker“; „Performance best practices and configuration guidelines for SQL Server on Linux“.
  • GitHub microsoft/mssql-docker: Issues #968 (Startskript gibt SIGTERM nicht weiter), #974 (Absturz kurz nach dem Start).
  • Docker-Dokumentation: docker stop und docker run --init.
  • In dieser Reihe: Übersicht und Teil 1: Linux, Container oder Windows? mit der Prüfabfrage „Was fehlt unter Linux?“.
  • Bei PSG: Neustart hilft nur kurz (was ein Neustart in SQL Server wirklich zurücksetzt), SQL Server Locking verstehen.

Sie betreiben SQL Server in Containern?

Prüfen Sie zuerst drei Dinge: ob Ihre Container mit Exitcode 0 oder 137 enden, ob cpu_count und physical_memory_mb aus Abfrage 2 zu den Grenzen passen, die Sie gesetzt haben, und wem das Datenverzeichnis gehört. Stimmt eines davon nicht, lohnt ein zweiter Blick auf die Container-Definition, bevor das nächste Update oder der nächste Stopp ansteht.

Weitere Teile der Reihe