microsoft / navcontainerhelper

Official Microsoft repository for BcContainerHelper, a PowerShell module, which makes it easier to work with Business Central Containers on Docker.
MIT License
381 stars 243 forks source link

Idea: DatabaseConversion before Service Tier start for external DBs #2223

Closed lktraser closed 2 years ago

lktraser commented 2 years ago

Describe the issue This is more of an idea than in issue but it would be great if we can improve the bccontainerhelper this way. Since we are using external DBs for some testing containers for a while now I'm getting more and more requests to also provide upgrade to these containers. I have since written a script to do just that but I have to take some very round about way to do so:

I have to do this because I cannot find a way to create a container of a new BC version against an existing DB of an old version since the Service Tier can't start due to the missing Database Conversion. Is there a way to run the Database Conversion before the Service Tier tries to start if the container is building against an older version DB? This would make upgrades a lot easier since I can skip the whole backup and restore process.

I would love to provide a PR for this but I wasn't able to figure out the correct location of the code.

freddydk commented 2 years ago

The problem with upgrades is that you need to uninstall and install apps as well - it isn't just a databaseconversion. this blog post https://freddysblog.com/2021/03/02/restoring-your-online-business-central-database-locally/ talks about how to mount a database from your online environment (which needs upgrade) on a container.

lktraser commented 2 years ago

That is correct but I'm aware of that. I solve it by uninstalling all apps before I backup the original Database.

I want to say again: My current upgrade process is working perfectly. I just wish there was a way to make it a bit more streamline. At the moment the newer version container creation fails because New-BCCotainer tries to start the Service Tier right away and fails because the database is not converted yet. This leads to it not completing lots of steps and makes the "new-version-container" useless to me. Output of container creation against an external DB with a lower version with all apps uninstalled:

BcContainerHelper is version 2.0.22
BcContainerHelper is running as administrator
Host is Microsoft Windows Server 2019 Datacenter - ltsc2019
Docker Client Version is 20.10.5
Docker Server Version is 20.10.5
Fetching all docker images
Fetching all docker volumes
ArtifactUrl and ImageName specified
Image sandbox-de-18.5.29545.29998:sandbox-18.5.29545.29998-de-nodb-mt already exists
Enabling SSL as otherwise all clients will see mixed HTTP / HTTPS request, which will cause problems e.g. on the mobile and modern windows clients
Using image sandbox-de-18.5.29545.29998:sandbox-18.5.29545.29998-de-nodb-mt
PublicDnsName is ***
Creating Container lkn
Style: sandbox
Multitenant: Yes
Version: 18.5.29545.29998
Platform: 18.0.29486.29981
Generic Tag: 1.0.1.7
Container OS Version: 10.0.17763.1935 (ltsc2019)
Host OS Version: 10.0.17763.1935 (ltsc2019)
Using process isolation
Using locale de-DE
Adding special CheckHealth.ps1 to enable Traefik support
Disabling the standard eventlog dump to container log every 2 seconds (use -dumpEventLog to enable)
Using license file ***
Additional Parameters:
***
-e webserverinstance=lkn
-e publicdnsname=***
-l "traefik.protocol=https"
-l "traefik.web.frontend.rule=PathPrefix:/lkn"
-l "traefik.web.port=443"
-l "traefik.soap.frontend.rule=PathPrefix:/lknsoap;ReplacePathRegex: ^/lknsoap(.*) /BC$1"
-l "traefik.soap.port=7047"
-l "traefik.rest.frontend.rule=PathPrefix:/lknrest;ReplacePathRegex: ^/lknrest(.*) /BC$1"
-l "traefik.rest.port=7048"
-l "traefik.dev.frontend.rule=PathPrefix:/lkndev;ReplacePathRegex: ^/lkndev(.*) /BC$1"
-l "traefik.dev.port=7049"
-l "traefik.snap.frontend.rule=PathPrefix:/lknsnap;ReplacePathRegex: ^/lknsnap(.*) /BC$1"
-l "traefik.snap.port=7083"
-l "traefik.dl.frontend.rule=PathPrefixStrip:/lkndl"
-l "traefik.dl.port=8080"
-l "traefik.dl.protocol=http"
-l "traefik.enable=true"
-l "traefik.frontend.entryPoints=https"
Files in C:\ProgramData\BcContainerHelper\Extensions\lkn\my:
- AdditionalOutput.ps1
- CheckHealth.ps1
- license.flf
- MainLoop.ps1
- SetupVariables.ps1
- updatehosts.ps1
Creating container lkn from image sandbox-de-18.5.29545.29998:sandbox-18.5.29545.29998-de-nodb-mt
Using Shared Encryption Key file
5a8325df2e998a2514678edf9cc426e5a34f4a90e37fddecfbca727584516715
Waiting for container lkn to be ready
Initializing...
Setting host.containerhelper.internal to 172.26.240.1 in container hosts file
Starting Container
Hostname is lkn
PublicDnsName is ***
Using NavUserPassword Authentication
Starting Internet Information Server
Import Encryption Key
The lkn-lkn database on the HOST.CONTAINERHELPER.INTERNAL server must be converted by using the Invoke-NAVApplicationDatabaseConversion cmdlet before you can use it with this version of Dynamics 365 Business Central.
at <ScriptBlock>, C:\Run\SetupDatabase.ps1: line 152
at <ScriptBlock>, C:\Run\navstart.ps1: line 122
at <ScriptBlock>, C:\Run\start.ps1: line 363
at <ScriptBlock>, <No file>: line 1Error
Initializing...
Setting host.containerhelper.internal to 172.26.240.1 in container hosts file
Starting Container
Hostname is lkn
PublicDnsName is ***
Using NavUserPassword Authentication
Starting Internet Information Server
Import Encryption Key
The lkn-lkn database on the HOST.CONTAINERHELPER.INTERNAL server must be converted by using the Invoke-NAVApplicationDatabaseConversion cmdlet before you can use it with this version of Dynamics 365 Business Central.
at <ScriptBlock>, C:\Run\SetupDatabase.ps1: line 152
at <ScriptBlock>, C:\Run\navstart.ps1: line 122
at <ScriptBlock>, C:\Run\start.ps1: line 363
at <ScriptBlock>, <No file>: line 1
Initialization of container lkn failed
At C:\Program Files\WindowsPowerShell\Modules\BcContainerHelper\2.0.22\ContainerHandling\Wait-NavContainerReady.ps1:42 char:17
+ ...             throw "Initialization of container $containerName failed" ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (Initialization of container lkn failed:String) [], RuntimeException
    + FullyQualifiedErrorId : Initialization of container lkn failed
freddydk commented 2 years ago

What you can do is to download this powershell script to your local machine:

https://github.com/microsoft/nav-docker/blob/master/generic/Run/SetupDatabase.ps1

and then add the code doing what you need in the right location and use -myscripts @("your file") when creating the container after that, you can share your setupdatabase.ps1 here and we can discuss what the right/best approach is to make this something that works "out-of-the-box"

OK?

lktraser commented 2 years ago

Awesome that's all I needed to know where to look. Thanks a lot. I'll get back to you

freddydk commented 2 years ago

It might be to just copy line 67 and insert it before line 152 (with databaseserver and credentials possibly)

lktraser commented 2 years ago

Thanks for the hint. The new container creates beautifully with this code added to the SetupDatabase.ps1 before the Import-NAVEncryptionKey:

$DatabaseName = 'lkn-lkn'
Invoke-NAVApplicationDatabaseConversion -DatabaseName $DatabaseName -DatabaseServer $databaseServerInstance -ApplicationDatabaseCredentials $DatabaseCredentials -Force | Out-Null

Problem is in that branch for existing external databases in SetupDatabase.ps1 the $DatabaseName variable is empty. How would I go about injecting the DB name into this script or detecting the database name?

Thanks a lot already

freddydk commented 2 years ago

Very strange... Your output above:

The lkn-lkn database on the HOST.CONTAINERHELPER.INTERNAL server must be converted by using the Invoke-NAVApplicationDatabaseConversion cmdlet before you can use it with this version of Dynamics 365 Business Central. at , C:\Run\SetupDatabase.ps1: line 152

states that it knows that databasename when trying to import the key. Have you changed your script from then? Can you provide your script here?

lktraser commented 2 years ago

I have just figured out how to get the DatabaseName during the runtime of SetupDatabase.ps1 The DatabaseName is just not filled in that segment of code. I'm guessing that the Encryption cmtlet figures out itself what databasename to use.

# INPUT
#     $restartingInstance (optional)
#     $bakFile (optional)
#     $appBacpac and tenantBacpac (optional)
#     $databaseCredentials (optional)
#
# OUTPUT
#     $databaseServer
#     $databaseInstance
#     $databaseName
#

if ($restartingInstance) {

    # Nothing to do

}
elseif ($bakfile -ne "") {

    # .bak file specified - restore and use
    # if bakfile specified, download, restore and use

    if ($bakfile.StartsWith("https://") -or $bakfile.StartsWith("http://")) {
        $bakfileurl = $bakfile
        $databaseFile = (Join-Path $runPath "mydatabase.bak")
        Write-Host "Downloading database backup file '$bakfileurl'"
        (New-Object System.Net.WebClient).DownloadFile($bakfileurl, $databaseFile)

    }
    else {

        Write-Host "Using Database .bak file '$bakfile'"
        if (!(Test-Path -Path $bakfile -PathType Leaf)) {
            Write-Error "ERROR: Database Backup File not found."
            Write-Error "The file must be uploaded to the container or available on a share."
            exit 1
        }
        $databaseFile = $bakFile
    }

    # Restore database
    $databaseFolder = "c:\databases\my"

    if (!(Test-Path -Path $databaseFolder -PathType Container)) {
        New-Item -Path $databaseFolder -itemtype Directory | Out-Null
    }

    $databaseServerInstance = $databaseServer
    if ("$databaseInstance" -ne "") {
        $databaseServerInstance += "\$databaseInstance"
    }
    Write-Host "Using database server $databaseServerInstance"

    if (!$multitenant) {
        New-NAVDatabase -DatabaseServer $databaseServer `
            -DatabaseInstance $databaseInstance `
            -DatabaseName "$databaseName" `
            -FilePath "$databaseFile" `
            -DestinationPath "$databaseFolder" `
            -Timeout $SqlTimeout | Out-Null

        Set-DatabaseCompatibilityLevel -DatabaseServer $databaseServer -DatabaseInstance $databaseInstance -DatabaseName $databaseName

        if ($roleTailoredClientFolder -and (Test-Path "$roleTailoredClientFolder\finsql.exe")) {
            Start-Process -FilePath "$roleTailoredClientFolder\finsql.exe" -ArgumentList "Command=upgradedatabase, Database=$databaseName, ServerName=$databaseServerInstance, ntauthentication=1, logFile=c:\run\errorlog.txt" -Wait
        }
        else {
            Invoke-NAVApplicationDatabaseConversion -databaseServer $databaseServerInstance -databaseName $databaseName -Force | Out-Null
        }
    }
    else {
        New-NAVDatabase -DatabaseServer $databaseServer `
            -DatabaseInstance $databaseInstance `
            -DatabaseName "tenant" `
            -FilePath "$databaseFile" `
            -DestinationPath "$databaseFolder" `
            -Timeout $SqlTimeout | Out-Null

        Set-DatabaseCompatibilityLevel -DatabaseServer $databaseServer -DatabaseInstance $databaseInstance -DatabaseName "tenant"

        if ($roleTailoredClientFolder -and (Test-Path "$roleTailoredClientFolder\finsql.exe")) {
            Start-Process -FilePath "$roleTailoredClientFolder\finsql.exe" -ArgumentList "Command=upgradedatabase, Database=$databaseName, ServerName=$databaseServerInstance, ntauthentication=1, logFile=c:\run\errorlog.txt" -Wait
        }
        else {
            Invoke-NAVApplicationDatabaseConversion -databaseServer $databaseServerInstance -databaseName "tenant" -force | Out-Null
        }

        Write-Host "Exporting Application to $DatabaseName"
        Invoke-sqlcmd -serverinstance $databaseServerInstance -Database "tenant" -query 'CREATE USER "NT AUTHORITY\SYSTEM" FOR LOGIN "NT AUTHORITY\SYSTEM";'
        Export-NAVApplication -DatabaseServer $DatabaseServer -DatabaseInstance $DatabaseInstance -DatabaseName "tenant" -DestinationDatabaseName $databaseName -Force -ServiceAccount 'NT AUTHORITY\SYSTEM' | Out-Null
        Write-Host "Removing Application from tenant"
        Remove-NAVApplication -DatabaseServer $DatabaseServer -DatabaseInstance $DatabaseInstance -DatabaseName "tenant" -Force | Out-Null
    }

}
elseif ("$appBacpac" -ne "") {

    # appBacpac and tenantBacpac specified - restore and use

    if (Test-NavDatabase -DatabaseName "tenant") {
        Remove-NavDatabase -DatabaseName "tenant"
    }
    if (Test-NavDatabase -DatabaseName "default") {
        Remove-NavDatabase -DatabaseName "default"
    }

    $dbName = "app"
    $appBacpac, $tenantBacpac | % {
        if ($_) {
            if ($_.StartsWith("https://") -or $_.StartsWith("http://")) {
                $databaseFile = (Join-Path $runPath "${dbName}.bacpac")
                Write-Host "Downloading ${dbName}.bacpac"
                (New-Object System.Net.WebClient).DownloadFile($_, $databaseFile)
            }
            else {
                if (!(Test-Path -Path $_ -PathType Leaf)) {
                    Write-Error "ERROR: Database Backup File not found."
                    Write-Error "The file must be uploaded to the container or available on a share."
                    exit 1
                }
                $databaseFile = $_
            }
            Restore-BacpacWithRetry -Bacpac $databaseFile -DatabaseName $dbName
        }
        $dbName = "tenant"
    }

    $databaseServer = "localhost"
    $databaseInstance = "SQLEXPRESS"
    $databaseName = "app"

    if ("$licenseFile" -eq "") {
        $licenseFile = Join-Path $serviceTierFolder "Cronus.flf"
    }

}
elseif ($databaseCredentials) {

    if (Test-Path $myPath -PathType Container) {
        $EncryptionKeyFile = Join-Path $myPath 'DynamicsNAV.key'
    }
    else {
        $EncryptionKeyFile = Join-Path $runPath 'DynamicsNAV.key'
    }
    if (!(Test-Path $EncryptionKeyFile -PathType Leaf)) {
        New-NAVEncryptionKey -KeyPath $EncryptionKeyFile -Password $EncryptionSecurePassword -Force | Out-Null
    }

    Set-NAVServerConfiguration -ServerInstance $ServerInstance -KeyName "EnableSqlConnectionEncryption" -KeyValue "true" -WarningAction SilentlyContinue
    Set-NAVServerConfiguration -ServerInstance $ServerInstance -KeyName "TrustSQLServerCertificate" -KeyValue "true" -WarningAction SilentlyContinue

    $databaseServerInstance = $databaseServer
    if ("$databaseInstance" -ne "") {
        $databaseServerInstance += "\$databaseInstance"
    }    

    $DatabaseName = Get-NavServerInstance | Get-NAVServerConfiguration -KeyName "DatabaseName"
    Invoke-NAVApplicationDatabaseConversion -DatabaseName $DatabaseName -DatabaseServer $databaseServerInstance -ApplicationDatabaseCredentials $DatabaseCredentials -Force | Out-Null

    Write-Host "Import Encryption Key"    
    Import-NAVEncryptionKey -ServerInstance $ServerInstance `
        -ApplicationDatabaseServer $databaseServerInstance `
        -ApplicationDatabaseCredentials $DatabaseCredentials `
        -ApplicationDatabaseName $DatabaseName `
        -KeyPath $EncryptionKeyFile `
        -Password $EncryptionSecurePassword `
        -WarningAction SilentlyContinue `
        -Force

    Set-NavServerConfiguration -serverinstance $ServerInstance -databaseCredentials $DatabaseCredentials -WarningAction SilentlyContinue

}
elseif ($databaseServer -eq "localhost" -and $databaseInstance -eq "SQLEXPRESS" -and $multitenant) {

    if (!(Test-NavDatabase -DatabaseName "tenant")) {
        Copy-NavDatabase -SourceDatabaseName $databaseName -DestinationDatabaseName "tenant"
        Remove-NavDatabase -DatabaseName $databaseName
        Write-Host "Exporting Application to $DatabaseName"
        Invoke-sqlcmd -serverinstance "$DatabaseServer\$DatabaseInstance" -Database tenant -query 'CREATE USER "NT AUTHORITY\SYSTEM" FOR LOGIN "NT AUTHORITY\SYSTEM";'
        Export-NAVApplication -DatabaseServer $DatabaseServer -DatabaseInstance $DatabaseInstance -DatabaseName "tenant" -DestinationDatabaseName $databaseName -Force -ServiceAccount 'NT AUTHORITY\SYSTEM' | Out-Null
        Write-Host "Removing Application from tenant"
        Remove-NAVApplication -DatabaseServer $DatabaseServer -DatabaseInstance $DatabaseInstance -DatabaseName "tenant" -Force | Out-Null
    }
}

The problem now becomes that the conversion may not run on first setup of the databases. I could work around this by just using this modified SetupDatabase.ps1 for upgrades but It would be nicer if we had a way to detect if a conversion is actually needed. That way everyone could profit from this change

BcContainerHelper is version 2.0.22
BcContainerHelper is running as administrator
Host is Microsoft Windows Server 2019 Datacenter - ltsc2019
Docker Client Version is 20.10.5
Docker Server Version is 20.10.5
Setting database lkn-tenant offline
Removing database lkn-tenant
Setting database lkn-lkn offline
Removing database lkn-lkn
Setting database lkn-default offline
Removing database lkn-default
Starting Database Restore job from https://bcartifacts.azureedge.net/sandbox/18.1.24822.33495/de
Fetching all docker images
Fetching all docker volumes
ArtifactUrl and ImageName specified
Image sandbox-de-18.1:sandbox-18.1.24822.33495-de-nodb-mt already exists
Enabling SSL as otherwise all clients will see mixed HTTP / HTTPS request, which will cause problems e.g. on the mobile and modern windows clients
Using image sandbox-de-18.1:sandbox-18.1.24822.33495-de-nodb-mt
PublicDnsName is ***
Creating Container lkn
Style: sandbox
Multitenant: Yes
Version: 18.1.24822.33495
Platform: 18.0.24800.33413
Generic Tag: 1.0.1.7
Container OS Version: 10.0.17763.1935 (ltsc2019)
Host OS Version: 10.0.17763.1935 (ltsc2019)
Using process isolation
Using locale de-DE
Adding special CheckHealth.ps1 to enable Traefik support
Disabling the standard eventlog dump to container log every 2 seconds (use -dumpEventLog to enable)
Using license file ***
Additional Parameters:
--env defaultTenantHasAllowAppDatabaseWrite=Y
***
-e webserverinstance=lkn
-e publicdnsname=***
-l "traefik.protocol=https"
-l "traefik.web.frontend.rule=PathPrefix:/lkn"
-l "traefik.web.port=443"
-l "traefik.soap.frontend.rule=PathPrefix:/lknsoap;ReplacePathRegex: ^/lknsoap(.*) /BC$1"
-l "traefik.soap.port=7047"
-l "traefik.rest.frontend.rule=PathPrefix:/lknrest;ReplacePathRegex: ^/lknrest(.*) /BC$1"
-l "traefik.rest.port=7048"
-l "traefik.dev.frontend.rule=PathPrefix:/lkndev;ReplacePathRegex: ^/lkndev(.*) /BC$1"
-l "traefik.dev.port=7049"
-l "traefik.snap.frontend.rule=PathPrefix:/lknsnap;ReplacePathRegex: ^/lknsnap(.*) /BC$1"
-l "traefik.snap.port=7083"
-l "traefik.dl.frontend.rule=PathPrefixStrip:/lkndl"
-l "traefik.dl.port=8080"
-l "traefik.dl.protocol=http"
-l "traefik.enable=true"
-l "traefik.frontend.entryPoints=https"
Files in C:\ProgramData\BcContainerHelper\Extensions\lkn\my:
- AdditionalOutput.ps1
- CheckHealth.ps1
- license.flf
- MainLoop.ps1
- SetupDatabase.ps1
- SetupVariables.ps1
- updatehosts.ps1
Creating container lkn from image sandbox-de-18.1:sandbox-18.1.24822.33495-de-nodb-mt
Using Shared Encryption Key file
8d46428ce98eb0f8b6e92abdb013d50d35fd489c5339927c00e85a72c27bb71c
Waiting for container lkn to be ready
Initializing...
Setting host.containerhelper.internal to 172.26.240.1 in container hosts file
Starting Container
Hostname is lkn
PublicDnsName is ***
Using NavUserPassword Authentication
Starting Internet Information Server
Get DatabaseName: CRONUS
Doing Conversion
Done Conversion
Import Encryption Key
Waiting for database creation to finish........................................
Import Encryption Key
Creating Self Signed Certificate
Self Signed Certificate Thumbprint ***
Modifying Service Tier Config File with Instance Specific Settings
Modifying Service Tier Config File with settings from environment variable
Setting ClientServicesMaxUploadSize to 2000
Setting EnableTaskScheduler to True
***
Starting Service Tier
Registering event sources
Creating DotNetCore Web Server Instance
Enabling Financials User Experience
Using license file 'c:\run\my\license.flf'
Import License
Creating http download site
Container IP Address: 172.26.252.150
Container Hostname  : lkn
Container Dns Name  : ***
Web Client          : ***
Dev. Server         : ***
Dev. ServerInstance : BC
Dev. Server Tenant  : default
Setting lkn to 172.26.252.150 in host hosts file

Files:
***

WARNING: You are running a container which is 209 days old.
Microsoft recommends that you always run the latest version of our containers.

Container Total Physical Memory is 383.9Gb
Container Free Physical Memory is 185.9Gb

Initialization took 67 seconds
Ready for connections!
Reading CustomSettings.config from lkn
Set TimeZone in Container to W. Europe Standard Time
Creating Desktop Shortcuts for lkn
Creating Tenant default on lkn
Copying Database on host.containerhelper.internal from lkn-tenant to lkn-default
EngineEdition 3
backup database [lkn-tenant] to disk = 'D:\DATA\lkn\lkn-tenant.bak' with init, stats=10;
restore database [lkn-default] from disk = 'D:\DATA\lkn\lkn-tenant.bak' with stats=10, recovery, move 'Navision_NAV_DE_Data' to 'D:\DATA\lkn\lkn-default.mdf', move 'Navision_NAV_DE_Log' to 'D:\DATA\lkn\lkn-default.ldf'
Mounting Database for default on server host.containerhelper.internal with AllowAppDatabaseWrite = True
The tenant default could not be mounted because the following installed NAV extensions are missing, matching content could not be found, or have a higher version than those that are published and synchronized: "Intelligent Cloud Base" by Microsoft, version 18.1.24822.33495
"System Application" by Microsoft, version 18.1.24822.33495
"Business Central Cloud Migration - Previous Release (DE)" by Microsoft, version 18.1.24822.33495
"Email - Microsoft 365 Connector" by Microsoft, version 18.1.24822.33495
"AMC Banking 365 Fundamentals" by Microsoft, version 18.1.24822.33495
"Email - Outlook REST API" by Microsoft, version 18.1.24822.33495
"Business Central Cloud Migration - Previous Release" by Microsoft, version 18.1.24822.33495
"Late Payment Prediction" by Microsoft, version 18.1.24822.33495
"_Exclude_APIV1_" by Microsoft, version 18.1.24822.33495
"WorldPay Payments Standard" by Microsoft, version 18.1.24822.33495
"_Exclude_Microsoft Dynamics 365 - SmartList" by Microsoft, version 18.1.24822.33495
"PayPal Payments Standard" by Microsoft, version 18.1.24822.33495
"Universal Print Integration (Preview)" by Microsoft, version 18.1.24822.33495
"_Exclude_AnonymizedDataSharing_" by Microsoft, version 18.1.24822.33495
"Application" by Microsoft, version 18.1.24822.33495
"Business Central Intelligent Cloud" by Microsoft, version 18.1.24822.33495
"ELSTER VAT Localization for Germany" by Microsoft, version 18.1.24822.33495
"Simplified Bank Statement Import" by Microsoft, version 18.1.24822.33495
"Email - Current User Connector" by Microsoft, version 18.1.24822.33495
"Email - SMTP Connector" by Microsoft, version 18.1.24822.33495
"_Exclude_APIV2_" by Microsoft, version 18.1.24822.33495
"Company Hub" by Microsoft, version 18.1.24822.33495
"Send To Email Printer" by Microsoft, version 18.1.24822.33495
"_Exclude_ClientAddIns_" by Microsoft, version 18.1.24822.33495
"Essential Business Headlines" by Microsoft, version 18.1.24822.33495
"Base Application" by Microsoft, version 18.1.24822.33495
"_Exclude_SyncBaseApp_" by Microsoft, version 18.1.24822.33495
"Sales and Inventory Forecast" by Microsoft, version 18.1.24822.33495.
at Mount-NavDatabase, C:\Run\HelperFunctions.ps1: line 371
at <ScriptBlock>, <No file>: line 34
at Invoke-ScriptInBcContainer, C:\Program Files\WindowsPowerShell\Modules\BcContainerHelper\2.0.22\ContainerHandling\Invoke-ScriptInNavContainer.ps1: line 43
at New-BcContainerTenant, C:\Program Files\WindowsPowerShell\Modules\BcContainerHelper\2.0.22\TenantHandling\New-NavContainerTenant.ps1: line 49
at New-BcContainer, C:\Program Files\WindowsPowerShell\Modules\BcContainerHelper\2.0.22\ContainerHandling\New-NavContainer.ps1: line 2180
at Create-ALContainer, C:\Program Files\WindowsPowerShell\Modules\TraserBCHelper\1.0.161\ContainerHandling\Create-ALContainer.ps1: line 194
at <ScriptBlock>, <No file>: line 1
The tenant default could not be mounted because the following installed NAV extensions are missing, matching content could not be found, or have a higher version than those that are published and 
synchronized: "Intelligent Cloud Base" by Microsoft, version 18.1.24822.33495
"System Application" by Microsoft, version 18.1.24822.33495
"Business Central Cloud Migration - Previous Release (DE)" by Microsoft, version 18.1.24822.33495
"Email - Microsoft 365 Connector" by Microsoft, version 18.1.24822.33495
"AMC Banking 365 Fundamentals" by Microsoft, version 18.1.24822.33495
"Email - Outlook REST API" by Microsoft, version 18.1.24822.33495
"Business Central Cloud Migration - Previous Release" by Microsoft, version 18.1.24822.33495
"Late Payment Prediction" by Microsoft, version 18.1.24822.33495
"_Exclude_APIV1_" by Microsoft, version 18.1.24822.33495
"WorldPay Payments Standard" by Microsoft, version 18.1.24822.33495
"_Exclude_Microsoft Dynamics 365 - SmartList" by Microsoft, version 18.1.24822.33495
"PayPal Payments Standard" by Microsoft, version 18.1.24822.33495
"Universal Print Integration (Preview)" by Microsoft, version 18.1.24822.33495
"_Exclude_AnonymizedDataSharing_" by Microsoft, version 18.1.24822.33495
"Application" by Microsoft, version 18.1.24822.33495
"Business Central Intelligent Cloud" by Microsoft, version 18.1.24822.33495
"ELSTER VAT Localization for Germany" by Microsoft, version 18.1.24822.33495
"Simplified Bank Statement Import" by Microsoft, version 18.1.24822.33495
"Email - Current User Connector" by Microsoft, version 18.1.24822.33495
"Email - SMTP Connector" by Microsoft, version 18.1.24822.33495
"_Exclude_APIV2_" by Microsoft, version 18.1.24822.33495
"Company Hub" by Microsoft, version 18.1.24822.33495
"Send To Email Printer" by Microsoft, version 18.1.24822.33495
"_Exclude_ClientAddIns_" by Microsoft, version 18.1.24822.33495
"Essential Business Headlines" by Microsoft, version 18.1.24822.33495
"Base Application" by Microsoft, version 18.1.24822.33495
"_Exclude_SyncBaseApp_" by Microsoft, version 18.1.24822.33495
"Sales and Inventory Forecast" by Microsoft, version 18.1.24822.33495.
At C:\Program Files\WindowsPowerShell\Modules\BcContainerHelper\2.0.22\ContainerHandling\Invoke-ScriptInNavContainer.ps1:44 char:13
+             throw $_.Exception.Message
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (The tenant defa....1.24822.33495.:String) [], RuntimeException
    + FullyQualifiedErrorId : The tenant default could not be mounted because the following installed NAV extensions are missing, matching content could not be found, or have a higher version than those that 
    are published and synchronized: "Intelligent Cloud Base" by Microsoft, version 18.1.24822.33495
"System Application" by Microsoft, version 18.1.24822.33495
"Business Central Cloud Migration - Previous Release (DE)" by Microsoft, version 18.1.24822.33495
"Email - Microsoft 365 Connector" by Microsoft, version 18.1.24822.33495
"AMC Banking 365 Fundamentals" by Microsoft, version 18.1.24822.33495
"Email - Outlook REST API" by Microsoft, version 18.1.24822.33495
"Business Central Cloud Migration - Previous Release" by Microsoft, version 18.1.24822.33495
"Late Payment Prediction" by Microsoft, version 18.1.24822.33495
"_Exclude_APIV1_" by Microsoft, version 18.1.24822.33495
"WorldPay Payments Standard" by Microsoft, version 18.1.24822.33495
"_Exclude_Microsoft Dynamics 365 - SmartList" by Microsoft, version 18.1.24822.33495
"PayPal Payments Standard" by Microsoft, version 18.1.24822.33495
"Universal Print Integration (Preview)" by Microsoft, version 18.1.24822.33495
"_Exclude_AnonymizedDataSharing_" by Microsoft, version 18.1.24822.33495
"Application" by Microsoft, version 18.1.24822.33495
"Business Central Intelligent Cloud" by Microsoft, version 18.1.24822.33495
"ELSTER VAT Localization for Germany" by Microsoft, version 18.1.24822.33495
"Simplified Bank Statement Import" by Microsoft, version 18.1.24822.33495
"Email - Current User Connector" by Microsoft, version 18.1.24822.33495
"Email - SMTP Connector" by Microsoft, version 18.1.24822.33495
"_Exclude_APIV2_" by Microsoft, version 18.1.24822.33495
"Company Hub" by Microsoft, version 18.1.24822.33495
"Send To Email Printer" by Microsoft, version 18.1.24822.33495
"_Exclude_ClientAddIns_" by Microsoft, version 18.1.24822.33495
"Essential Business Headlines" by Microsoft, version 18.1.24822.33495
"Base Application" by Microsoft, version 18.1.24822.33495
"_Exclude_SyncBaseApp_" by Microsoft, version 18.1.24822.33495
"Sales and Inventory Forecast" by Microsoft, version 18.1.24822.33495.
git-no commented 2 years ago

There is an alternativ procedure without using massiv scripts:

  1. Create and start the new BC docker container with an internal database.
  2. Stop the NAV service. If you want you also deactivate the internal SQL service.
  3. Convert the external database from the container.
  4. Reset the service connection within the container from internal to external SQL database (if you do not have the server security key you just create one).
  5. Start the NAV service in the container to connect to the previously converted external database (or restart the container).

From performance perspective it is better to store the database outside of the container.

lktraser commented 2 years ago

@git-no Thanks, sounds like an interesting approach although a lot more complicated than the workaround with the changed SetupDatabase.ps1 I have now. @freddydk Can you think of a way we can integrate this into the default SetupDatabase.ps1?

StijnBt commented 2 years ago

@lktraser I'm trying to combine your script with this

But I'm experiencing the same problem with retrieving the name of the external database. It isn't CRONUS in my case

image

freddydk commented 2 years ago

In the above screenshot - you read the database name from the config file (line 159) During startup of a container, the config file isn't yet updated - that happens AFTER SetupDatabase.ps1 The script assumes databaseName to be in the databaseName variable already - you should just remove line 159 (I guess)

StijnBt commented 2 years ago

Thanks for the response, I tried it but with no luck. Then I tried the approach git-no proposed and it works perfectly. The end result is that I have a fully docker based upgrade on an external sql (version of choice). That's what I wanted to achieve, so I'm very happy with what docker & bccontainerhelper is bringing to the table. Keep up the great work Freddy!