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.
1FROM mcr.microsoft.com/mssql/server:2019-latest
2
3# Elevate to root to install required packages
4USER root
5RUN apt-get update \
6 && apt-get install unzip libunwind8 libicu55 -y
7
8# Install SQLPackage for Linux and make it executable
9RUN wget -progress=bar:force -q -O sqlpackage.zip https://go.microsoft.com/fwlink/?linkid=2113331 \
10 && unzip -qq sqlpackage.zip -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
15
16# Lower the privilege
17USER mssql
18
19# Add the DACPAC to the image
20COPY site.bacpac /tmp/db/db.bacpac
21
22# Configure external build arguments to allow configurability.
23ARG DBNAME=Database
24ARG PASSWORD
25
26# Configure the required environmental variables
27ENV ACCEPT_EULA=Y
28ENV SA_PASSWORD=$PASSWORD
29
30# Launch SQL Server, confirm startup is complete, deploy the DACPAC, then terminate SQL Server.
31# See https://stackoverflow.com/a/51589787/488695
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.