Build an MSSQL Docker Container. Level up development with container... | by Richard Peterson | Towards Data Science

Level up development with container databases
You can stop waiting for your database admin to give you access to a dev server, or sifting through the endless documentation for setting up a MS SQL database on your computer’s locked-down work environment, and get to the bare bones of what you really NEED. A sql server that can take requests and return data. That’s it. Your API needs testing, and you need a database.
In the beginning stages of development, you do not want to spend hours configuring your sql server or dealing with a hosted database for a prototype project. This is where a local Docker container can change your life.
We will build a Docker container based on the mcr.microsoft.com/mssql/server image to create a custom Dockerfile that launches a SQL Server, creates a database, creates a table, and populates the table with data. This is article is written in the context of building a .NET Core API for the Angular Tour of Heroes app.
For the finished MSSQL Dockerfile and scripts, please visit my GitHub.
BIG THANKS: twright-msft for his stellar docker image. Much of my image is copied straight from his repo.
Before we go crazy and build a custom Dockerfile, let’s download and run the image to make sure that it works. Make sure that you have Docker installed on your system.
From the command line, run:
docker pull mcr.microsoft.com/mssql/server:latest
Run the image and build the container by running the below code. Specify environment variables such as the password and the version of SQL Server, Express.
docker run \-e 'ACCEPT_EULA=Y' \-e 'SA_PASSWORD=Password1!' \-e 'MSSQL_PID=Express' \--name sqlserver \-p 1433:1433 -d mcr.microsoft.com/mssql/server:latest
If you run docker container ls you should see the sqlserver container running on port 1433.
Run this command to enter your container and be presented with a bash terminal:
docker exec -it sqlserver "bash"
Launch sqlcmd from the container command line. Notice we are using the same password we used when we created the container with docker run.
/opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P "Password1!"
You should see a 1> that informs you that you are on the sqlcmd command line, and can interact with your server! Let’s write some SQL to create a database and a table.
CREATE DATABASE heroesGOUSE heroesCREATE TABLE HeroValue (id INT, name VARCHAR(50))INSERT into HeroValue VALUES (1, "Wonder Woman")GO
Now, query the database to ensure the data was written correctly:
SELECT * FROM HeroValue;GO
Success!
It’s great that we can create the database and insert entries from the bash terminal, but it still feels a bit “manual.” Let’s automate this by writing 3 scripts that our Dockerfile will run on creation of the container. These scripts are:
entrypoint.sh — script ran at startup that simply runs import-data.sh and starts the SQL Server.import-data.sh — runs a sqlcmd that calls setup.sql, and a bcp command that imports a .csv file.setup.sql — SQL script that creates a database and a table.
entrypoint.sh — script ran at startup that simply runs import-data.sh and starts the SQL Server.
import-data.sh — runs a sqlcmd that calls setup.sql, and a bcp command that imports a .csv file.
setup.sql — SQL script that creates a database and a table.
Here’s the final Dockerfile that references these three scripts. Don’t worry, we’ll go into greater detail about how this all works!
FROM microsoft/mssql-server-linux:latest# Create work directoryRUN mkdir -p /usr/workWORKDIR /usr/work# Copy all scripts into working directoryCOPY . /usr/work/# Grant permissions for the import-data script to be executableRUN chmod +x /usr/work/import-data.shEXPOSE 1433CMD /bin/bash ./entrypoint.sh
Per the MSSQL docker docs, you must run the database customization before the final command to start the SQL Server. In our entrypoint.sh file, we call import-data.sh before starting the server.
/usr/work/import-data.sh & /opt/mssql/bin/sqlservr
At container creation, entrypoint will run import-data.sh and start the server. Import-data.sh gives us two SQL Server commands, as well as a very necessary command to sleep for 90 seconds while the database starts up. Grab a cup of tea while you wait or meditate.
# wait for the SQL Server to come upsleep 90s#run the setup script to create the DB and the schema in the DB/opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P "Password1!" -i setup.sql# import the data from the csv file/opt/mssql-tools/bin/bcp heroes.dbo.HeroValue in "/usr/work/heroes.csv" -c -t',' -S localhost -U SA -P "Password1!" -d heroes
The second command, sqlcmd, runs setup.sql, which scaffolds our database. After creating the database, it imports data from a .csv file using bcp.
CREATE DATABASE heroes;GOUSE heroes;GOCREATE TABLE HeroValue (id INT, name VARCHAR(50));GO
Tag your image mssql:dev and build by running:
docker build -t mssql:dev .
When this completes, run the image using docker run. This is almost identical to our first docker run, except we have changed the image to our newly created and tagged mssql:dev image.
docker run \-e 'ACCEPT_EULA=Y' \-e 'SA_PASSWORD=Password1!' \-e 'MSSQL_PID=Express' \--name sqlserver \-p 1433:1433 \-d mssql:dev
When the image has been created and we receive a confirmation image ID, access the container to confirm it is working.
docker exec -it sqlserver "bash"
From the container command line, access the heroes database.
/opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P "Password1!" -d heroes
Query the data to make sure that it was inserted correctly. For some reason, when I run this, it returns a block of blank values, and the last value. But I have confirmed by running queries from C# that all the values are there. If anyone knows why all the values are not showing, I would love to know.
SELECT * FROM HeroValue;GO
That’s it! You now have a SQL Server database that you can easily configure and launch at your pleasure!
You can kill your container by running:
docker kill sqlserver
And restart your container with your docker run command, which you could easily store in a script, such as start-docker-sql.sh, or some such file.
docker run \-e 'ACCEPT_EULA=Y' \-e 'SA_PASSWORD=Password1!' \-e 'MSSQL_PID=Express' \--name sqlserver \-p 1433:1433 \-d mssql:dev
Now that you have a working image, you definitely want to save it on a hosted repository so that you can pull the image as needed to different machines.
Create a Docker Hub account at https://hub.docker.com/.
Then create a new repository and give it a Name and description.
From the command line, run docker login. You will be prompted for the credentials you set up when you created your account.
Now, tag your image:
docker tag local-image:tagname username/new-repo:tagname
Next, push your image to your new repository:
docker push username/new-repo:tagname
When this is complete, you will be able to pull your image by running:
docker pull username/new-repo:tagname
I hope this makes your life a little easier! You can head on over to my next article in this series to use this database with a .NET API.
"ConnectionStrings": {    "DockerDB": "Server=localhost,1433;Database=heroes;User ID=SA;Password=Password1!"  }
Thank you for reading!