Ken Muse

Automating SQL Server 2019 Docker Deployments

In a previous article, I walked through deploying to SQL Server 2017 containers and provided an overview of deploying DACPACs and BACPACs in containers. Since that time, SQL Server 2019 has been released; this requires a few changes to the approach. In this article, we’ll look at what changes you need to make to deploy to a 2019 container.

Let’s start with the code, then examine what’s changed.

 3# Elevate to root to install required packages
 4USER root
 5RUN apt-get update \
 6    && apt-get install unzip libunwind8 libicu55 -y
 8# Install SQLPackage for Linux and make it executable
 9RUN wget -progress=bar:force -q -O \
10    && unzip -qq -d /opt/sqlpackage \
11    && chmod +x /opt/sqlpackage/sqlpackage \
12    && chown -R mssql /opt/sqlpackage \
13    && mkdir /tmp/db \
14    && chown -R mssql /tmp/db
16# Lower the privilege
17USER mssql
19# Add the DACPAC to the image
20COPY site.bacpac /tmp/db/db.bacpac
22# Configure external build arguments to allow configurability.
23ARG DBNAME=Database
26# Configure the required environmental variables
30# Launch SQL Server, confirm startup is complete, deploy the DACPAC, then terminate SQL Server.
31# See
32RUN ( /opt/mssql/bin/sqlservr & ) | grep -q "Service Broker manager has started" \
33    && /opt/sqlpackage/sqlpackage /a:Import /tsn:. /tdn:${DBNAME} /tu:sa /tp:$SA_PASSWORD /sf:/tmp/db/db.bacpac \
34    && rm -r /tmp/db \
35    && pkill sqlservr \
36    && rm -r /opt/sqlpackage

To begin with, you will need to use a SQL Server 2019 image, such as 2019-latest. There is a complete list of images, which includes specific releases of SQL Server that you can use. Microsoft documents installing and connecting to SQL Server 2019 on Docker if you want to learn more about working with the containerized version of SQL Server. The Microsoft docs site also provides a guide to configuring Docker containers. The default Linux image is based on Ubuntu, but official RHEL images are also available.

Next, it’s important to know that the images are substantially more secure than the 2017 release. Instead of the images being built as root, a less privileged user called mssql is utilized. Because of this change, you need to explicitly switch users to install packages into the container via apt-get. This is done using Docker’s USER command. Switching to root is required when running apt-get to install packages, adjusting the ownership of folders, or performing other operations which required elevated privileges. In this case, the Dockerfile is installing dependencies that are required for sqlpackage.

Finally, the Dockerfile in this version changes the ownership of folders to enable automatically removing sqlpackage and the deployed BACPAC/DACPAC at the end of the process. To do that, we have to ensure the mssql user account is the owner of those folders. A natural question is why we can’t simply wait until after the last RUN to switch the user from root to mssql? Commands are executed in the context of the current user account. If we wait to switch back, we execute the deployment commands as the root user. As a result, any files created (such as the database files) are owned by that account. This would prevent the mssql account from being able to read and write those files. As a best practice, it’s important to observe least privileges. The code execute the commands in the lower-privileged mssql account, ensuring the proper permissions are automatically applied.

And that’s it. With these changes in place, we can use SQL Server 2019 containers and automatically deploy our database packages.