A complete beginner's guide to running Microsoft SQL Server on Linux using Docker. Every command explained step by step — from installation to creating your first database and connecting with a GUI tool.
Introduction
Microsoft SQL Server is one of the most popular database systems in the world — used by businesses of all sizes to store and manage data. The great news is you don't need a Windows server or an expensive license to run it. You can run it for free on your Linux server using Docker in just a few minutes.
This guide walks you through every single step, with plain English explanations of every command.
What You'll Need
- A Linux server with Docker already installed (follow our Docker installation guide if you haven't done this yet)
- SSH access to your server
- Basic familiarity with the terminal
Key Terms Explained
| Term | What it means |
|---|---|
| SQL Server | Microsoft's database management system — used to store, retrieve, and manage data |
| MSSQL | Short for Microsoft SQL Server |
| Database | An organized collection of data stored in tables (like spreadsheets) |
| Table | A structured set of data organized into rows and columns — like an Excel sheet |
| SA | "System Administrator" — the built-in admin account in SQL Server with full control |
| Port 1433 | The default network port that SQL Server listens on for connections |
| sqlcmd | Microsoft's official command line tool for running SQL commands |
| EULA | "End User License Agreement" — the terms of use you must accept to use the software |
| PID | "Product ID" — tells SQL Server which edition to run (Express, Developer, etc.) |
| Docker Volume | A storage area managed by Docker that persists your data even if the container is deleted |
| chown | "Change Owner" — a Linux command to change who owns a file or folder |
SQL Server Editions (Free Options)
You don't need to pay anything to follow this guide. Here are the free editions:
| Edition | Best For | Limits |
|---|---|---|
Express | Small apps, learning | 10GB database size limit |
Developer | Development and testing | Full features, not for production use |
For this guide we'll use Express. Change it to Developer if you need full features for testing.
Step 1: Connect to Your Server via SSH
Open your terminal and connect to your server:
ssh root@your-server-ip
Breaking this down:
ssh— Secure Shell, opens a secure remote connection to your serverroot— the admin usernameyour-server-ip— replace with your actual server IP address
Type your password when prompted and press Enter. You won't see the password as you type — that's normal.
Step 2: Create a Folder for SQL Server
Keep things organized by creating a dedicated folder:
mkdir ~/mssql && cd ~/mssql
mkdir— "make directory" — creates a new folder~/mssql— creates it in your home directory (~= home)&&— runs the next command only if the first succeedscd ~/mssql— moves you into the new folder
Step 3: Fix Folder Permissions
SQL Server 2022 runs as a non-root user inside the container (user ID 10001). We need to create the data folder and give it the correct ownership so SQL Server can write to it:
mkdir -p ./mssql-data
sudo chown -R 10001:10001 ./mssql-data
Breaking this down:
mkdir -p ./mssql-data— creates the data folder (-pmeans don't error if it already exists)sudo— run as administratorchown— "change owner" — changes the ownership of a file or folder-R— applies the change recursively to everything inside the folder10001:10001— the user ID and group ID that SQL Server runs as inside Docker./mssql-data— the folder we're changing ownership of
Why is this needed? SQL Server 2022 changed its default behavior to run as a non-root user for security reasons. If the data folder is owned by root, SQL Server can't write to it and will crash with a "Permission Denied" error.
Step 4: Create the Docker Compose File
nano docker-compose.yml
nano opens a terminal text editor. Type or paste the following:
services:
mssql:
image: mcr.microsoft.com/mssql/server:2022-latest
restart: unless-stopped
user: root
ports:
- "1433:1433"
environment:
- ACCEPT_EULA=Y
- SA_PASSWORD=YourStrongPassword123!
- MSSQL_PID=Express
volumes:
- mssql-data:/var/opt/mssql
volumes:
mssql-data:
Breaking this down:
image: mcr.microsoft.com/mssql/server:2022-latest— the official Microsoft SQL Server 2022 Docker image from Microsoft's container registryrestart: unless-stopped— automatically restarts if the server reboots (unless you manually stop it)user: root— runs the container as root to avoid permission issues on startupports: "1433:1433"— maps port 1433 on your server to port 1433 inside the container (the default SQL Server port)ACCEPT_EULA=Y— you must set this toYto accept Microsoft's license agreement, otherwise SQL Server will refuse to startSA_PASSWORD— the password for thesa(System Administrator) account. Change this to your own strong password!MSSQL_PID=Express— sets the edition to Express (free). Valid values:Express,Developer,Standard,Enterprisevolumes: mssql-data— uses a Docker-managed volume to store your databases permanently
Password Requirements: SQL Server enforces strong passwords. Your password must have at least 8 characters and include all of: an uppercase letter, a lowercase letter, a number, and a special character (like !, @, #). SQL Server will refuse to start if the password is too weak.
Save and exit nano: Press Ctrl + X, then Y to confirm, then Enter to keep the filename.
Step 5: Start SQL Server
docker compose up -d
docker compose up— starts all containers defined in your compose file-d— "detached mode" — runs in the background so your terminal stays free
SQL Server takes about 30 seconds to fully initialize. Give it a moment before the next step.
Step 6: Verify It's Running
Check the container is up:
docker ps
You should see a container called mssql-mssql-1 with status Up.
Then check the logs to confirm SQL Server started successfully:
docker compose logs
Look for this line:
SQL Server is now ready for client connections.
If you see it — SQL Server is running!
Step 7: Open the Firewall Port
sudo ufw allow 1433
ufw— "Uncomplicated Firewall" — Linux's built-in firewall toolallow 1433— opens port 1433 so external tools can connect to SQL Server
Cloud server users (AWS, DigitalOcean, Linode, etc.): You also need to open port 1433 in your cloud provider's dashboard under "Security Groups" or "Firewall" settings. This is a separate firewall from the Linux one — both need to be configured.
Step 8: Test the Connection from Inside the Container
Let's verify SQL Server is working by connecting to it directly:
docker exec -it mssql-mssql-1 /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P 'YourStrongPassword123!' -No
Breaking this down:
docker exec— runs a command inside a running container-it— "interactive terminal" — lets you type and see outputmssql-mssql-1— the name of your container (verify withdocker ps)/opt/mssql-tools18/bin/sqlcmd— the path to Microsoft's SQL command line tool inside the container-S localhost— connect to the server at localhost (inside the container)-U sa— username issa(System Administrator)-P 'YourStrongPassword123!'— your password (keep the single quotes)-No— disables SSL certificate validation, required for SQL Server 2022
You'll see a 1> prompt — you're connected! Run a quick test:
SELECT @@VERSION
GO
SELECT @@VERSION— displays the SQL Server version informationGO— sends the command to SQL Server for execution (always needed after SQL statements in sqlcmd)
Type exit to disconnect.
Step 9: Create Your First Database
Still inside sqlcmd (or reconnect using the command from Step 8), run these SQL commands:
-- Create a new database
CREATE DATABASE myapp;
GO
-- Switch to using it
USE myapp;
GO
-- Create a users table
CREATE TABLE users (
id INT PRIMARY KEY IDENTITY,
name NVARCHAR(100),
email NVARCHAR(100),
created_at DATETIME DEFAULT GETDATE()
);
GO
-- Insert a test record
INSERT INTO users (name, email) VALUES ('John Doe', 'john@example.com');
GO
-- Read the data back
SELECT * FROM users;
GO
Breaking this down:
CREATE DATABASE— creates a new databaseUSE myapp— switches to that database so following commands run inside itCREATE TABLE— creates a new table with defined columnsINT PRIMARY KEY IDENTITY— an auto-incrementing number that uniquely identifies each rowNVARCHAR(100)— a text field that supports Unicode characters, up to 100 charactersDATETIME DEFAULT GETDATE()— a date/time field that automatically saves the current timeINSERT INTO— adds a new row of dataSELECT *— retrieves all rows and columns from the table
Step 10: Connect Using a GUI Tool (Recommended)
The command line is useful but a visual tool makes working with databases much easier. Azure Data Studio is Microsoft's free, cross-platform database GUI.
Download Azure Data Studio: azure.microsoft.com/products/data-studio
Connection details:
- Server:
your-server-public-ip - Port:
1433 - Authentication type: SQL Login
- Username:
sa - Password:
YourStrongPassword123! - Trust server certificate: Enable this
Alternatively, DBeaver is another free GUI that works great with SQL Server and many other databases: dbeaver.io
Troubleshooting Common Issues
Error: Permission Denied / .system could not be created
This is a folder permissions issue. Run:
docker compose down
mkdir -p ./mssql-data
sudo chown -R 10001:10001 ./mssql-data
docker compose up -d
Error: The provided PID is invalid
Your MSSQL_PID value is wrong. Make sure it's exactly Express or Developer — no extra characters, correct capitalization.
Error: Password validation failed
Your SA_PASSWORD doesn't meet the requirements. It must include uppercase, lowercase, a number, and a special character.
Can't connect from outside the server
- Check Linux firewall:
sudo ufw status— port 1433 should show as ALLOW - Check your cloud provider's security group has port 1433 open
- Make sure the container is running:
docker ps
Container name not found
Run docker ps and copy the exact container name shown — it may differ slightly.
Connection refused from GUI tool
Make sure "Trust server certificate" is enabled in your connection settings.
Useful Commands Reference
# Start SQL Server
cd ~/mssql && docker compose up -d
# Stop SQL Server
cd ~/mssql && docker compose down
# Restart SQL Server
cd ~/mssql && docker compose restart
# View logs
cd ~/mssql && docker compose logs
# Connect via terminal
docker exec -it mssql-mssql-1 /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P 'YourPassword' -No
# Check running containers
docker ps
# Check firewall status
sudo ufw status
What's Next?
Now that SQL Server is running, here are some things you can explore:
- Connect your app — link SQL Server to a Node.js, .NET, Python, or PHP application
- Create more databases — one database per project is a common practice
- Set up regular backups — use SQL Server's built-in backup commands to protect your data
- Create additional users — avoid using the
saaccount for your apps; create a dedicated user with limited permissions instead - Explore SQL Server Management Studio (SSMS) — Microsoft's full-featured Windows GUI for managing SQL Server
Summary
Here's the full process in a nutshell:
- Connect via SSH:
ssh root@your-ip - Create the project folder:
mkdir ~/mssql && cd ~/mssql - Fix folder permissions with
chown - Write your
docker-compose.ymlwith your SA password and edition - Launch:
docker compose up -d - Confirm it's ready in the logs
- Open port 1433 in the firewall
- Connect with
sqlcmdand run a test query - Create a database and table
- Connect using Azure Data Studio or DBeaver
You now have Microsoft SQL Server running on your Linux server inside Docker — completely free and ready to use!