InletDownload

Connect · Docker

Connect to SQL Server in Docker from your Mac

Run mcr.microsoft.com/mssql/server with ACCEPT_EULA=Y and a strong MSSQL_SA_PASSWORD, publish port 1433, and connect to 127.0.0.1 as sa. On Apple silicon the image runs under Rosetta, and its certificate is self-signed: encrypt without checking it (sqlcmd -C).

Updated 9 October 2026

What you need

  • Docker on your Mac: Docker Desktop or OrbStack.
  • At least 2 GB of memory for the container and about 2 GB of disk. That’s Microsoft’s minimum; the images take about 1.7 GB on disk, and a new SQL Server 2022 container used about 1.1 GB of memory once it had started.
  • On Apple silicon, Rosetta. The SQL Server images are built for x86-64 only. Docker Desktop runs them with Rosetta when Use Rosetta for x86_64/amd64 emulation on Apple Silicon is on (Settings › General; it needs the Apple Virtualization framework). OrbStack uses Rosetta for Intel images without any setting.

A container started like this one is ready in a few seconds:

docker run --name sqlserver --platform linux/amd64 \
  -e ACCEPT_EULA=Y -e 'MSSQL_SA_PASSWORD=<strong-password>' \
  -p 1433:1433 -v sqlserver-data:/var/opt/mssql \
  -d mcr.microsoft.com/mssql/server:2022-latest

For SQL Server 2025, use mcr.microsoft.com/mssql/server:2025-latest.

  • ACCEPT_EULA=Y accepts the licence. Microsoft lists it as required.
  • MSSQL_SA_PASSWORD sets the password of sa, the built-in administrator. Put it in single quotes so your shell leaves ! and $ alone.
  • MSSQL_PID picks the edition. Both images default to developer, the free edition for development and testing. Express selects the free Express edition. On SQL Server 2025, Developer reports itself as Enterprise Developer Edition; 2025 also has StandardDeveloper.
  • --platform linux/amd64 says you want the Intel image on purpose. Without it, Docker prints WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested and runs it anyway.
  • -v sqlserver-data:/var/opt/mssql keeps the databases in a named volume. Without a volume, removing the container deletes them.

Rosetta works, but Microsoft doesn’t support it. Microsoft supports the images only on x86-64 hosts and says emulation such as Rosetta 2 isn’t tested or supported. The containers we tested this page with run that way: SQL Server 2019, 2022 and 2025 under OrbStack on Apple silicon, where docker image inspect … --format '{{.Architecture}}' prints amd64 and uname -m inside the container prints x86_64.

Azure SQL Edge is no longer an option. It used to be the way to run SQL Server’s engine natively on ARM. Microsoft retired it on 30 September 2025, and it no longer supports ARM64.

Find your connection details

SettingValue
Host127.0.0.1 (or localhost)
Portthe host side of -p (1433 in -p 1433:1433)
Usersa, or a login you create (below)
Passwordyour MSSQL_SA_PASSWORD
Databasemaster until you create your own

The sa password must pass SQL Server’s password policy: at least 8 characters, from at least three of uppercase letters, lowercase letters, digits and symbols, and not containing the account name. If it doesn’t, the container starts, fails to set the password and stops. We started a temporary SQL Server 2022 container (16.0.4295.3) with MSSQL_SA_PASSWORD=password; 14 seconds later it had stopped, and docker logs ended with:

2026-10-09 15:00:52.08 spid41s     ERROR: Unable to set system administrator password: Password validation failed. The password does not meet SQL Server password policy requirements because it is not complex enough. The password must be at least 8 characters long and contain characters from three of the following four sets: Uppercase letters, Lowercase letters, Base 10 digits, and Symbols..
2026-10-09 15:00:52.09 spid41s     An error occurred during server setup. See previous errors for more information.

With a strong password, a new container was ready in 11 seconds. It’s ready when docker logs sqlserver shows:

SQL Server is now ready for client connections. This is an informational message; no user action is required.

Create a database and a login for your app rather than working as sa. In the container’s sqlcmd (see below), as sa:

CREATE DATABASE app;
GO
CREATE LOGIN app WITH PASSWORD = '<app-password>', DEFAULT_DATABASE = app;
GO
USE app;
CREATE USER app FOR LOGIN app;
ALTER ROLE db_owner ADD MEMBER app;
GO

A login signs in to the server; the user maps it into one database. Signed in as app with -d app, SELECT SUSER_NAME(), USER_NAME(), DB_NAME() returned app app app. Logins get the same password policy as sa, and the rule about the account name catches people out: SQL Server 2022 refused CREATE LOGIN seo_probe WITH PASSWORD = 'Q7-seo_probe-x9', which has all four kinds of character, with the same “not complex enough” message:

Msg 33064, Level 16, State 2, Server e8a1529753be, Line 1
Password validation failed. The password does not meet SQL Server password policy requirements because it is not complex enough. The password must be at least 8 characters long and contain characters from three of the following four sets: Uppercase letters, Lowercase letters, Base 10 digits, and Symbols.

A password under 8 characters gets error 33062 instead, …because it is too short.

The 2022 and 2025 images can also do this at first start: Microsoft documents MSSQL_DB, MSSQL_USER and MSSQL_PASSWORD. In the images we have (2022 CU27, 2025 CU9), the image’s setup script creates the database, a login and a user with CONTROL on that database, only when the data directory is empty, and only if MSSQL_USER and MSSQL_PASSWORD are set together. The 2019 image has no such script. We read the script rather than ran it.

The server’s name is the container ID (Server name is 'e8a1529753be' in the log) unless you add --hostname, for example --hostname sqlserver.

Connection string

sqlserver://sa:<password>@127.0.0.1:1433?database=master&encrypt=true&TrustServerCertificate=true

The same in ADO.NET form:

Server=tcp:127.0.0.1,1433;Initial Catalog=app;User ID=app;Password=<app-password>;Encrypt=True;TrustServerCertificate=True;

Note the comma before the port in ADO.NET strings and sqlcmd -S. More forms in SQL Server connection strings, and special characters in passwords.

TLS

The container encrypts connections with a certificate it makes for itself at start. Its log says A self-generated certificate was successfully loaded for encryption. No one can verify that certificate, so a client that checks certificates refuses it. sqlcmd 18 encrypts and checks by default, and fails:

Sqlcmd: Error: Microsoft ODBC Driver 18 for SQL Server : SSL Provider: [error:0A000086:SSL routines::certificate verify failed:self-signed certificate].
Sqlcmd: Error: Microsoft ODBC Driver 18 for SQL Server : Client unable to establish connection. For solutions related to encryption errors, see https://go.microsoft.com/fwlink/?linkid=2226722.

Add -C (trust the server certificate, TrustServerCertificate=True in a connection string). The connection is still encrypted: sys.dm_exec_connections showed encrypt_option TRUE. With -No (encryption optional) it showed FALSE. For a container on your own Mac, encrypting without checking is fine.

Leave strict encryption off. Strict encryption (TDS 8.0, Encrypt=strict) needs a certificate configured on the server, and a self-generated one doesn’t count. We tried it against the SQL Server 2022 container; the client saw TCP Provider: Error code 0x2746 (the connection was reset) and the server logged:

Error: 17821, Severity: 20, State: 1.
A valid TLS certificate is not configured to accept strict (TDS 8.0 and above) connections. The connection has been closed.

The 2022 image allows TLS 1.0 to 1.2; the 2025 image adds TLS 1.3 (both say so in their logs at start).

Connect with Inlet

  1. Choose New Connection, pick SQL Server, and enter 127.0.0.1, the published port, sa (or your login), the password and the database. Or paste a sqlserver:// URL or an ADO.NET string and Inlet fills in the form. Inlet has its own SQL Server driver, so there’s no ODBC driver or FreeTDS to install.
  2. Under encryption, choose to encrypt without checking the certificate, since the container’s is self-signed. If you ask Inlet to verify it, the connection fails with “The server’s certificate couldn’t be verified: self-signed certificate”. Leave strict encryption (TDS 8.0) off, as above.
  3. Save the password in the Keychain, or have Inlet ask every time.
  4. Tag the connection local (or development).

Connect from the command line

The image includes sqlcmd (the ODBC version, 18.6 in these images), so you don’t need one on your Mac:

docker exec -it sqlserver /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -C

Leave out -P and sqlcmd asks for the password (Password:), which keeps it out of your shell history. Add -d app to start in your database. Older images had the tools in /opt/mssql-tools/bin; the 2019, 2022 and 2025 images here have only /opt/mssql-tools18.

On your Mac, Microsoft’s Go-based sqlcmd (go-sqlcmd) installs with Homebrew: brew install sqlcmd. Give the host and port with a comma:

sqlcmd -S 127.0.0.1,1433 -U sa

Microsoft documents that go-sqlcmd, unlike the ODBC version, doesn’t check the server certificate unless you pass -N, so it connects to the container as it is. It can also create a SQL Server container for you (sqlcmd create mssql --tag 2022-latest --hostname sql1 --name sql1 --port 1433 --accept-eula). We describe go-sqlcmd from Microsoft’s documentation; we didn’t install it for this page.

Troubleshooting

  • The container stops seconds after docker run. Read docker logs sqlserver. A weak MSSQL_SA_PASSWORD gives ERROR: Unable to set system administrator password (above). Give the container at least 2 GB of memory.

  • Certificate verify failed: self-signed certificate: the client checks the certificate, and the container’s can’t be checked. Use -C or TrustServerCertificate=True, or encrypt without checking in Inlet.

  • Login failed for user: the client only ever says Login failed for user 'app'. The reason is in the server’s log, which for a container is docker logs:

    Login failed for user 'app'. Reason: Password did not match that for the login provided. [CLIENT: 192.168.215.2]
    Login failed for user 'app'. Reason: Could not find a login matching the name provided. [CLIENT: 192.168.215.2]
    
  • Cannot open database “app” requested by the login: the database doesn’t exist yet, or is misspelled. sqlcmd printed Cannot open database "nosuch" requested by the login. The login failed., and the log Reason: Failed to open the explicitly specified database 'nosuch'. If a login’s default database has no user for it, you get Cannot open user default database. Login failed.

  • A network-related or instance-specific error: nothing answered on that port. The container isn’t running, the port isn’t published, or it’s still starting. Against a port with nothing behind it, sqlcmd printed:

    Sqlcmd: Error: Microsoft ODBC Driver 18 for SQL Server : Login timeout expired.
    Sqlcmd: Error: Microsoft ODBC Driver 18 for SQL Server : TCP Provider: Error code 0x2749.
    Sqlcmd: Error: Microsoft ODBC Driver 18 for SQL Server : A network-related or instance-specific error has occurred while establishing a connection to host.docker.internal,14398. Server is not found or not accessible. Check if instance name is correct and if SQL Server is configured to allow remote connections. For more information see SQL Server Books Online..
    

    Inlet says Couldn’t connect to 127.0.0.1:1433: Connection refused.

  • Connection string is not valid [87]: you wrote host:port. SQL Server tools want a comma: 127.0.0.1,1433.

  • port is already allocated from docker run: something else already publishes that host port. Publish another, such as -p 14330:1433, and connect to that.

Related

Sources