diff --git a/Dockerfile b/Dockerfile index cf381ed7c..e1295786d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,29 +1,12 @@ # Build the runtime image -FROM mcr.microsoft.com/dotnet/aspnet:10.0-alpine AS runtime +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/runtime:10.0.0-rc.1-azurelinux3.0-distroless AS runtime -# Add build argument for publish directory ARG PUBLISH_DIR - -# Error out if PUBLISH_DIR is not set -RUN if [ -z "$PUBLISH_DIR" ]; then \ - echo "ERROR: PUBLISH_DIR build argument is required" && exit 1; \ - fi - -RUN apk add --no-cache libc6-compat +ARG TARGETOS +ARG TARGETARCH # Copy the contents of the publish directory to '/azuremcpserver' and set it as the working directory -RUN mkdir -p /azuremcpserver -COPY ${PUBLISH_DIR} /azuremcpserver/ +COPY ${PUBLISH_DIR}/${TARGETOS}-${TARGETARCH}/dist/ /azuremcpserver/ WORKDIR /azuremcpserver -# List the contents of the current directory -RUN ls -la - -# Ensure the main binary exists and is executable -RUN if [ ! -f "azmcp" ]; then \ - echo "ERROR: azmcp executable does not exist" && exit 1; \ - fi \ - && chmod +x azmcp \ - && test -x azmcp - ENTRYPOINT ["./azmcp", "server", "start"] diff --git a/eng/scripts/Build-Docker.ps1 b/eng/scripts/Build-Docker.ps1 index d61f8e916..f37f811f5 100644 --- a/eng/scripts/Build-Docker.ps1 +++ b/eng/scripts/Build-Docker.ps1 @@ -7,39 +7,105 @@ param( [Parameter(Mandatory=$true)] [string] $ServerName, [switch] $Trimmed, - [switch] $DebugBuild + [switch] $DebugBuild, + [Parameter(Mandatory=$true, ParameterSetName='SpecificPlatform')] + [ValidateSet('windows','linux','macOS')] + [string] $OperatingSystem, + [Parameter(Mandatory=$true, ParameterSetName='SpecificPlatform')] + [ValidateSet('x64','arm64')] + [string] $Architecture, + [Parameter(ParameterSetName='AllPlatforms')] + [switch] $AllPlatforms ) +function Get-DockerOS([string]$dotnetName) { + switch ($dotnetName) { + 'linux' { return 'linux' } + 'macOS' { return 'linux' } + 'windows' { return 'win' } + default { return $dotnetName } + } +} + +function Get-DockerArchitecture([string]$dotnetName) { + switch ($dotnetName) { + 'x64' { return 'amd64' } + default { return $dotnetName } + } +} + . "$PSScriptRoot/../common/scripts/common.ps1" $root = $RepoRoot.Path.Replace('\', '/') $distPath = "$root/.work" $dockerFile = "$root/Dockerfile" $properties = & "$PSScriptRoot/Get-ProjectProperties.ps1" -ProjectName "$ServerName.csproj" $dockerImageName = $properties.DockerImageName +$buildDirectory = $([System.IO.Path]::Combine($distPath, "build", $ServerName)) if(!$Version) { $Version = $properties.Version } -# Will fix this when we update Dockerfile to multi-platform -$os = "linux" -$arch = "x64" $SingleFile = $Trimmed $tag = "$dockerImageName`:$Version$VersionSuffix"; -& "$root/eng/scripts/Build-Code.ps1" -ServerName $ServerName -VersionSuffix $VersionSuffix -SelfContained -Trimmed:$Trimmed -SingleFile:$SingleFile -DebugBuild:$DebugBuild -OperatingSystem $os -Architecture $arch +if ($AllPlatforms) { + & "$root/eng/scripts/Build-Code.ps1" -ServerName $ServerName -VersionSuffix $VersionSuffix -SelfContained -Trimmed:$Trimmed -SingleFile:$SingleFile -DebugBuild:$DebugBuild -AllPlatforms + + $operatingSystems = @('linux','windows') + $architectures = @('x64','arm64') + +} elseif ($OperatingSystem -and $Architecture) { + if ($OperatingSystem -eq 'macOS') { + $OperatingSystem = 'linux' + } + + & "$root/eng/scripts/Build-Code.ps1" -ServerName $ServerName -VersionSuffix $VersionSuffix -SelfContained -Trimmed:$Trimmed -SingleFile:$SingleFile -DebugBuild:$DebugBuild -OperatingSystem $OperatingSystem -Architecture $Architecture + + $operatingSystems = @($OperatingSystem) + $architectures = @($Architecture) +} else { + Write-Error "Either specify both OperatingSystem and Architecture, or use the AllPlatforms switch." + exit 1 +} + if ($LastExitCode -ne 0) { exit $LastExitCode } -[string]$publishDirectory = $([System.IO.Path]::Combine($distPath, "build", $ServerName, "$os-$arch", "dist")) -$relativeDirectory = $(Resolve-Path $publishDirectory -Relative).Replace('\', '/') +# Move x64 folder to amd64 to match Docker naming conventions +foreach ($os in $operatingSystems) { + +} + +[string[]]$identifiers = @() +foreach($os in $operatingSystems) { + $dockerOS = Get-DockerOS $os -Write-Host "Building Docker image ($tag). PATH: [$relativeDirectory]. Absolute: [$publishDirectory]." + foreach($arch in $architectures) { + $dockerArchitecture = Get-DockerArchitecture $arch -if (!(Test-Path $publishDirectory)) { - Write-Error "Build output directory does not exist: $publishDirectory" + if ($arch -eq 'x64') { + $x64Folder = "$buildDirectory/$dockerOS-x64" + $destination = "$buildDirectory/$dockerOS-amd64" + Write-Host "Moving $x64Folder to $destination" -ForegroundColor Yellow + Move-Item -Path $x64Folder -Destination $destination -Force + } + + $identifiers += "$dockerOS/$dockerArchitecture" + } +} + +# The COPY command needs to be within the scope of the "working directory". Usually where the ./Dockerfile is. We need a relative path. +$relativeDirectory = $(Resolve-Path $buildDirectory -Relative).Replace('\', '/') + +if (!(Test-Path $buildDirectory)) { + Write-Error "Build output directory does not exist: $buildDirectory" return } -& docker build --build-arg PUBLISH_DIR="$relativeDirectory" --file $dockerFile --tag $tag . +[string]$platformString = [string]::Join(',', $identifiers) + +Write-Host "Building Docker image ($tag). PATH: [$relativeDirectory]. Absolute: [$buildDirectory]. Platforms: [$platformString]" + +& docker build --platform $platformString --build-arg PUBLISH_DIR="$relativeDirectory" --file $dockerFile --tag $tag .