Docker NAV Images

OK, So I am late to this game but rather late than never. I recently started messing around with docker. My knowledge is still limited on the subject, but I wanted to get something going. This blog serves a purpose more in tracking my progress and reminding me of the how, what, and where, but if anyone else find this useful, that would be a bonus.

Lets begin…..

Since my current clients are mostly on NAV2016, I wanted to be able to spin up a docker container with my source code and run some automated tests. Later I will probably send the results somewhere and then stop the container all overnight with no human intervention, but for now the idea was just to get docker going.

This post assume you have docker installed and running on your machine already. If not, head over to Docker and get going.

Getting the right docker image

DockerHub has all the images you would need to get nav up and running in a container.

Before We could use these containers, we first need to install a Nifty little tool called the “navcontainerhelper“. This is as easy as running the following powershell command:

Install-Module -Name navcontainerhelper -force

As I said earlier, I needed a 2016 version of NAV, so I created a Powershell Script that would do this for me automatically…. Well I changed a Script first provided by a good friend of mine, Luc van Vught. – If you don’t know him yet (are you sure you use nav??), head over to his Blog (I left the comments in the Script below to show some additional option possible):

Update-Module -Name navcontainerhelper -force 

# set accept_eula to $true to accept the eula found here: https://go.microsoft.comfwlink/?linkid=861843
$accept_eula = $true

$doNotExportObjectsToText = $true

# container name and version
$containerName = 'NAV2016RTM'
$navdockerimage = 'microsoft/dynamics-nav:2016-rtm'
$licenseFile = "C:\DEV 2018.flf" # Training license
#$dbServer = 'NITRO-01'
#$dbInstance = 'NAVDEMO'
#$DBName = 'CRONUS'

# set credentials for using with NavUserPassword
 #$login = "UserName"
 #$password = "Password"
 #$securepassword = (ConvertTo-SecureString -String $password -AsPlainText -Force)
 #$credential = New-Object System.Management.Automation.PSCredential($login, $securepassword)

New-NavContainer -accept_eula:$accept_eula `
                 -containerName $containerName `
                 -imageName $navdockerimage `
                 -includeCSide `
                 -includeTestToolkit `
                 -doNotExportObjectsToText:$doNotExportObjectsToText `
                 -licenseFile $licenseFile `
                 -auth Windows `
                 -updateHosts `
                 #-credential $credential `
                 #-databaseServer  $dbServer `
                 #-databaseInstance $dbInstance `
                 #-databaseName $DBName

Your Container is Running

After running the above script successfully, you will have a running docker container with your chosen nav installed. It even places handy shortcuts on your desktop to access the Web Client / RTC Client, Dev Environment as well as powershell environment easily.

You can stop here if you like and manage everything from the docker container manually from here on, but I wanted to automate getting my code into the Docker container. Below is the route I followed. There is probably a plethora of better ways, but this is how I did it while I was learning. Hopefully I will come across better ways as I go along.

Bringing in my customized code into the docker Nav

What I decided to do was to export my objects from my development database and import it into the Docker container database. I also wanted to import my test code into the docker container database. To do this, I created a script that gets everything i need and move it into the docker container. Once everything is in the container, I will be executing a script in the container itself (copied there as part of the previous step). The script to do this looks as follows:

Write-Host -ForegroundColor Green "Importing NAV Dependancies"
Import-Module "C:\Program Files\Microsoft Dynamics NAV\90\Service\NavAdminTool.ps1"
Import-Module "C:\Program Files (x86)\Microsoft Dynamics NAV\90\RoleTailored Client\Microsoft.Dynamics.Nav.Model.Tools.psd1"


#Write-Host -ForegroundColor Green "Switch Working Location"
#Set-Location -Path $env:TEMP
Write-Host -ForegroundColor Green "Export All Objects from database as FOB"
Export-NAVApplicationObject -DatabaseName "2016-DEV" -DatabaseServer "MY-DEVSERVER" -Path $env:TEMP\ALL.fob -Force -Verbose


Write-Host -ForegroundColor Green "Combining Source into one Text file ALLTEST.TXT"
$ParentPath = (Get-Item .).Parent.FullName
Join-NAVApplicationObjectFile -Source $ParentPath\*.TXT -Destination $env:TEMP\ALLTEST.TXT -force

Write-Host -ForegroundColor Green "Copy All Files created into the Docker"
docker container cp .\ContainerScript.ps1 NAV2016RTM:C:\run
docker container cp $env:TEMP\ALL.fob NAV2016RTM:C:\run
docker container cp $env:TEMP\ALLTEST.TXT NAV2016RTM:C:\run

Write-Host -ForegroundColor Green "Execure Script in Docker"
C:\Windows\system32\CMD.EXE /C docker.exe exec -it NAV2016RTM powershell c:\run\ContainerScript.ps1

Some Paths are hard coded in the script. You are welcome to modify the script to take these as parameters but I just kept it as is for now.

The ContainerScript.ps1 file mentioned in the previous script, Uses the Files Moved into the container to do what I want to do. That being… Import my source and test code into the container database. The Content of the ContainerScript.ps1 file is pasted below:

Write-Host -ForegroundColor Green "Switch to Working Location in Docker"
Set-Location -Path "C:\run"

Write-Host -ForegroundColor Green "Importing NAV Dependancies into Docker"
Import-Module "C:\Program Files\Microsoft Dynamics NAV\90\Service\NavAdminTool.ps1"
Import-Module "C:\Program Files (x86)\Microsoft Dynamics NAV\90\RoleTailored Client\Microsoft.Dynamics.Nav.Model.Tools.psd1"

Write-Host -ForegroundColor Green "Changing Docker System Date to dd/MM/yyyy"
# I do this as my text export of objects is in this format
Set-ItemProperty -Path "HKCU:\Control Panel\International" -Name sShortDate -Value dd/MM/yyyy


Write-Host -ForegroundColor Green "Importing FOB File ALL.fob"
Import-NAVApplicationObject All.fob -DatabaseName CRONUS -DatabaseServer NAV2016RTM –Confirm:$false -ImportAction Overwrite -SynchronizeSchemaChanges No
Write-Host -ForegroundColor Green "Importing TEXT File ALLTEST.TXT"
Import-NAVApplicationObject AllTEST.TXT -DatabaseName CRONUS -DatabaseServer NAV2016RTM –Confirm:$false -ImportAction Overwrite -SynchronizeSchemaChanges No
Write-Host -ForegroundColor Green "Compile All Uncompiled"
Compile-NAVApplicationObject -DatabaseName CRONUS -DatabaseServer NAV2016RTM -NavServerInstance nav -SynchronizeSchemaChanges No -LogPath C:\run
Write-Host -ForegroundColor Green "Syncing the Schema"
Sync-NAVTenant -ServerInstance nav -Mode ForceSync -Force

Write-Host -ForegroundColor Green "ALL DONE"
Start-Sleep -s 5

And that is it… You can thread all these scripts together to update the container, get your source ready, Move it to the container and import it – all in one script. Once this is complete, you should have a running NAV Client on your custom source with test code imported and compiled.

If there is a better way of doing this, please let me know. My next Project on Docker will be to create my own image that contains my own database and not the standard CRONUS.

That however is for Next time

Have Fun

Leave a comment