775 lines
21 KiB
PowerShell
775 lines
21 KiB
PowerShell
|
|
############################################################
|
|
# Script to install the community edition of docker on Windows
|
|
############################################################
|
|
|
|
<#
|
|
.NOTES
|
|
Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
Use of this sample source code is subject to the terms of the Microsoft
|
|
license agreement under which you licensed this sample source code. If
|
|
you did not accept the terms of the license agreement, you are not
|
|
authorized to use this sample source code. For the terms of the license,
|
|
please see the license agreement between you and Microsoft or, if applicable,
|
|
see the LICENSE.RTF on your install media or the root of your tools installation.
|
|
THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
|
|
|
|
.SYNOPSIS
|
|
Installs the prerequisites for creating Windows containers
|
|
|
|
.DESCRIPTION
|
|
Installs the prerequisites for creating Windows containers
|
|
|
|
.PARAMETER DockerPath
|
|
Path to Docker.exe, can be local or URI
|
|
|
|
.PARAMETER DockerDPath
|
|
Path to DockerD.exe, can be local or URI
|
|
|
|
.PARAMETER DockerVersion
|
|
Version of docker to pull from download.docker.com - ! OVERRIDDEN BY DockerPath & DockerDPath
|
|
|
|
.PARAMETER ExternalNetAdapter
|
|
Specify a specific network adapter to bind to a DHCP network
|
|
|
|
.PARAMETER SkipDefaultHost
|
|
Prevents setting localhost as the default network configuration
|
|
|
|
.PARAMETER Force
|
|
If a restart is required, forces an immediate restart.
|
|
|
|
.PARAMETER HyperV
|
|
If passed, prepare the machine for Hyper-V containers
|
|
|
|
.PARAMETER NATSubnet
|
|
Use to override the default Docker NAT Subnet when in NAT mode.
|
|
|
|
.PARAMETER NoRestart
|
|
If a restart is required the script will terminate and will not reboot the machine
|
|
|
|
.PARAMETER ContainerBaseImage
|
|
Use this to specify the URI of the container base image you wish to pre-pull
|
|
|
|
.PARAMETER Staging
|
|
|
|
.PARAMETER TransparentNetwork
|
|
If passed, use DHCP configuration. Otherwise, will use default docker network (NAT). (alias -UseDHCP)
|
|
|
|
.PARAMETER TarPath
|
|
Path to the .tar that is the base image to load into Docker.
|
|
|
|
.EXAMPLE
|
|
.\install-docker-ce.ps1
|
|
|
|
#>
|
|
#Requires -Version 5.0
|
|
|
|
[CmdletBinding(DefaultParameterSetName="Standard")]
|
|
param(
|
|
[string]
|
|
[ValidateNotNullOrEmpty()]
|
|
$DockerPath = "default",
|
|
|
|
[string]
|
|
[ValidateNotNullOrEmpty()]
|
|
$DockerDPath = "default",
|
|
|
|
[string]
|
|
[ValidateNotNullOrEmpty()]
|
|
$DockerVersion = "latest",
|
|
|
|
[string]
|
|
$ExternalNetAdapter,
|
|
|
|
[switch]
|
|
$Force,
|
|
|
|
[switch]
|
|
$HyperV,
|
|
|
|
[switch]
|
|
$SkipDefaultHost,
|
|
|
|
[string]
|
|
$NATSubnet,
|
|
|
|
[switch]
|
|
$NoRestart,
|
|
|
|
[string]
|
|
$ContainerBaseImage,
|
|
|
|
[Parameter(ParameterSetName="Staging", Mandatory)]
|
|
[switch]
|
|
$Staging,
|
|
|
|
[switch]
|
|
[alias("UseDHCP")]
|
|
$TransparentNetwork,
|
|
|
|
[string]
|
|
[ValidateNotNullOrEmpty()]
|
|
$TarPath
|
|
)
|
|
|
|
$global:RebootRequired = $false
|
|
$global:ErrorFile = "$pwd\Install-ContainerHost.err"
|
|
$global:BootstrapTask = "ContainerBootstrap"
|
|
$global:HyperVImage = "NanoServer"
|
|
$global:AdminPriviledges = $false
|
|
|
|
$global:DefaultDockerLocation = "https://download.docker.com/win/static/stable/x86_64/"
|
|
$global:DockerDataPath = "$($env:ProgramData)\docker"
|
|
$global:DockerServiceName = "docker"
|
|
|
|
function
|
|
Restart-And-Run()
|
|
{
|
|
Test-Admin
|
|
|
|
Write-Output "Restart is required; restarting now..."
|
|
|
|
$argList = $script:MyInvocation.Line.replace($script:MyInvocation.InvocationName, "")
|
|
|
|
#
|
|
# Update .\ to the invocation directory for the bootstrap
|
|
#
|
|
$scriptPath = $script:MyInvocation.MyCommand.Path
|
|
|
|
$argList = $argList -replace "\.\\", "$pwd\"
|
|
|
|
if ((Split-Path -Parent -Path $scriptPath) -ne $pwd)
|
|
{
|
|
$sourceScriptPath = $scriptPath
|
|
$scriptPath = "$pwd\$($script:MyInvocation.MyCommand.Name)"
|
|
|
|
Copy-Item $sourceScriptPath $scriptPath
|
|
}
|
|
|
|
Write-Output "Creating scheduled task action ($scriptPath $argList)..."
|
|
$action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoExit $scriptPath $argList"
|
|
|
|
Write-Output "Creating scheduled task trigger..."
|
|
$trigger = New-ScheduledTaskTrigger -AtLogOn
|
|
|
|
Write-Output "Registering script to re-run at next user logon..."
|
|
Register-ScheduledTask -TaskName $global:BootstrapTask -Action $action -Trigger $trigger -RunLevel Highest | Out-Null
|
|
|
|
try
|
|
{
|
|
if ($Force)
|
|
{
|
|
Restart-Computer -Force
|
|
}
|
|
else
|
|
{
|
|
Restart-Computer
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
Write-Error $_
|
|
|
|
Write-Output "Please restart your computer manually to continue script execution."
|
|
}
|
|
|
|
exit
|
|
}
|
|
|
|
|
|
function
|
|
Install-Feature
|
|
{
|
|
[CmdletBinding()]
|
|
param(
|
|
[ValidateNotNullOrEmpty()]
|
|
[string]
|
|
$FeatureName
|
|
)
|
|
|
|
Write-Output "Querying status of Windows feature: $FeatureName..."
|
|
if (Get-Command Get-WindowsFeature -ErrorAction SilentlyContinue)
|
|
{
|
|
if ((Get-WindowsFeature $FeatureName).Installed)
|
|
{
|
|
Write-Output "Feature $FeatureName is already enabled."
|
|
}
|
|
else
|
|
{
|
|
Test-Admin
|
|
|
|
Write-Output "Enabling feature $FeatureName..."
|
|
}
|
|
|
|
$featureInstall = Add-WindowsFeature $FeatureName
|
|
|
|
if ($featureInstall.RestartNeeded -eq "Yes")
|
|
{
|
|
$global:RebootRequired = $true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((Get-WindowsOptionalFeature -Online -FeatureName $FeatureName).State -eq "Disabled")
|
|
{
|
|
if (Test-Nano)
|
|
{
|
|
throw "This NanoServer deployment does not include $FeatureName. Please add the appropriate package"
|
|
}
|
|
|
|
Test-Admin
|
|
|
|
Write-Output "Enabling feature $FeatureName..."
|
|
$feature = Enable-WindowsOptionalFeature -Online -FeatureName $FeatureName -All -NoRestart
|
|
|
|
if ($feature.RestartNeeded -eq "True")
|
|
{
|
|
$global:RebootRequired = $true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Write-Output "Feature $FeatureName is already enabled."
|
|
|
|
if (Test-Nano)
|
|
{
|
|
#
|
|
# Get-WindowsEdition is not present on Nano. On Nano, we assume reboot is not needed
|
|
#
|
|
}
|
|
elseif ((Get-WindowsEdition -Online).RestartNeeded)
|
|
{
|
|
$global:RebootRequired = $true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
function
|
|
New-ContainerTransparentNetwork
|
|
{
|
|
# Check if transparent network already created
|
|
$networkList = docker network ls
|
|
if ($networkList -match '\bTransparent\b')
|
|
{
|
|
Write-Output "Network with the name Transparent exists."
|
|
return
|
|
}
|
|
|
|
# Continue with network creation
|
|
if ($ExternalNetAdapter)
|
|
{
|
|
$netAdapter = (Get-NetAdapter |? {$_.Name -eq "$ExternalNetAdapter"})[0]
|
|
}
|
|
else
|
|
{
|
|
$netAdapter = (Get-NetAdapter |? {($_.Status -eq 'Up') -and ($_.ConnectorPresent)})[0]
|
|
}
|
|
|
|
Write-Output "Creating container network (Transparent)..."
|
|
docker network create -d transparent -o com.docker.network.windowsshim.interface="$($netAdapter.Name)" "Transparent"
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "Failed to create transparent network."
|
|
}
|
|
|
|
# Transparent networks are not picked up by docker until after a service restart.
|
|
if (Test-Docker)
|
|
{
|
|
Restart-Service -Name $global:DockerServiceName
|
|
Wait-Docker
|
|
}
|
|
}
|
|
|
|
|
|
function
|
|
Install-ContainerHost
|
|
{
|
|
"If this file exists when Install-ContainerHost.ps1 exits, the script failed!" | Out-File -FilePath $global:ErrorFile
|
|
|
|
if (Test-Client)
|
|
{
|
|
if (-not $HyperV)
|
|
{
|
|
Write-Output "Enabling Hyper-V containers by default for Client SKU"
|
|
$HyperV = $true
|
|
}
|
|
}
|
|
#
|
|
# Validate required Windows features
|
|
#
|
|
Install-Feature -FeatureName Containers
|
|
|
|
if ($HyperV)
|
|
{
|
|
Install-Feature -FeatureName Hyper-V
|
|
}
|
|
|
|
if ($global:RebootRequired)
|
|
{
|
|
if ($NoRestart)
|
|
{
|
|
Write-Warning "A reboot is required; stopping script execution"
|
|
exit
|
|
}
|
|
|
|
Restart-And-Run
|
|
}
|
|
|
|
#
|
|
# Unregister the bootstrap task, if it was previously created
|
|
#
|
|
if ((Get-ScheduledTask -TaskName $global:BootstrapTask -ErrorAction SilentlyContinue) -ne $null)
|
|
{
|
|
Unregister-ScheduledTask -TaskName $global:BootstrapTask -Confirm:$false
|
|
}
|
|
|
|
#
|
|
# Install, register, and start Docker
|
|
#
|
|
if (Test-Docker)
|
|
{
|
|
Write-Output "Docker is already installed."
|
|
}
|
|
else
|
|
{
|
|
if ($NATSubnet)
|
|
{
|
|
Install-Docker -DockerPath $DockerPath -DockerDPath $DockerDPath -NATSubnet $NATSubnet -ContainerBaseImage $ContainerBaseImage
|
|
}
|
|
else
|
|
{
|
|
Install-Docker -DockerPath $DockerPath -DockerDPath $DockerDPath -ContainerBaseImage $ContainerBaseImage
|
|
}
|
|
}
|
|
|
|
#
|
|
# Configure networking
|
|
#
|
|
if ($($PSCmdlet.ParameterSetName) -ne "Staging")
|
|
{
|
|
if ($TransparentNetwork)
|
|
{
|
|
Write-Output "Waiting for Hyper-V Management..."
|
|
$networks = $null
|
|
|
|
try
|
|
{
|
|
$networks = Get-ContainerNetwork -ErrorAction SilentlyContinue
|
|
}
|
|
catch
|
|
{
|
|
#
|
|
# If we can't query network, we are in bootstrap mode. Assume no networks
|
|
#
|
|
}
|
|
|
|
if ($networks.Count -eq 0)
|
|
{
|
|
Write-Output "Enabling container networking..."
|
|
New-ContainerTransparentNetwork
|
|
}
|
|
else
|
|
{
|
|
Write-Output "Networking is already configured. Confirming configuration..."
|
|
|
|
$transparentNetwork = $networks |? { $_.Mode -eq "Transparent" }
|
|
|
|
if ($transparentNetwork -eq $null)
|
|
{
|
|
Write-Output "We didn't find a configured external network; configuring now..."
|
|
New-ContainerTransparentNetwork
|
|
}
|
|
else
|
|
{
|
|
if ($ExternalNetAdapter)
|
|
{
|
|
$netAdapters = (Get-NetAdapter |? {$_.Name -eq "$ExternalNetAdapter"})
|
|
|
|
if ($netAdapters.Count -eq 0)
|
|
{
|
|
throw "No adapters found that match the name $ExternalNetAdapter"
|
|
}
|
|
|
|
$netAdapter = $netAdapters[0]
|
|
$transparentNetwork = $networks |? { $_.NetworkAdapterName -eq $netAdapter.InterfaceDescription }
|
|
|
|
if ($transparentNetwork -eq $null)
|
|
{
|
|
throw "One or more external networks are configured, but not on the requested adapter ($ExternalNetAdapter)"
|
|
}
|
|
|
|
Write-Output "Configured transparent network found: $($transparentNetwork.Name)"
|
|
}
|
|
else
|
|
{
|
|
Write-Output "Configured transparent network found: $($transparentNetwork.Name)"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($TarPath)
|
|
{
|
|
cmd /c "docker load -i `"$TarPath`""
|
|
}
|
|
|
|
Remove-Item $global:ErrorFile
|
|
|
|
Write-Output "Script complete!"
|
|
}
|
|
|
|
function
|
|
Copy-File
|
|
{
|
|
[CmdletBinding()]
|
|
param(
|
|
[string]
|
|
$SourcePath,
|
|
|
|
[string]
|
|
$DestinationPath
|
|
)
|
|
|
|
if ($SourcePath -eq $DestinationPath)
|
|
{
|
|
return
|
|
}
|
|
|
|
if (Test-Path $SourcePath)
|
|
{
|
|
Copy-Item -Path $SourcePath -Destination $DestinationPath
|
|
}
|
|
elseif (($SourcePath -as [System.URI]).AbsoluteURI -ne $null)
|
|
{
|
|
if (Test-Nano)
|
|
{
|
|
$handler = New-Object System.Net.Http.HttpClientHandler
|
|
$client = New-Object System.Net.Http.HttpClient($handler)
|
|
$client.Timeout = New-Object System.TimeSpan(0, 30, 0)
|
|
$cancelTokenSource = [System.Threading.CancellationTokenSource]::new()
|
|
$responseMsg = $client.GetAsync([System.Uri]::new($SourcePath), $cancelTokenSource.Token)
|
|
$responseMsg.Wait()
|
|
|
|
if (!$responseMsg.IsCanceled)
|
|
{
|
|
$response = $responseMsg.Result
|
|
if ($response.IsSuccessStatusCode)
|
|
{
|
|
$downloadedFileStream = [System.IO.FileStream]::new($DestinationPath, [System.IO.FileMode]::Create, [System.IO.FileAccess]::Write)
|
|
$copyStreamOp = $response.Content.CopyToAsync($downloadedFileStream)
|
|
$copyStreamOp.Wait()
|
|
$downloadedFileStream.Close()
|
|
if ($copyStreamOp.Exception -ne $null)
|
|
{
|
|
throw $copyStreamOp.Exception
|
|
}
|
|
}
|
|
}
|
|
}
|
|
elseif ($PSVersionTable.PSVersion.Major -ge 5)
|
|
{
|
|
#
|
|
# We disable progress display because it kills performance for large downloads (at least on 64-bit PowerShell)
|
|
#
|
|
$ProgressPreference = 'SilentlyContinue'
|
|
Invoke-WebRequest -Uri $SourcePath -OutFile $DestinationPath -UseBasicParsing
|
|
$ProgressPreference = 'Continue'
|
|
}
|
|
else
|
|
{
|
|
$webClient = New-Object System.Net.WebClient
|
|
$webClient.DownloadFile($SourcePath, $DestinationPath)
|
|
}
|
|
}
|
|
else
|
|
{
|
|
throw "Cannot copy from $SourcePath"
|
|
}
|
|
}
|
|
|
|
|
|
function
|
|
Test-Admin()
|
|
{
|
|
# Get the ID and security principal of the current user account
|
|
$myWindowsID=[System.Security.Principal.WindowsIdentity]::GetCurrent()
|
|
$myWindowsPrincipal=new-object System.Security.Principal.WindowsPrincipal($myWindowsID)
|
|
|
|
# Get the security principal for the Administrator role
|
|
$adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator
|
|
|
|
# Check to see if we are currently running "as Administrator"
|
|
if ($myWindowsPrincipal.IsInRole($adminRole))
|
|
{
|
|
$global:AdminPriviledges = $true
|
|
return
|
|
}
|
|
else
|
|
{
|
|
#
|
|
# We are not running "as Administrator"
|
|
# Exit from the current, unelevated, process
|
|
#
|
|
throw "You must run this script as administrator"
|
|
}
|
|
}
|
|
|
|
|
|
function
|
|
Test-Client()
|
|
{
|
|
return (-not ((Get-Command Get-WindowsFeature -ErrorAction SilentlyContinue) -or (Test-Nano)))
|
|
}
|
|
|
|
|
|
function
|
|
Test-Nano()
|
|
{
|
|
$EditionId = (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' -Name 'EditionID').EditionId
|
|
|
|
return (($EditionId -eq "ServerStandardNano") -or
|
|
($EditionId -eq "ServerDataCenterNano") -or
|
|
($EditionId -eq "NanoServer") -or
|
|
($EditionId -eq "ServerTuva"))
|
|
}
|
|
|
|
|
|
function
|
|
Wait-Network()
|
|
{
|
|
$connectedAdapter = Get-NetAdapter |? ConnectorPresent
|
|
|
|
if ($connectedAdapter -eq $null)
|
|
{
|
|
throw "No connected network"
|
|
}
|
|
|
|
$startTime = Get-Date
|
|
$timeElapsed = $(Get-Date) - $startTime
|
|
|
|
while ($($timeElapsed).TotalMinutes -lt 5)
|
|
{
|
|
$readyNetAdapter = $connectedAdapter |? Status -eq 'Up'
|
|
|
|
if ($readyNetAdapter -ne $null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Write-Output "Waiting for network connectivity..."
|
|
Start-Sleep -sec 5
|
|
|
|
$timeElapsed = $(Get-Date) - $startTime
|
|
}
|
|
|
|
throw "Network not connected after 5 minutes"
|
|
}
|
|
|
|
|
|
function
|
|
Install-Docker()
|
|
{
|
|
[CmdletBinding()]
|
|
param(
|
|
[string]
|
|
[ValidateNotNullOrEmpty()]
|
|
$DockerPath = "default",
|
|
|
|
[string]
|
|
[ValidateNotNullOrEmpty()]
|
|
$DockerDPath = "default",
|
|
|
|
[string]
|
|
[ValidateNotNullOrEmpty()]
|
|
$NATSubnet,
|
|
|
|
[switch]
|
|
$SkipDefaultHost,
|
|
|
|
[string]
|
|
$ContainerBaseImage
|
|
)
|
|
|
|
Test-Admin
|
|
|
|
#If one of these are set to default then the whole .zip needs to be downloaded anyways.
|
|
Write-Output "DOCKER $DockerPath"
|
|
if ($DockerPath -eq "default" -or $DockerDPath -eq "default") {
|
|
Write-Output "Checking Docker versions"
|
|
#Get the list of .zip packages available from docker.
|
|
$availableVersions = ((Invoke-WebRequest -Uri $DefaultDockerLocation -UseBasicParsing).Links | Where-Object {$_.href -like "docker*"}).href | Sort-Object -Descending
|
|
|
|
#Parse the versions from the file names
|
|
$availableVersions = ($availableVersions | Select-String -Pattern "docker-(\d+\.\d+\.\d+).+" -AllMatches | Select-Object -Expand Matches | %{ $_.Groups[1].Value })
|
|
$version = $availableVersions[0]
|
|
|
|
if($DockerVersion -ne "latest") {
|
|
$version = $DockerVersion
|
|
if(!($availableVersions | Select-String $DockerVersion)) {
|
|
Write-Error "Docker version supplied $DockerVersion was invalid, please choose from the list of available versions: $availableVersions"
|
|
throw "Invalid docker version supplied."
|
|
}
|
|
}
|
|
|
|
$zipUrl = $global:DefaultDockerLocation + "docker-$version.zip"
|
|
$destinationFolder = "$env:UserProfile\DockerDownloads"
|
|
|
|
if(!(Test-Path "$destinationFolder")) {
|
|
md -Path $destinationFolder | Out-Null
|
|
} elseif(Test-Path "$destinationFolder\docker-$version") {
|
|
Remove-Item -Recurse -Force "$destinationFolder\docker-$version"
|
|
}
|
|
|
|
Write-Output "Downloading $zipUrl to $destinationFolder\docker-$version.zip"
|
|
Copy-File -SourcePath $zipUrl -DestinationPath "$destinationFolder\docker-$version.zip"
|
|
|
|
#Prevent issues with CLI non-interactive execution on Window Server 2019
|
|
$global:ProgressPreference = "SilentlyContinue"
|
|
Expand-Archive -Path "$destinationFolder\docker-$version.zip" -DestinationPath "$destinationFolder\docker-$version"
|
|
$global:ProgressPreference = "Continue"
|
|
|
|
if($DockerPath -eq "default") {
|
|
$DockerPath = "$destinationFolder\docker-$version\docker\docker.exe"
|
|
}
|
|
if($DockerDPath -eq "default") {
|
|
$DockerDPath = "$destinationFolder\docker-$version\docker\dockerd.exe"
|
|
}
|
|
}
|
|
|
|
Write-Output "Installing Docker... $DockerPath"
|
|
Copy-File -SourcePath $DockerPath -DestinationPath $env:windir\System32\docker.exe
|
|
|
|
Write-Output "Installing Docker daemon... $DockerDPath"
|
|
Copy-File -SourcePath $DockerDPath -DestinationPath $env:windir\System32\dockerd.exe
|
|
|
|
$dockerConfigPath = Join-Path $global:DockerDataPath "config"
|
|
|
|
if (!(Test-Path $dockerConfigPath))
|
|
{
|
|
md -Path $dockerConfigPath | Out-Null
|
|
}
|
|
|
|
#
|
|
# Register the docker service.
|
|
# Configuration options should be placed at %programdata%\docker\config\daemon.json
|
|
#
|
|
Write-Output "Configuring the docker service..."
|
|
|
|
$daemonSettings = New-Object PSObject
|
|
|
|
$certsPath = Join-Path $global:DockerDataPath "certs.d"
|
|
|
|
if (Test-Path $certsPath)
|
|
{
|
|
$daemonSettings | Add-Member NoteProperty hosts @("npipe://", "0.0.0.0:2376")
|
|
$daemonSettings | Add-Member NoteProperty tlsverify true
|
|
$daemonSettings | Add-Member NoteProperty tlscacert (Join-Path $certsPath "ca.pem")
|
|
$daemonSettings | Add-Member NoteProperty tlscert (Join-Path $certsPath "server-cert.pem")
|
|
$daemonSettings | Add-Member NoteProperty tlskey (Join-Path $certsPath "server-key.pem")
|
|
}
|
|
elseif (!$SkipDefaultHost.IsPresent)
|
|
{
|
|
# Default local host
|
|
$daemonSettings | Add-Member NoteProperty hosts @("npipe://")
|
|
}
|
|
|
|
if ($NATSubnet -ne "")
|
|
{
|
|
$daemonSettings | Add-Member NoteProperty fixed-cidr $NATSubnet
|
|
}
|
|
|
|
$daemonSettingsFile = Join-Path $dockerConfigPath "daemon.json"
|
|
|
|
$daemonSettings | ConvertTo-Json | Out-File -FilePath $daemonSettingsFile -Encoding ASCII
|
|
|
|
& dockerd --register-service --service-name $global:DockerServiceName
|
|
|
|
Start-Docker
|
|
|
|
#
|
|
# Waiting for docker to come to steady state
|
|
#
|
|
Wait-Docker
|
|
|
|
if(-not [string]::IsNullOrEmpty($ContainerBaseImage)) {
|
|
Write-Output "Attempting to pull specified base image: $ContainerBaseImage"
|
|
docker pull $ContainerBaseImage
|
|
}
|
|
|
|
Write-Output "The following images are present on this machine:"
|
|
|
|
docker images -a | Write-Output
|
|
|
|
Write-Output ""
|
|
}
|
|
|
|
function
|
|
Start-Docker()
|
|
{
|
|
Start-Service -Name $global:DockerServiceName
|
|
}
|
|
|
|
|
|
function
|
|
Stop-Docker()
|
|
{
|
|
Stop-Service -Name $global:DockerServiceName
|
|
}
|
|
|
|
|
|
function
|
|
Test-Docker()
|
|
{
|
|
$service = Get-Service -Name $global:DockerServiceName -ErrorAction SilentlyContinue
|
|
|
|
return ($service -ne $null)
|
|
}
|
|
|
|
|
|
function
|
|
Wait-Docker()
|
|
{
|
|
Write-Output "Waiting for Docker daemon..."
|
|
$dockerReady = $false
|
|
$startTime = Get-Date
|
|
|
|
while (-not $dockerReady)
|
|
{
|
|
try
|
|
{
|
|
docker version | Out-Null
|
|
|
|
if (-not $?)
|
|
{
|
|
throw "Docker daemon is not running yet"
|
|
}
|
|
|
|
$dockerReady = $true
|
|
}
|
|
catch
|
|
{
|
|
$timeElapsed = $(Get-Date) - $startTime
|
|
|
|
if ($($timeElapsed).TotalMinutes -ge 1)
|
|
{
|
|
throw "Docker Daemon did not start successfully within 1 minute."
|
|
}
|
|
|
|
# Swallow error and try again
|
|
Start-Sleep -sec 1
|
|
}
|
|
}
|
|
Write-Output "Successfully connected to Docker Daemon."
|
|
}
|
|
|
|
try
|
|
{
|
|
Install-ContainerHost
|
|
}
|
|
catch
|
|
{
|
|
Write-Error $_
|
|
} |