Last week I purchased a shiny new MacBook Air with an M2 processor. After I got all the standard stuff up and running, I set out to learn how to run SQL Server containers on this new hardware. This post shows you how to run SQL Server on Apple Silicon using colima.
Colima is a container runtime that runs a Linux VM on your Mac. This Linux VM runs using the Virtualization framework hypervisor native in MacOS. Your containers will run inside this virtual machine.
Install Required Software
Docker Desktop for Mac
First, you’ll need Docker Desktop. Well, technically, you don’t need Docker Desktop. Docker Desktop provides both the command line tooling and the container runtime. I’m installing Docker because it will provide the command line interface that I’m used to when working with containers, the
docker command. We’re not going to use Docker as the container runtime. As I write this post, Docker Desktop for Mac recently added MacOS Virtualization framework support, but SQL Server doesn’t run in this environment. I plan to watch this space to see if Docker provides similar functionality in upcoming releases.
Update 22 Jan 23: As predicted, Docker Desktop now supports the Use of Rosetta for x86/amd64 emulation on Apple Silion. Open up your Docker Desktop Settings, click Features in Development and check Use of Rosetta for x86/amd64 emulation on Apple Silion. Once enabled and docker restarts, you can jump right to the section Starting a SQL Server Container. You may be thinking, why would I still go the Colima route? Well, Docker has changed their licensing model and the Colima solution may be a good alternative for you.
Next, you’ll need Rosetta 2, which provides emulation for x86 CPU architectures. In other words, software built for x86 can run on Apple Silicon.
You can then
brew to install Colima.
brew install colima
Setting the Colima virtual machine template configuration
Now, you need to configure Colima’s virtual machine template. Like Docker for Mac, Colima uses a virtual machine to provide a Linux kernel for containers running on MacOS. This virtual machine needs some configuration to run x86 containers.
To configure the VM, you use the command
colima template. This will open Colima’s yaml configuration file in your default text editor.
First, let’s configure the VM to use the MacOS’s Virtualization framework (
vz) rather than the default, which is
Around line 121, change
vmType: qemu to
Next, around line 133, change
mountType: sshfs to
Next, not required, but reccomended you need to update the CPU and memory allocated to the VM.
Around line 9, change
cpu: 2 to
cpu 4 and around line 18 change
memory: 2 to
Starting up Colima
Now, you’ll create a virtual machine from the template file configured in the previous section. You execute the command
colima start. This creates and boots up a VM. And it changes the context of your docker command to point to the Colima container runtime rather than Docker Desktop’s. So when you use
docker commands, they are executed against this VM rather than the Docker Desktop installation. As a note, the settings you set in the template file above can be passed as runtime parameters for the
colima start command. But my preference is to have them persistent in a file.
bash-3.2$ colima start INFO starting colima INFO runtime: docker INFO creating and starting ... context=vm INFO provisioning ... context=docker INFO starting ... context=docker INFO done
Working with Contexts
A second ago, I used the term context. A context is a configuration for your docker CLI tools telling the tools which container runtime endpoint to execute the commands against. When you install Docker Desktop, your default context is the Docker container runtime endpoint. When you start up Colima, it adds a new context and configures your default docker context to point to this new endpoint. You can easily switch between these to launch containers in either container runtimes using the command
docker context use [context name]. To get a listing of which contexts are available on your system, you can use
docker context list and you will get this output.
docker context list NAME TYPE DESCRIPTION DOCKER ENDPOINT KUBERNETES ENDPOINT ORCHESTRATOR colima * moby colima unix:///Users/aen/.colima/default/docker.sock default moby Current DOCKER_HOST based configuration unix:///var/run/docker.sock swarm desktop-linux moby unix:///Users/aen/.docker/run/docker.sock
* next to
colima, this means it is the default. So
docker commands will execute and start containers in this container runtime. Note you can also define which context you want your commands to run against for each execution with the parameter
--context rather than relying on the default context configuration.
At this point, you no longer need the docker container runtime. To conserve your systems resources, you can quit docker and set it to not restart when your computer starts up.
Starting a SQL Server Container
OK, so now that everything is up and running, let’s start a SQL Server container. Most of these parameters are familiar to you if you’ve been working with SQL Server in containers. There is one new one,
--platform linux/amd64. This gives
docker a hint on which container image to pull.
docker run \ --env 'ACCEPT_EULA=Y' \ --env 'MSSQL_SA_PASSWORD=S0methingS@Str0ng!' \ --name 'sqldemo1' \ --hostname 'sqldemo1' \ --publish 31433:1433 \ --volume sqldemo1:/var/opt/mssql \ --detach \ --platform linux/amd64 mcr.microsoft.com/mssql/server:2022-RTM-ubuntu-20.04
If you don’t specify
--platform linux/amd64, everything works fine, but you’ll get this warning at startup.
WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
Checking out what SQL Server thinks about all of this
What I like most about this is all the code I’ve written using the
docker command just work, even though this container isn’t running in the docker container runtime but rather Colima.
With that up and running, we can use
docker logs sqldemo1 to get some information about this container.
SQL Server thinks it’s running on an x64 CPU.
2023-01-02 15:59:32.97 Server Microsoft SQL Server 2022 (RTM) - 16.0.1000.6 (X64) Oct 8 2022 05:58:25 Copyright (C) 2022 Microsoft Corporation Developer Edition (64-bit) on Linux (Ubuntu 20.04.5 LTS) <X64>
Based on our Colima virtual machine configuration, you can see SQL Server had access to four CPUs. The MacBook Air I have has eight cores. But this CPU topology is coming from the Colima VM.
2023-01-02 15:59:32.98 Server SQL Server detected 1 sockets with 4 cores per socket and 4 logical processors per socket, 4 total logical processors; using 4 logical processors based on SQL Server licensing. This is an informational message; no user action is required.
Next, we configured Colima to use 4GB of RAM. The VM has 4GB of RAM, but due to the architecture of SQL Server on Linux with SQLPAL, the default is the SQL Server process sees about 80% of that. So here we see 3142MB of memory.
2023-01-02 15:59:32.98 Server Detected 3142 MB of RAM. This is an informational message; no user action is required.
SQL Server throwing some shade at my configuration:
2023-01-02 15:59:33.67 Server In-Memory OLTP initialized on lowend machine.
This whole experiment isn’t a performance play. I need the ability to run SQL Server containers on my laptop in a functional way. This configuration gives me just that. And it’s pretty decent on performance too. While, I still need to do a complete evaluation of performance, here’s a restore of a backup…getting roughly 785MB/sec. That’s good enough for what I need.
USE [master] RESTORE DATABASE [tpcc100] FROM DISK = N'/var/opt/mssql/data/tpcc100.bak' WITH REPLACE Database 'tpcc100' running the upgrade step from version 912 to version 913. ... Database 'tpcc100' running the upgrade step from version 956 to version 957. RESTORE DATABASE successfully processed 1032597 pages in 10.278 seconds (784.896 MB/sec). Total execution time: 00:00:12.866