--- title: Secure SQL Server Linux Containers description: Understand the different ways to secure SQL Server Linux containers and how you can run containers as different non-root users on the host. author: amitkh-msft ms.author: amitkh ms.reviewer: vanto, randolphwest ms.date: 07/03/2025 ms.service: sql ms.subservice: linux ms.topic: how-to ms.custom: - engagement-fy23 - linux-related-content - sfi-ropc-blocked - ignite-2025 monikerRange: ">=sql-server-linux-2017 || >=sql-server-2017" --- # Secure SQL Server Linux containers [!INCLUDE [SQL Server - Linux](../includes/applies-to-version/sql-linux.md)] [!INCLUDE [sssql17-md](../includes/sssql17-md.md)] containers start up as the root user by default, which can cause some security concerns. This article talks about security options that you have when running [!INCLUDE [ssnoversion-md](../includes/ssnoversion-md.md)] Linux containers, and how to build a [!INCLUDE [ssnoversion-md](../includes/ssnoversion-md.md)] container as a non-root user. The examples in this article assume that you're using Docker, but you can apply the same principles to other container orchestration tools including Kubernetes. ## Build and run non-root SQL Server 2017 containers Follow these steps to build a [!INCLUDE [sssql17-md](../includes/sssql17-md.md)] container that starts up as the `mssql` (non-root) user. > [!NOTE] > Containers for [!INCLUDE [sssql19-md](../includes/sssql19-md.md)] and later versions automatically start up as non-root, while [!INCLUDE [sssql17-md](../includes/sssql17-md.md)] containers start as root by default. For more information on running SQL Server containers as non-root, see [Secure SQL Server Linux containers](sql-server-linux-docker-container-security.md). 1. Download the [sample Dockerfile for non-root SQL Server containers](https://raw.githubusercontent.com/microsoft/mssql-docker/master/linux/preview/examples/mssql-server-linux-non-root/Dockerfile) and save it as `dockerfile`. 1. Run the following command in the context of the dockerfile directory to build the non-root [!INCLUDE [ssnoversion-md](../includes/ssnoversion-md.md)] container: ```bash cd docker build -t 2017-latest-non-root . ``` 1. Start the container. > [!IMPORTANT] > The `SA_PASSWORD` environment variable is deprecated. Use `MSSQL_SA_PASSWORD` instead. ```bash docker run -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=" --cap-add SYS_PTRACE --name sql1 -p 1433:1433 -d 2017-latest-non-root ``` > [!NOTE] > The `--cap-add SYS_PTRACE` flag is required for non-root [!INCLUDE [ssnoversion-md](../includes/ssnoversion-md.md)] containers to generate dumps for troubleshooting purposes. 1. Check that the container is running as non-root user: ```bash docker exec -it sql1 bash ``` Run `whoami`, which returns the user running within the container. ```bash whoami ``` ## Run container as a different non-root user on the host To run the [!INCLUDE [ssnoversion-md](../includes/ssnoversion-md.md)] container as a different non-root user, add the `-u` flag to the `docker run` command. The non-root container has the restriction that it must run as part of the `root` group unless a volume is mounted to `/var/opt/mssql` that the non-root user can access. The `root` group doesn't grant any extra root permissions to the non-root user. #### Run as a user with a UID 4000 You can start [!INCLUDE [ssnoversion-md](../includes/ssnoversion-md.md)] with a custom UID. For example, the following command starts [!INCLUDE [ssnoversion-md](../includes/ssnoversion-md.md)] with UID 4000: ```bash docker run -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=" --cap-add SYS_PTRACE -u 4000:0 -p 1433:1433 -d mcr.microsoft.com/mssql/server:2019-latest ``` > [!WARNING] > Make sure that the [!INCLUDE [ssnoversion-md](../includes/ssnoversion-md.md)] container has a named user such as `mssql` or `root`, otherwise **sqlcmd** can't run within the container. You can check if the [!INCLUDE [ssnoversion-md](../includes/ssnoversion-md.md)] container is running as a named user by running `whoami` within the container. #### Run the non-root container as the root user You can run the non-root container as the root user if necessary, which also grants all file permissions automatically to the container, because it has higher privilege. ```bash docker run -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=" -u 0:0 -p 1433:1433 -d mcr.microsoft.com/mssql/server:2019-latest ``` #### Run as a user on your host machine You can start [!INCLUDE [ssnoversion-md](../includes/ssnoversion-md.md)] with an existing user on the host machine with the following command: ```bash docker run -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=" --cap-add SYS_PTRACE -u $(id -u myusername):0 -p 1433:1433 -d mcr.microsoft.com/mssql/server:2019-latest ``` #### Run as a different user and group You can start [!INCLUDE [ssnoversion-md](../includes/ssnoversion-md.md)] with a custom user and group. In this example, the mounted volume has permissions configured for the user or group on the host machine. ```bash docker run -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=" --cap-add SYS_PTRACE -u $(id -u myusername):$(id -g myusername) -v /path/to/mssql:/var/opt/mssql -p 1433:1433 -d mcr.microsoft.com/mssql/server:2019-latest ``` ## Configure persistent storage permissions for non-root containers To allow the non-root user to access database files that are on mounted volumes, make sure that the user or group you run the container under, can read from, and write to, the persistent file storage. You can get the current ownership of the database files with this command. ```bash ls -ll ``` Run one of the following commands if [!INCLUDE [ssnoversion-md](../includes/ssnoversion-md.md)] doesn't have access to persisted database files. #### Grant the root group read/write access to the database files Grant the root group permissions to the following directories so that the non-root [!INCLUDE [ssnoversion-md](../includes/ssnoversion-md.md)] container has access to database files. ```bash chgrp -R 0 chmod -R g=u ``` #### Set the non-root user as the owner of the files The owner can be the default non-root user, or any other non-root user you'd like to specify. In this example, you set UID 10001 as the non-root user. ```bash chown -R 10001:0 ``` ## Encrypt connections to SQL Server Linux containers > [!IMPORTANT] > When you configure Active Directory authentication or encryption options such as Transparent Data Encryption (TDE) and SSL/TLS for [!INCLUDE [ssnoversion-md](../includes/ssnoversion-md.md)] on Linux or containers, there are several files, such as the keytab, certificates, and machine key, that are created by default under the folder `/var/opt/mssql/secrets`, and access to which is restricted by default to `mssql` and `root` users. When you configure persistent storage for [!INCLUDE [ssnoversion-md](../includes/ssnoversion-md.md)] containers, use the same access strategy, ensuring that the path on the host or shared volume that is mapped to the `/var/opt/mssql/secrets` folder inside the container is protected and accessible only to the `mssql` and `root` users on the host as well. If the access to this path/folder is compromised, a malicious user can gain access to these critical files, compromising the encryption hierarchy and/or Active Directory configurations. To encrypt connections to [!INCLUDE [ssnoversion-md](../includes/ssnoversion-md.md)] Linux containers, you need a certificate with the following [requirements](sql-server-linux-encrypted-connections.md). Following is an example of how the connection can be encrypted to [!INCLUDE [ssnoversion-md](../includes/ssnoversion-md.md)] Linux containers. Here you use a self-signed certificate, which shouldn't be used for production scenarios. For such environments, you should use CA certificates instead. 1. Create a self-signed certificate, which is suited for test and non-production environments only. ```bash openssl req -x509 -nodes -newkey rsa:2048 -subj '/CN=sql1.contoso.com' -keyout /container/sql1/mssql.key -out /container/sql1/mssql.pem -days 365 ``` In the previous code sample, `sql1` is the hostname of the SQL container, so when connecting to this container the name used in the connection string is going to be `sql1.contoso.com,port`. You must also ensure that the folder path `/container/sql1/` already exists before running the previous command. 1. Ensure you set the right permissions on the `mssql.key` and `mssql.pem` files, so you avoid errors when you mount the files to [!INCLUDE [ssnoversion-md](../includes/ssnoversion-md.md)] container: ```bash chmod 440 /container/sql1/mssql.pem chmod 440 /container/sql1/mssql.key ``` 1. Now create a `mssql.conf` file with the following content to enable the Server Initiated encryption. For Client initiated encryption, change the last line to `forceencryption = 0`. ```ini [network] tlscert = /etc/ssl/certs/mssql.pem tlskey = /etc/ssl/private/mssql.key tlsprotocols = 1.2 forceencryption = 1 ``` > [!NOTE] > For some Linux distributions, the path for storing the certificate and key could also be `/etc/pki/tls/certs/` and `/etc/pki/tls/private/` respectively. Verify the path before updating the `mssql.conf` for [!INCLUDE [ssnoversion-md](../includes/ssnoversion-md.md)] containers. The location you set in the `mssql.conf` is the location where [!INCLUDE [ssnoversion-md](../includes/ssnoversion-md.md)] in the container is going to search for the certificate and its key. In this case, that location is `/etc/ssl/certs/` and `/etc/ssl/private/`. The `mssql.conf` file is also created under the same folder location `/container/sql1/`. After running the above steps, you should have three files: `mssql.conf`, `mssql.key`, and `mssql.pem` in the `sql1` folder. 1. Deploy the [!INCLUDE [ssnoversion-md](../includes/ssnoversion-md.md)] container with the following command (replace `` with a valid password): ```bash docker run -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=" -p 5434:1433 --name sql1 -h sql1 -v /container/sql1/mssql.conf:/var/opt/mssql/mssql.conf -v /container/sql1/mssql.pem:/etc/ssl/certs/mssql.pem -v /container/sql1/mssql.key:/etc/ssl/private/mssql.key -d mcr.microsoft.com/mssql/server:2019-latest ``` In the previous command, you mounted the `mssql.conf`, `mssql.pem`, and `mssql.key` files to the container and mapped the 1433 ([!INCLUDE [ssnoversion-md](../includes/ssnoversion-md.md)] default port) port in the container to port 5434 on the host. > [!NOTE] > If you use Red Hat Enterprise Linux 8 and later versions, you can also use `podman run` command instead of `docker run`. Follow the "Register the certificate on your client machine" and "Example connection strings" sections documented in [Client Initiated Encryption](sql-server-linux-encrypted-connections.md?tabs=client#overview) to start encrypting connections to [!INCLUDE [ssnoversion-md](../includes/ssnoversion-md.md)] on Linux containers. ## Related content ::: moniker range="=sql-server-linux-2017 || =sql-server-2017" - Get started with [!INCLUDE [sssql17-md](../includes/sssql17-md.md)] container images on Docker by going through the [quickstart](quickstart-install-connect-docker.md?view=sql-server-2017&preserve-view=true) ::: moniker-end ::: moniker range="=sql-server-linux-ver15 || =sql-server-ver15" - Get started with [!INCLUDE [sssql19-md](../includes/sssql19-md.md)] container images on Docker by going through the [quickstart](quickstart-install-connect-docker.md?view=sql-server-ver15&preserve-view=true) ::: moniker-end ::: moniker range="=sql-server-linux-ver16 || =sql-server-ver16" - Get started with [!INCLUDE [sssql22-md](../includes/sssql22-md.md)] container images on Docker by going through the [quickstart](quickstart-install-connect-docker.md?view=sql-server-ver16&preserve-view=true) ::: moniker-end ::: moniker range=">=sql-server-linux-ver17 || >=sql-server-ver17" - Get started with [!INCLUDE [sssql25-md](../includes/sssql25-md.md)] container images on Docker by going through the [quickstart](quickstart-install-connect-docker.md?view=sql-server-ver17&preserve-view=true) ::: moniker-end - [Deploy and connect to SQL Server Linux containers](sql-server-linux-docker-container-deployment.md) - [Configure and customize SQL Server Linux containers](sql-server-linux-docker-container-configure.md) - [Troubleshoot SQL Server Docker containers](sql-server-linux-docker-container-troubleshooting.md)