In this guide, you will run SQL Server on Docker and leave it ready for exercises, testing, and queries.
At the end you will have:
- SQL Server listening on
localhost:1433. - A
pw0database. - A
sensortable. - Sample records loaded from a file.
If you want to jump straight to the download, go to Download.
Folder structure
| |
What each file is for:
Dockerfile: builds the image that Docker Compose uses to run the service.docker-compose.yml: defines service, ports, env vars, and healthcheck.mssql.env: required environment variables for SQL Server startup.setup/entrypoint.sh: main container startup script.setup/configure-db.sh: waits for SQL Server and then runs SQL scripts.scripts/database.sql: creates thepw0database.scripts/table.sql: creates thesensortable and loads data.sample-data/room-climate.csv: sample dataset.
Full startup flow
- Docker Compose uses
docker-compose.ymlto start the service. - During startup, Compose builds the image from
Dockerfile. - When the container starts,
entrypoint.shruns. entrypoint.shlaunchesconfigure-db.shin background, then starts SQL Server.configure-db.shwaits until the engine is ready.- Once ready, it runs
database.sqland thentable.sql. - Final result: database and table created, data loaded.
File 1: docker-compose.yml (service and startup)
docker-compose.yml:
| |
Minimum important parts:
container_name: container branding (pw0-sql-server).build.context: .: uses the localDockerfile.ports: exposes SQL Server onlocalhost:1433.env_file: loads env vars frommssql.env.healthcheck: verifies SQL Server is responding.
File 2: Dockerfile (image build)
| |
Quick line-by-line read (execution order):
FROM ...: starts from an image that already contains SQL Server.RUN mkdir -p /usr/config: creates a folder for scripts and data.WORKDIR /usr/config: sets the working directory.COPY . /usr/config: copies the full project content into the container.RUN chmod +x ...: gives execution permission to.shscripts.ENTRYPOINT [...]: defines the startup command.
File 3: mssql.env (environment variables)
| |
What each variable does:
ACCEPT_EULA="Y": accepts SQL Server license terms.MSSQL_SA_PASSWORD="...": sets thesaadmin password.MSSQL_PID="Developer": selects Developer edition.
File 4: entrypoint.sh (startup orchestration)
| |
Why this order:
configure-db.sh &: starts the init process in background.sqlservr: starts SQL Server as the main container process.&lets both run in parallel.
File 5: configure-db.sh (wait + SQL execution)
| |
This is the key startup step:
- Waits up to 60 seconds for SQL Server readiness.
- Runs
database.sqlfirst (database must exist before table creation). - Uses
&&sotable.sqlonly runs ifdatabase.sqlsucceeds. - Prevents partial initialization on failures.
File 6: database.sql (database creation)
| |
This script:
- Runs from
master. - Checks whether
pw0already exists. - Creates
pw0only when missing.
File 7: table.sql (table + initial load)
| |
This script:
- Selects
pw0. - Creates
sensoronly if missing. - Loads CSV rows when the table is empty.
Start the stack (step-by-step or zip)
From the folder that contains docker-compose.yml:
| |
This command applies in both cases:
- If you followed the step-by-step setup and created files manually.
- If you downloaded the
.zipand started from that project folder.
Load your own data
Recommended formats in this setup:
CSV: easiest option withBULK INSERT.- Delimited
TXT: also valid with the right delimiter. Excel (.xlsx): export to CSV first.
What to change
- Put your file in
sample-data/(for examplemy-data.csv). - Update
CREATE TABLEcolumns and types inscripts/table.sql. - Update the
BULK INSERTfile path:
| |
- If your delimiter is not comma, change
FIELDTERMINATOR. - If your file has no header row, use
FIRSTROW = 1.
Example for semicolon-separated files:
| |
Quick verification
Step 1: open sqlcmd
| |
Step 2: check database
| |
Expected output (example):
| |
Step 3: check loaded row count
| |
Expected output (example):
| |
Step 4: check sample rows
| |
Stop and remove the stack
When you finish:
| |
This stops and removes the stack containers.
Download
If you do not want to copy files manually, download the full stack (optional):