Skip to main content

Command Palette

Search for a command to run...

Mastering SQL Server in Containers: 2026 Deep Dive

From Docker pull to production persistence—everything you need to know about the modern SQL Server lifecycle.

Updated
Mastering SQL Server in Containers: 2026 Deep Dive
S

Computer Science enthusiast, just getting started with open source and soon will land on a remote job.

It’s 2026, and if you're still manually installing SQL Server on your local machine, you’re essentially choosing to carry a heavy backpack when you have a perfectly good hoverboard right there.

Containerizing SQL Server isn't just a "DevOps thing" anymore; it’s the gold standard for consistency, speed, and keeping your host OS clean. Whether you're using Docker, Podman, or Kubernetes, here is your deep-dive guide into mastering SQL Server in a containerized world.

Why Containers? (The "Why" in 2026)

According to recent industry shifts, nearly 90% of organizations have moved to containerized production workloads. For a database like SQL Server, containers solve the "it works on my machine" problem by:

  • Isolation: No more registry bloat or conflicting DLLs on your Windows/Linux host.

  • Version Parity: Run SQL Server 2019, 2022, and 2025 side-by-side without them ever knowing the others exist.

  • Ephemerality: Messed up a table? Kill the container and spin up a fresh one in 5 seconds.


Step 1: Pulling the Latest Image

Microsoft hosts all official images on the Microsoft Container Registry (MCR). While Docker Hub exists, MCR is the source of truth for the newest SQL Server 2025 images.

Open your terminal and pull the latest image:

Bash

docker pull mcr.microsoft.com/mssql/server:2025-latest

Pro Tip: If you're on a security-hardened Linux distro, you might prefer the Red Hat Universal Base Image (UBI) version: mcr.microsoft.com/mssql/rhel/server:2025-latest.


Step 2: The "Golden Command"

To get a container running, you need three things: an accepted EULA, a strong password, and a port mapping.

Bash

docker run -e "ACCEPT_EULA=Y" \
           -e "MSSQL_SA_PASSWORD=Your_Strong_P@ssw0rd!" \
           -p 1433:1433 \
           --name sql2025 \
           -d mcr.microsoft.com/mssql/server:2025-latest

Breaking down the flags:

  • -e "ACCEPT_EULA=Y": You agree to the terms (mandatory).

  • -e "MSSQL_SA_PASSWORD=...": Must be at least 8 characters with 3 of the 4 complexity requirements (SQL Server is picky!).

  • -p 1433:1433: Maps the host’s port 1433 to the container’s port 1433.

  • -d: Runs in detached mode (background).


Step 3: Persistence is Key (Volumes)

By default, containers are stateless. If you delete the container, your data goes to the digital void. To keep your databases safe, you must use Docker Volumes.

Bash

docker run -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=Strong_Pass!" \
   -v mssql_data:/var/opt/mssql \
   -p 1433:1433 -d mcr.microsoft.com/mssql/server:2025-latest

By mapping /var/opt/mssql to a volume named mssql_data, your .mdf and .ldf files survive container restarts and deletions.


The Pro Move: Automating with Docker Compose

While the manual docker run command is great for a quick test, real-world development requires Infrastructure as Code. Instead of remembering long strings of environment variables every time you want to start your server, you can use Docker Compose.

By saving your configuration in a .yml file, you ensure that your database environment is identical every time you—or a teammate—spin it up.

The docker-compose.yml Template

Create a new file in your project folder named docker-compose.yml and paste the following:

YAML

services:
  sql-server:
    image: mcr.microsoft.com/mssql/server:2025-latest
    container_name: mssql_2025_dev
    restart: always
    environment:
      - ACCEPT_EULA=Y
      - MSSQL_SA_PASSWORD=Your_Strong_P@ssw0rd!
      - MSSQL_PID=Developer 
    ports:
      - "1433:1433"
    volumes:
      - mssql_data:/var/opt/mssql
    healthcheck:
      test: ["CMD-SHELL", "/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P 'Your_Strong_P@ssw0rd!' -Q 'SELECT 1' -b"]
      interval: 10s
      timeout: 3s
      retries: 10

volumes:
  mssql_data:

Why this configuration wins:

  • Healthchecks: This setup doesn't just start the container; it actively checks if the SQL engine is actually ready to receive queries.

  • Automatic Restarts: If your computer reboots or Docker crashes, the restart: always flag ensures your database comes back online automatically.

  • Named Volumes: By using mssql_data, your databases are stored safely outside the container. You can delete the container, upgrade the image, or prune your system without losing a single row of data.

Quick Start: Once the file is saved, simply run docker compose up -d in your terminal. Docker will handle the rest.


Best Practices for 2026

1. Resource Limits

SQL Server is a "memory hog" by design—it will try to claim as much RAM as it sees. In a container, you should cap this to prevent the host from freezing.

  • Memory: At least 2GB is required, but 4GB is the sweet spot for dev.

  • Command: Use the --memory="4g" flag in your docker run.

2. Docker vs. Podman

In 2026, many developers are switching to Podman for its daemonless and rootless architecture.

  • Docker: Better for Mac (M1/M2/M3/M4) users because of its superior Rosetta 2 integration for x86 emulation.

  • Podman: Better for Linux production environments due to higher security (no root daemon required).

3. Change the Port

To avoid conflicts with a local SQL instance, map to a different host port:

  • -p 14033:1433 (Connect via localhost,14033)

Connecting via SSMS

Now that your container is humming along in the background, you need to actually talk to it. While Azure Data Studio is great for cross-platform work, many of us still rely on the heavy-duty power of SQL Server Management Studio (SSMS) 22.

Connecting to a container isn't quite the same as connecting to a local Windows service. Follow these steps to avoid the dreaded "Connection Refused" error:

1. The Connection String

When you open the Connect to Server dialog, use the following:

  • Server name: localhost,1433 (Note the comma—SQL Server uses commas for ports, not colons).

  • Authentication: Change this to SQL Server Authentication.

  • Login: sa

  • Password: The strong password you defined in your docker run command.

2. The "Encryption" Gotcha

Since SSMS 20, Microsoft has moved to an "Encryption Mandatory" stance. Because your SQL Server container uses a self-signed certificate by default, your connection will fail with a "Certificate chain not trusted" error unless you do this:

  1. Click the Options >> button at the bottom of the connection window.

  2. Go to the Connection Properties tab.

  3. Check the box that says Trust server certificate.

  4. (Optional) Ensure Encrypt is set to Mandatory or Strict if you're working with SQL Server 2025.

3. Troubleshooting Common Connection Issues

If you still can't connect, check these three things:

  • Is the container running? Run docker ps to verify the status is "Up".

  • Is the port mapped? Ensure you didn't forget the -p 1433:1433 flag.

  • Firewall: On some corporate machines, you may need to allow Docker Desktop to communicate through the Windows Firewall on port 1433.


The Verdict: A Complete Modern Workflow

Running SQL Server in containers isn't just about avoiding a messy installation—it’s about total environment control. By combining the portability of Docker with the familiar power of SSMS, you’ve effectively decoupled your database from your hardware.

You now have a setup that is:

  • Disposable: Messed up a schema? Kill it and start over.

  • Portable: Share your setup with a teammate via a single command.

  • Scalable: Move from your laptop to a production Kubernetes cluster with zero changes to your database logic.

The "old way" of manual installs is officially a legacy move. Welcome to the future of data management.


Final Tip for the Road

Before you close your terminal, remember that containerized SQL Server is only as good as its backup strategy. Always ensure your volumes are mapped to a secure location, and you'll never have to worry about "losing everything" during a Docker update again.