Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

dp-800-sql-ai-dev-local-lab

Local development lab for SQL Server 2025 Express calling Ollama over HTTPS through an internal nginx reverse proxy.

The stack is designed for DP-800 preparation on Windows 10/11 with WSL 2, Docker Desktop, and a NVIDIA GPU, but it is started with plain Docker Compose so the runtime commands are portable.

Architecture

SQL client on host
  -> localhost,1433
  -> sql-server

SQL Server engine inside container
  -> https://localhost:11434/*
  -> nginx TLS proxy
  -> http://localhost:11435/*
  -> Ollama

The containers share the sql-server network namespace:

  • sql-server publishes only 1433 to the host.
  • nginx listens internally on https://localhost:11434.
  • ollama listens internally on http://localhost:11435.
  • nginx transparently proxies every path to Ollama.

This means SQL Server calls the normal Ollama API through HTTPS:

https://localhost:11434/api/tags
https://localhost:11434/api/embed
https://localhost:11434/v1/completions

Contents

.env.example
certs/
docker-compose.yml
nginx/nginx.conf
sql/
sqlserver.Dockerfile

The certificates under certs/ are part of the lab and are expected to be present in the repository.

Reference Environment

The lab was tested on this machine. These values are not minimum requirements; they are provided as a practical reference point.

Computer: HP ZBook
OS: Windows 10 22H2, build 19045.7417, 64-bit
CPU: 11th Gen Intel Core i7-11800H @ 2.30 GHz
RAM: 32 GB
GPU: NVIDIA T1200 Laptop GPU
VRAM: 4 GB
NVIDIA driver: 596.72 Quadro RTX Desktop/Notebook DCH WHQL
Docker Desktop: 4.79.0
WSL: WSL 2, Ubuntu 24.04.4 LTS
SQL Server image: mcr.microsoft.com/mssql/server:2025-latest
SQL Server version: Microsoft SQL Server 2025 (RTM-CU6) 17.0.4055.5, Express Edition, Linux
Default models: nomic-embed-text, gemma3:1b

Measured Docker disk usage with the default models:

Docker images:
  sql-server-2025-express: 2.52 GB
  ollama/ollama: 8.03 GB
  nginx:1.27-alpine: 74.5 MB
  Approximate lab image total: 10.6 GB

Docker volumes:
  dp-800-sql-server-data: 74.5 MB
  dp-800-ollama-data: 1.0 GB
  Approximate lab volume total: 1.1 GB

Approximate lab total: 11.7 GB

Docker build cache, unrelated images, unrelated volumes, and Docker Desktop internal services are not included in the approximate lab total.

Prerequisites

Windows 10/11 + WSL 2 + Docker Desktop

The commands in this section target Ubuntu/Debian WSL distributions, which are the recommended option for this lab. If you use a different WSL distribution, follow the official NVIDIA Container Toolkit instructions for that platform.

Install a recent NVIDIA Windows driver with WSL support. The CUDA driver layer for WSL comes from Windows; do not install a Linux NVIDIA kernel driver inside WSL.

Validate the GPU from Windows:

nvidia-smi

Validate WSL and make sure the Docker-integrated distribution is WSL 2:

wsl --version
wsl --status
wsl -l -v

If needed:

wsl --set-version Ubuntu 2
wsl --update

Before configuring Docker Desktop, open the Ubuntu/Debian WSL distribution and install NVIDIA Container Toolkit there.

Configure the NVIDIA apt repository in WSL:

curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey \
  | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg

curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list \
  | sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' \
  | sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list

Install the toolkit in WSL:

sudo apt-get update
sudo apt-get install -y nvidia-container-toolkit

Then configure Docker Desktop, not the WSL Docker daemon. For Docker Desktop on Windows, do not use nvidia-ctk runtime configure inside WSL to configure the runtime; update Docker Desktop's Windows daemon configuration manually instead.

  • Use the WSL 2 based engine.
  • Enable WSL integration for the Ubuntu/Debian distribution.
  • Use Linux containers.

Update Docker Desktop's Windows daemon runtime file manually:

%USERPROFILE%\.docker\windows-daemon.json

Example content:

{
  "experimental": false,
  "runtimes": {
    "nvidia": {
      "args": null,
      "path": "nvidia-container-runtime"
    }
  }
}

Restart WSL and Docker Desktop:

wsl --shutdown

Then quit and reopen Docker Desktop.

Validate Docker and GPU access:

docker version
docker run --rm hello-world
docker run --rm --gpus=all nvidia/cuda:13.0.0-base-ubuntu24.04 nvidia-smi

Native Linux Host: Ubuntu/Debian

Install the NVIDIA driver for your Linux distribution first. Then install NVIDIA Container Toolkit.

Configure the NVIDIA apt repository:

curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey \
  | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg

curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list \
  | sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' \
  | sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list

Install the toolkit:

sudo apt-get update
sudo apt-get install -y nvidia-container-toolkit

Configure the Docker runtime:

sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker

If your Linux environment does not use systemd, restart Docker with the service command available in your distribution:

sudo service docker restart

Validate Docker GPU access:

docker version
docker run --rm hello-world
docker run --rm --gpus=all nvidia/cuda:13.0.0-base-ubuntu24.04 nvidia-smi

Other Linux Distributions

For distributions other than Ubuntu or Debian, follow the official NVIDIA Container Toolkit guide for your platform.

References:

Configuration

Create .env from the example:

cp .env.example .env

On PowerShell:

Copy-Item .env.example .env

Edit .env and set a strong SQL Server password:

MSSQL_SA_PASSWORD=Change_this_Strong_Password_123!
OLLAMA_MODELS=nomic-embed-text gemma3:1b

OLLAMA_MODELS is used by the ollama-models one-shot Compose service to pull the models into the shared Ollama volume.

Start

From this directory:

docker compose up -d --build

Watch model downloads:

docker logs -f ollama-models

Check containers:

docker ps

Expected host port exposure:

sql-server   0.0.0.0:1433->1433/tcp
nginx        no host port
ollama       no host port

Stop

Stop the stack without deleting SQL data or downloaded models:

docker compose down

Stop the stack and delete SQL Server and Ollama volumes:

docker compose down --volumes

Validation

Validate nginx -> Ollama from inside the SQL Server container:

docker exec sql-server curl -v https://localhost:11434/api/tags

Expected result:

HTTP/1.1 200 OK

At this point, nginx logs should show curl as the caller:

docker logs nginx

Example:

127.0.0.1 - - "GET /api/tags HTTP/1.1" 200 ... "curl/8.5.0"

After running the T-SQL validation in sql/00-setup-database-and-test-tags.sql, nginx logs should show SQL Server as the caller:

127.0.0.1 - - "GET /api/tags HTTP/1.1" 200 ... "Express Edition (64-bit)/17.0.4055.5"

SQL Lab Scripts

Connect from SSMS, Azure Data Studio, or sqlcmd:

Server: localhost,1433
Login: sa
Password: value from MSSQL_SA_PASSWORD
Trust server certificate: enabled if your SQL client requires it

Run the scripts under sql/ in order:

sql/00-setup-database-and-test-tags.sql
sql/01-completions.sql
sql/02-embeddings.sql
sql/03-chunking-with-embeddings.sql
sql/04-vector-distance-search.sql
sql/05-vector-table-diskann-index.sql
sql/06-rag-with-vector-context.sql

The flow is:

  • 00 creates the [DP-800] database, enables sp_invoke_external_rest_endpoint, enables SQL Server 2025 preview features for vector indexes, creates the database master key if needed, and validates https://localhost:11434/api/tags.
  • 01 calls Ollama's OpenAI-compatible completions endpoint.
  • 02 creates the OllamaNomicEmbeddings external model and runs AI_GENERATE_EMBEDDINGS.
  • 03 creates dbo.DocumentChunks, runs AI_GENERATE_CHUNKS, and stores chunk embeddings.
  • 04 runs exact semantic search with VECTOR_DISTANCE.
  • 05 creates dbo.VectorDocuments, loads 100 lab rows from the chunk table, builds a DiskANN vector index, and compares exact KNN with ANN search.
  • 06 runs a local RAG flow: retrieve relevant chunks from SQL Server, build a grounded prompt, and call Ollama completions.

DiskANN vector indexes require at least 100 rows with non-null vectors. The 05 script expands the small demo chunk table into 100 lab rows before creating the index.

Compatibility note for ANN syntax: current documentation may mention SELECT TOP (...) WITH APPROXIMATE for newer vector index syntax. On the tested SQL Server 2025 RTM-CU6 build, that syntax fails with:

Incorrect syntax near 'APPROXIMATE'.

For this build, use the earlier VECTOR_SEARCH syntax with TOP_N:

FROM VECTOR_SEARCH
(
    TABLE = dbo.VectorDocuments AS v,
    COLUMN = embedding,
    SIMILAR_TO = @question_embedding,
    METRIC = 'cosine',
    TOP_N = 3
) AS s

Conceptually, both forms request an approximate nearest-neighbor search. The lab uses TOP_N because it is the syntax supported by the tested SQL Server 2025 container image.

If you run the lab with a non-admin SQL login, grant permission in the database where you run the lab:

GRANT EXECUTE ANY EXTERNAL ENDPOINT TO [USER];
GO

First Request Latency

The first call to an embeddings or completions endpoint can take noticeably longer than later calls. Ollama may need to load the selected model into memory, initialize GPU/CPU execution, and perform the first inference pass.

The delay depends on the host hardware, available GPU memory, current system load, and the selected model size. Embeddings models usually warm up faster; completions models can take a few minutes on the first request, especially on laptops or GPUs with limited VRAM.

If the first request is slow but nginx logs show activity and the container is healthy, wait before assuming the request failed. Subsequent calls should be much faster while the model remains loaded.

Certificates

The lab uses a local self-signed CA and localhost server certificate committed under certs/.

nginx uses:

certs/localhost.pem
certs/localhost.key

The SQL Server image installs:

certs/localhost.ca.crt
certs/localhost.crt

into the Linux trust store and also copies them to:

/var/opt/mssql/security/ca-certificates

owned by mssql:mssql.

Important note for SQL Server on Linux: installing the CA only in the standard Linux trust store is not enough for SQL Server's internal HTTP/REST clients. The image still adds the certificates to the Linux store with /usr/local/share/ca-certificates and update-ca-certificates, but SQL Server uses SQLPAL for certificate validation.

For SQLPAL, additional trusted CAs must be available under:

/var/opt/mssql/security/ca-certificates

SQL Server reads certificates from that directory during startup and adds them to the PAL trust store. Microsoft documents this behavior for SQL Server on Linux and also documents a limit of 50 files in that location.

The certificates are for local lab use only.

Docker Objects

Compose project: dp-800
Image: sql-server-2025-express
Container: sql-server
Container: nginx
Container: ollama
Container: ollama-models
Network: dp-800-network
Volume: dp-800-sql-server-data
Volume: dp-800-ollama-data

Troubleshooting

Check model pull logs:

docker logs ollama-models

Check nginx logs:

docker logs nginx

Check Ollama logs:

docker logs ollama

Check SQL Server logs:

docker logs sql-server

Check GPU use:

docker exec ollama nvidia-smi

If the CUDA test hangs or leaves a container in Created:

docker ps -a
docker rm <container-id>

If port 1433 is already in use, change the host port:

ports:
  - "51433:1433"

Then connect to:

localhost,51433

If external REST endpoints are disabled, SQL Server can return errors like:

'sp_invoke_external_rest_endpoint' is disabled on this instance of SQL Server.
Use sp_configure 'external rest endpoint enabled' to enable it.

or:

'ai_generate_embeddings' is disabled on this instance of SQL Server.
Use sp_configure 'external rest endpoint enabled' to enable it.

Enable it with the SQL setup commands from sql/00-setup-database-and-test-tags.sql.

Security Notes

This lab is local-only:

  • SQL Server is the only published service.
  • nginx and Ollama are not published to the host.
  • nginx terminates HTTPS on localhost:11434 inside the shared container namespace.
  • Ollama stays behind nginx on localhost:11435.
  • Certificates are self-signed and intended only for this local lab.
  • Do not reuse this certificate material in production.

About

SQL Server 2025 local AI lab for DP-800: Docker Compose stack with Ollama, nginx HTTPS, NVIDIA GPU support, embeddings, vector search, DiskANN, and RAG examples.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages