Restoring SQL Server Backups in Docker on macOS with VS Code

Whether you are a long-time Mac user or recently transitioned from Windows, running SQL Server on macOS brings a unique set of challenges. Most tutorials assume you’re on Windows using SQL Server Management Studio (SSMS), which is a tool that doesn’t exist for Mac. Instead, you’re likely running SQL Server inside a Docker container and using a tool like VS Code.

While the VS Code mssql extension is great for querying, it lacks the administrative wizards found in SSMS. You won’t find a “Restore” button to handle your .bak files here. This may leave you wondering where to even start, especially since you have to bridge the gap between a Windows-born backup file and a Linux-based Docker filesystem.

In this article, I’ll show you how to take control of the process. We’ll move your backup into the container via the Terminal and use a T-SQL script to “re-map” the internal file paths. Here is the straightforward, 3-step workflow to get your database up and running.

1. Copy the Backup File to the Container

The first step in the process is to copy the .bak file to the Docker container where SQL Server resides.

For this article, we’ll use the WideWorldImporters-Full.bak file, which is a backup of the WideWorldImporters sample database.

Open your Terminal and run the following command to copy the file from your Mac into the running Docker container (using the path/file name of your own .bak file):

docker cp ~/Downloads/WideWorldImporters-Full.bak sql_container_name:/var/opt/mssql/data/

Don’t forget to:

  • Replace ~/Downloads/WideWorldImporters-Full.bak with your .bak file
  • Replace sql_container_name with your actual container name

2. Identify Logical File Names

SQL Server backups contain internal “logical” names for data and log files. Since the original backup was likely made on Windows, we need to “move” these files to the Linux-based paths inside your Docker container.

In VS Code (or another DB tool), open a new SQL query window (connected to your Docker instance) and run:

RESTORE FILELISTONLY 
FROM DISK = '/var/opt/mssql/data/WideWorldImporters-Full.bak';

Look for the LogicalName column in the results. For the WideWorldImporters database, these are typically WWI_Primary, WWI_UserData, WWI_Log, and WWI_InMemory_Data_1.

Here’s a screenshot of what this might look like:

Screenshot of result set showing the logical names and the physical file paths

More columns are returned than what’s listed here, but we can see the main ones we’re interested in. We can see the logical names alongside their physical file paths. Given our container image uses Linux, these paths are no good and will need to be changed (which we’ll do next, when we restore the backup).

3. Run the Restore Script

Use the following T-SQL in VS Code to perform the actual restoration. This script maps the Windows-style paths in the backup to the appropriate Linux paths in your container.

USE [master];
GO

RESTORE DATABASE [WideWorldImporters]
FROM DISK = N'/var/opt/mssql/data/WideWorldImporters-Full.bak'
WITH 
    MOVE N'WWI_Primary' TO N'/var/opt/mssql/data/WideWorldImporters.mdf',
    MOVE N'WWI_UserData' TO N'/var/opt/mssql/data/WideWorldImporters_UserData.ndf',
    MOVE N'WWI_Log' TO N'/var/opt/mssql/data/WideWorldImporters.ldf',
    MOVE N'WWI_InMemory_Data_1' TO N'/var/opt/mssql/data/WideWorldImporters_InMemory_Data_1',
    RECOVERY, 
    STATS = 5;
GO

Bear in mind the following:

  • Logical Name: This is a “hardcoded” label inside the backup. You must find this using FILELISTONLY and use it exactly as-is in your script.
  • Physical Path: This is the destination on your “disk” (the container’s filesystem). You have full creative control over what these files are named, as long as the directory exists.

That’s it. The database has now been restored. You can now go ahead and start using it.

Troubleshooting Tips & Consideration

Here are some common issues and things to consider:

  • Case Sensitivity: Unlike Windows, the Linux file system inside the Docker container is case-sensitive. If you name your file MyBackup.bak but type mybackup.bak in the SQL script, it will fail.
  • Permissions: Sometimes the mssql user inside the container doesn’t have permission to read the folder where you copied the backup. Using /var/opt/mssql/ as a destination is usually the safest bet.
  • No Need for a “Blank DB”: You don’t need to create the database first. The .bak file is sufficient to build the entire database from scratch.
  • M1/M2/M3 Macs: Ensure you are using the latest SQL Server image. At the time of writing this is mcr.microsoft.com/mssql/server:2022-latest, with mcr.microsoft.com/mssql/server:2025-latest also being available in preview mode. Older versions may not support ARM64 architecture natively. You can also use SQL Edge, although that has now been retired.