Skip to content
This repository was archived by the owner on Jul 18, 2025. It is now read-only.

Commit 8c217ea

Browse files
committed
Update to latest SQL images
1 parent 16cc1ce commit 8c217ea

File tree

6 files changed

+113
-75
lines changed

6 files changed

+113
-75
lines changed

windows/sql-server/Dockerfile.builder

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,2 @@
1-
# escape=`
2-
FROM microsoft/windowsservercore
3-
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop';"]
4-
5-
RUN Install-PackageProvider -Name chocolatey -RequiredVersion 2.8.5.130 -Force; `
6-
Install-Package -Name microsoft-build-tools -RequiredVersion 15.0.26228.0 -Force; `
7-
Install-Package -Name netfx-4.5.2-devpack -RequiredVersion 4.5.5165101 -Force
8-
9-
RUN Install-Package nuget.commandline -RequiredVersion 3.5.0 -Force; `
10-
& C:\Chocolatey\bin\nuget install Microsoft.Data.Tools.Msbuild -Version 10.0.61026
11-
12-
ENV MSBUILD_PATH="C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\MSBuild\15.0\Bin"
13-
14-
RUN $env:PATH = $env:MSBUILD_PATH + ';' + $env:PATH; `
15-
[Environment]::SetEnvironmentVariable('PATH', $env:PATH, [EnvironmentVariableTarget]::Machine)
1+
FROM microsoft/dotnet-framework:4.7.2-sdk-windowsservercore-ltsc2016
2+
RUN nuget install Microsoft.Data.Tools.Msbuild -Version 10.0.61804.210

windows/sql-server/Dockerfile.v1

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,33 @@ FROM dockersamples/assets-db-builder AS builder
44
WORKDIR C:\src
55
COPY src\Assets.Database-v1\ .
66
RUN msbuild Assets.Database.sqlproj `
7-
/p:SQLDBExtensionsRefPath="C:\Microsoft.Data.Tools.Msbuild.10.0.61026\lib\net40" `
8-
/p:SqlServerRedistPath="C:\Microsoft.Data.Tools.Msbuild.10.0.61026\lib\net40"
7+
/p:SQLDBExtensionsRefPath="C:\Microsoft.Data.Tools.Msbuild.10.0.61804.210\lib\net46" `
8+
/p:SqlServerRedistPath="C:\Microsoft.Data.Tools.Msbuild.10.0.61804.210\lib\net46"
9+
10+
# update to latest SqlPackage
11+
FROM microsoft/windowsservercore:ltsc2016 AS sqlpackage
12+
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
13+
14+
ENV download_url="https://download.microsoft.com/download/6/E/4/6E406E38-0A01-4DD1-B85E-6CA7CF79C8F7/EN/x64/DacFramework.msi"
15+
16+
RUN Invoke-WebRequest -Uri $env:download_url -OutFile DacFramework.msi ; `
17+
Start-Process msiexec.exe -ArgumentList '/i', 'DacFramework.msi', '/quiet', '/norestart' -NoNewWindow -Wait; `
18+
Remove-Item -Force DacFramework.msi
919

1020
# db image
11-
FROM microsoft/mssql-server-windows-express
21+
FROM microsoft/mssql-server-windows-express:2016-sp1
1222
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop';"]
1323

14-
VOLUME C:\database
15-
ENV sa_password D0cker!a8s
24+
COPY --from=sqlpackage ["C:\\Program Files\\Microsoft SQL Server\\140\\DAC", "C:\\Program Files\\Microsoft SQL Server\\140\\DAC"]
25+
26+
ENV ACCEPT_EULA="Y" `
27+
DATA_PATH="C:\database" `
28+
sa_password="D0cker!a8s"
29+
30+
VOLUME ${DATA_PATH}
1631

1732
WORKDIR C:\init
1833
COPY Initialize-Database.ps1 .
19-
CMD ./Initialize-Database.ps1 -sa_password $env:sa_password -Verbose
34+
ENTRYPOINT ["powershell", "./Initialize-Database.ps1"]
2035

2136
COPY --from=builder C:\src\bin\Debug\Assets.Database.dacpac .

windows/sql-server/Dockerfile.v2

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,33 @@ FROM dockersamples/assets-db-builder AS builder
44
WORKDIR C:\src
55
COPY src\Assets.Database-v2\ .
66
RUN msbuild Assets.Database.sqlproj `
7-
/p:SQLDBExtensionsRefPath="C:\Microsoft.Data.Tools.Msbuild.10.0.61026\lib\net40" `
8-
/p:SqlServerRedistPath="C:\Microsoft.Data.Tools.Msbuild.10.0.61026\lib\net40"
7+
/p:SQLDBExtensionsRefPath="C:\Microsoft.Data.Tools.Msbuild.10.0.61804.210\lib\net46" `
8+
/p:SqlServerRedistPath="C:\Microsoft.Data.Tools.Msbuild.10.0.61804.210\lib\net46"
9+
10+
# update to latest SqlPackage
11+
FROM microsoft/windowsservercore:ltsc2016 AS sqlpackage
12+
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
13+
14+
ENV download_url="https://download.microsoft.com/download/6/E/4/6E406E38-0A01-4DD1-B85E-6CA7CF79C8F7/EN/x64/DacFramework.msi"
15+
16+
RUN Invoke-WebRequest -Uri $env:download_url -OutFile DacFramework.msi ; `
17+
Start-Process msiexec.exe -ArgumentList '/i', 'DacFramework.msi', '/quiet', '/norestart' -NoNewWindow -Wait; `
18+
Remove-Item -Force DacFramework.msi
919

1020
# db image
11-
FROM microsoft/mssql-server-windows-express
21+
FROM microsoft/mssql-server-windows-express:2016-sp1
1222
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop';"]
1323

14-
VOLUME C:\database
15-
ENV sa_password D0cker!a8s
24+
COPY --from=sqlpackage ["C:\\Program Files\\Microsoft SQL Server\\140\\DAC", "C:\\Program Files\\Microsoft SQL Server\\140\\DAC"]
25+
26+
ENV ACCEPT_EULA="Y" `
27+
DATA_PATH="C:\database" `
28+
sa_password="D0cker!a8s"
29+
30+
VOLUME ${DATA_PATH}
1631

1732
WORKDIR C:\init
1833
COPY Initialize-Database.ps1 .
19-
CMD ./Initialize-Database.ps1 -sa_password $env:sa_password -Verbose
34+
ENTRYPOINT ["powershell", "./Initialize-Database.ps1"]
2035

2136
COPY --from=builder C:\src\bin\Debug\Assets.Database.dacpac .
Lines changed: 55 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,66 @@
1-
# Adapted from Microsoft's SQL Server Express sample:
2-
# https://github.com/Microsoft/sql-server-samples/blob/master/samples/manage/windows-containers/mssql-server-2016-express-windows/start.ps1
3-
41
param(
5-
[Parameter(Mandatory=$false)]
6-
[string]$sa_password)
2+
[string] $sa_password = $env:sa_password,
3+
[string] $data_path = $env:data_path,
4+
[string] $TargetServerName = '.\SQLEXPRESS',
5+
[string] $TargetDatabaseName = 'AssetsDB',
6+
[string] $TargetUser = 'sa',
7+
[string] $TargetPassword = $env:sa_password
8+
)
79

8-
# start the service
9-
Write-Verbose 'Starting SQL Server'
10-
start-service MSSQL`$SQLEXPRESS
10+
if ($TargetDatabaseName -eq '.\SQLEXPRESS') {
1111

12-
if ($sa_password -ne "_") {
13-
Write-Verbose 'Changing SA login credentials'
14-
$sqlcmd = "ALTER LOGIN sa with password='$sa_password'; ALTER LOGIN sa ENABLE;"
15-
Invoke-Sqlcmd -Query $sqlcmd -ServerInstance ".\SQLEXPRESS"
16-
}
12+
# start the service
13+
Write-Verbose 'Starting SQL Server'
14+
Start-Service MSSQL`$SQLEXPRESS
15+
16+
if ($sa_password -ne "_") {
17+
Write-Verbose 'Changing SA login credentials'
18+
$sqlcmd = "ALTER LOGIN sa with password='$sa_password'; ALTER LOGIN sa ENABLE;"
19+
Invoke-SqlCmd -Query $sqlcmd -ServerInstance ".\SQLEXPRESS"
20+
}
1721

18-
# attach data files if they exist:
19-
$mdfPath = 'c:\database\AssetsDB_Primary.mdf'
20-
if ((Test-Path $mdfPath) -eq $true) {
21-
$sqlcmd = "CREATE DATABASE AssetsDB ON (FILENAME = N'$mdfPath')"
22-
$ldfPath = 'c:\database\AssetsDB_Primary.ldf'
22+
$mdfPath = "$data_path\AssetsDB_Primary.mdf"
23+
$ldfPath = "$data_path\AssetsDB_Primary.ldf"
24+
25+
# attach data files if they exist:
2326
if ((Test-Path $mdfPath) -eq $true) {
24-
$sqlcmd = "$sqlcmd, (FILENAME = N'$ldfPath')"
27+
$sqlcmd = "IF DB_ID('AssetsDB') IS NULL BEGIN CREATE DATABASE AssetsDB ON (FILENAME = N'$mdfPath')"
28+
if ((Test-Path $ldfPath) -eq $true) {
29+
$sqlcmd = "$sqlcmd, (FILENAME = N'$ldfPath')"
30+
}
31+
$sqlcmd = "$sqlcmd FOR ATTACH; END"
32+
Write-Verbose 'Data files exist - will attach and upgrade database'
33+
Invoke-Sqlcmd -Query $sqlcmd -ServerInstance ".\SQLEXPRESS"
34+
}
35+
else {
36+
Write-Verbose 'No data files - will create new database'
2537
}
26-
$sqlcmd = "$sqlcmd FOR ATTACH;"
27-
Write-Verbose "Invoke-Sqlcmd -Query $($sqlcmd) -ServerInstance '.\SQLEXPRESS'"
28-
Invoke-Sqlcmd -Query $sqlcmd -ServerInstance ".\SQLEXPRESS"
2938
}
3039

3140
# deploy or upgrade the database:
32-
$SqlPackagePath = 'C:\Program Files (x86)\Microsoft SQL Server\130\DAC\bin\SqlPackage.exe'
41+
$SqlPackagePath = 'C:\Program Files\Microsoft SQL Server\140\DAC\bin\SqlPackage.exe'
3342
& $SqlPackagePath `
3443
/sf:Assets.Database.dacpac `
35-
/a:Script /op:create.sql /p:CommentOutSetVarDeclarations=true `
36-
/tsn:.\SQLEXPRESS /tdn:AssetsDB /tu:sa /tp:$sa_password
37-
38-
$SqlCmdVars = "DatabaseName=AssetsDB", "DefaultFilePrefix=AssetsDB", "DefaultDataPath=c:\database\", "DefaultLogPath=c:\database\"
39-
Invoke-Sqlcmd -InputFile create.sql -Variable $SqlCmdVars -Verbose
40-
41-
# relay SQL event logs to Docker
42-
$lastCheck = (Get-Date).AddSeconds(-2)
43-
while ($true) {
44-
Get-EventLog -LogName Application -Source "MSSQL*" -After $lastCheck | Select-Object TimeGenerated, EntryType, Message
45-
$lastCheck = Get-Date
46-
Start-Sleep -Seconds 2
47-
}
44+
/a:Script /op:deploy.sql /p:CommentOutSetVarDeclarations=true `
45+
/TargetServerName:$TargetServerName /TargetDatabaseName:$TargetDatabaseName `
46+
/TargetUser:$TargetUser /TargetPassword:$TargetPassword
47+
48+
if ($TargetServerName -eq '.\SQLEXPRESS') {
49+
$SqlCmdVars = "DatabaseName=$TargetDatabaseName", "DefaultFilePrefix=$TargetDatabaseName", "DefaultDataPath=$data_path\", "DefaultLogPath=$data_path\"
50+
Invoke-Sqlcmd -InputFile deploy.sql -Variable $SqlCmdVars -Verbose
51+
52+
Write-Verbose "Deployed AssetsDB database, data files at: $data_path"
53+
54+
$lastCheck = (Get-Date).AddSeconds(-2)
55+
while ($true) {
56+
Get-EventLog -LogName Application -Source "MSSQL*" -After $lastCheck | Select-Object TimeGenerated, EntryType, Message
57+
$lastCheck = Get-Date
58+
Start-Sleep -Seconds 2
59+
}
60+
}
61+
else {
62+
$SqlCmdVars = "DatabaseName=$TargetDatabaseName", "DefaultFilePrefix=$TargetDatabaseName", "DefaultDataPath=$data_path\", "DefaultLogPath=$data_path\"
63+
Invoke-Sqlcmd -ServerInstance $TargetServerName -Database $TargetDatabaseName -User $TargetUser -Password $TargetPassword -InputFile deploy.sql -Variable $SqlCmdVars -Verbose
64+
65+
Write-Verbose "Deployed AssetsDB database, data files at: $data_path"
66+
}

windows/sql-server/part-3.md

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,23 @@ You now have a Docker image with a SQL schema and deployment script, packaged on
77
The image can be used in development environments where a fresh database is needed for working on new app features, and you want to easily reset the data to an initial state. In this scenario you don't want to persist data between containers, you want the database container to be disposable:
88

99
```Docker
10-
docker container run --detach --name assets-db --publish 1433 dockersamples/assets-db:v1
10+
docker container run --detach --name assets-db --publish 1433:1433 dockersamples/assets-db:v1
1111
```
1212

1313
When the container starts it runs the deployment script, finds that there are no existing database files and creates a new database. You can check that by viewing the logs from the container - you'll see the output from the script:
1414

1515
```
1616
> docker container logs assets-db
17-
...
17+
VERBOSE: Starting SQL Server
18+
VERBOSE: Changing SA login credentials
19+
VERBOSE: No data files - will create new database
20+
Generating publish script for database 'AssetsDB' on server '.\SQLEXPRESS'.
21+
Successfully generated script to file C:\init\deploy.sql.
22+
VERBOSE: Changed database context to 'master'.
1823
VERBOSE: Creating AssetsDB...
1924
VERBOSE: Changed database context to 'AssetsDB'.
2025
VERBOSE: Creating [dbo].[Assets]...
2126
VERBOSE: Creating [dbo].[AssetTypes]...
22-
VERBOSE: Creating [dbo].[Locations]...
23-
VERBOSE: Creating [dbo].[FK_Assets_To_Locations]...
24-
VERBOSE: Creating [dbo].[FK_Assets_To_AssetTypes]...
2527
```
2628

2729
You can connect to the database container using SQL Server Management Studio or any other SQL client. From your Docker machine you need to get the IP address of the container with `docker container inspect`:
@@ -54,7 +56,7 @@ You can see that when you remove the container, and start a new one with the sam
5456
```PowerShell
5557
docker container rm --force assets-db
5658
57-
docker container run --detach --publish 1433 --name assets-db dockersamples/assets-db:v1
59+
docker container run --detach --publish 1433:1433 --name assets-db dockersamples/assets-db:v1
5860
```
5961

6062
Inspect this container with `docker container inspect` and you'll see it has a new IP address - this is a whole new container. Connect your SQL client, repeat the `SELECT * FROM Assets` query and you'll see the table is empty - the old data was lost when you removed the container, and its volume was removed. The new container starts with a new database.
@@ -70,7 +72,7 @@ docker container rm --force assets-db
7072
7173
mkdir C:\mssql
7274
73-
docker container run -d -p 1433 --name assets-db --volume C:\mssql:C:\database dockersamples/assets-db:v1
75+
docker container run -d -p 1433:1433 --name assets-db --volume C:\mssql:C:\database dockersamples/assets-db:v1
7476
```
7577

7678
When the container has started, you can verify that the new database is created and the files are written to the host directory by listing the contents on the host:
@@ -82,16 +84,16 @@ When the container has started, you can verify that the new database is created
8284
8385
Mode LastWriteTime Length Name
8486
---- ------------- ------ ----
85-
-a---- 25/09/2017 16:20 8388608 AssetsDB_Primary.ldf
86-
-a---- 25/09/2017 16:20 8388608 AssetsDB_Primary.mdf
87+
-a---- 10/09/2018 15:13 8388608 AssetsDB_Primary.ldf
88+
-a---- 10/09/2018 15:13 8388608 AssetsDB_Primary.mdf
8789
```
8890

8991
Now you can inspect the container to get its IP address, connect and insert rows into the `Assets` table. The data will be stored outside of the container, in the directory on the host. You can replace the container without changing the schema - say you rebuild it with a new version of the base image to get the latest Windows updates. As long as you use the same volume mapping as the previous container, you'll retain all the data:
9092

9193
```PowerShell
9294
docker container rm -f assets-db
9395
94-
docker container run -d -p 1433 --name assets-db --volume C:\mssql:C:\database dockersamples/assets-db:v1
96+
docker container run -d -p 1433:1433 --name assets-db --volume C:\mssql:C:\database dockersamples/assets-db:v1
9597
```
9698

9799
This is a new container with a new file system, but the database ___location is mapped to the same host directory as the previous container. The setup script still runs, but it finds no differences in the current database schema and the schema definition in the Dacpac, so there's no diff script to apply.

windows/sql-server/part-4.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ Now you have two images locally, each packaging a separate version of the databa
3030
```PowerShell
3131
docker container rm -f assets-db
3232
33-
docker container run -d -p 1433 --name assets-db -v C:\mssql:C:\database dockersamples/assets-db:v2
33+
docker container run -d -p 1433:1433 --name assets-db -v C:\mssql:C:\database dockersamples/assets-db:v2
3434
```
3535

3636
When this new container starts, the init script attaches the existing data files and runs `SqlPackage`. Noe the schema is different from the Dacpac, so the tool generates a diff script to apply. Then it runs the script to update the schema - you can see the output in `docker container logs`:
@@ -46,7 +46,7 @@ VERBOSE: Creating [dbo].[FK_Assets_To_Users]...
4646
The container retains the upgrade script which `SqlPackage` generates, and you can read it from the container to see the exact SQL statements that were used in the upgrade:
4747

4848
```PowerShell
49-
docker container exec assets-db powershell cat C:\init\create.sql
49+
docker container exec assets-db powershell cat C:\init\deploy.sql
5050
```
5151

5252
For the v2 upgrade the script is 150+ lines of SQL, containing the DDL to update the schema, and the DML post-deployment scripts. The DDL includes the table changes and the new table, as in this snippet:

0 commit comments

Comments
 (0)