나노 서버에 ASP.NET Core 응용 프로그램 배포하기

등록일시: 2016-08-01 08:00,  수정일시: 2016-08-22 13:42
조회수: 9,181
이 문서는 ASP.NET Core 기술을 널리 알리고자 하는 개인적인 취지로 제공되는 번역문서입니다. 이 문서에 대한 모든 저작권은 마이크로소프트에 있으며 요청이 있을 경우 언제라도 게시가 중단될 수 있습니다. 번역 내용에 오역이 존재할 수 있고 주석은 번역자 개인의 의견일 뿐이며 마이크로소프트는 이에 관한 어떠한 보장도 하지 않습니다. 번역이 완료된 이후에도 대상 제품 및 기술이 개선되거나 변경됨에 따라 원문의 내용도 변경되거나 보완되었을 수 있으므로 주의하시기 바랍니다.
본문에서는 나노 서버 개발자 VHD 파일을 이용해서 Hyper-V 가상 머신을 생성하고 IIS를 설치하여, 실행 중인 나노 서버의 인스턴스에 기존에 만들어진 ASP.NET Core 응용 프로그램을 배포해봅니다.

주의

본 자습서에서는 Windows Server Technical Preview 5에서 제공되는 나노 서버(Nano Server) 설치 옵션의 미리보기 버전을 사용합니다. 이 버전의 가상 하드 디스크 이미지는 내부적으로 소프트웨어를 검증하고 평가하기 위한 목적으로만 사용해야 합니다. 실제 운영 환경에서는 이 소프트웨어를 사용할 수 없습니다. 미리보기 버전의 라이선스 만료 날짜에 관한 보다 자세한 정보는 Windows Server Technical Preview 만료 문서를 참고하시기 바랍니다.

본문에서는 IIS가 실행 중인 나노 서버의 인스턴스에 기존에 만들어진 ASP.NET Core 응용 프로그램을 배포해봅니다.

개요

나노 서버(Nano Server)는 서버 코어(Server Core) 및 일반적인 GUI 기반의 서버에 비해 극단적으로 작은 풋 프린트와 향상된 보안, 그리고 더 나은 서비스를 제공해주는 Windows Server 2016의 설치 옵션 중 하나입니다. 보다 자세한 내용은 공식 나노 서버 문서를 참고하시기 바랍니다. 직접 나노 서버를 사용해볼 수 있는 방법에는 다음과 같은 세 가지 방법이 존재합니다:

  1. Windows Server 2016 Technical Preview 5 ISO 파일을 다운로드 받아서 직접 나노 서버 이미지를 빌드합니다.
  2. 나노 서버 개발자 VHD를 다운로드 받습니다.
  3. Azure Gallery에서 제공해주는 나노 서버 이미지를 이용해서 Azure에 가상 머신(VM)을 생성합니다. 만약 Azure 계정이 없다면 무료 Azure 계정을 만들 수 있습니다.

본문에서는 Windows Server Technical Preview 5를 기반으로 미리 빌드된 나노 서버 개발자 VHD를 사용합니다.

본 자습서의 내용을 따라해보려면 기존 ASP.NET Core 응용 프로그램의 게시된 출력이 필요합니다. 준비된 응용 프로그램이 64 비트 프로세스에서 실행되도록 빌드됐는지 확인하시기 바랍니다.

역주

본문에서 사용하는 VHD 파일에는 IIS가 미리 설치되어 있지 않습니다. 그래서 이후 과정의 한 단계로 PowerShell Remoting을 통해서 온라인으로 Microsoft-NanoServer-IIS-Package를 설치하는 작업을 수행하게 됩니다. 그러나 아쉽지만 현재 Technical Preview 5에서는 이 기능이 정상적으로 동작하지 않습니다. 이에 관한 더 자세한 정보는 NanoServerPackage Provider 문서의 Known Issues 절을 참고하시기 바랍니다.

본 문서에서는 이 문제점을 해결할 수 있는 방법으로 두 가지 방안이 제시되고 있는데, 그 중 첫 번째 방법은 Microsoft-NanoServer-Storage-Package 같이 재시작이 필요한 패키지를 먼저 설치한 다음, 재시작을 하지 않고 바로 IIS 패키지를 설치하는 것입니다. 그러나 저의 경우 이 방법은 몇 번을 시도해도 실패했습니다. 두 번째 방법은 VHD 파일에 미리 IIS 패키지를 설치하고 Hyper-V 가상 머신을 생성하는 방법으로 저는 이 방법을 시도해서 성공했습니다.

이렇게 VHD 파일에 IIS 패키지를 설치하려면 관리자 권한으로 실행한 로컬 PowerShell 창에 다음 명령들을 차례대로 입력합니다:

Install-PackageProvider NanoServerPackage
Import-PackageProvider NanoServerPackage
Install-NanoServerPackage -Name Microsoft-NanoServer-IIS-Package -ToVhd <vhd-file-path>

그리고 본문에서 말하는 '게시된 출력'은 프로젝트 파일이나 빌드된 파일들을 말하는 것이 아닙니다. 말 그대로 게시를 위해서 출력된 파일들의 모음을 뜻하는 것으로, 이 게시된 출력을 만드는 가장 간단한 방법은 Visual Studio를 이용하는 것입니다. 먼저 Visual Studio에서 예제 프로젝트를 생성한 다음, 솔루션 탐색기에서 마우스 오른쪽 버튼으로 프로젝트를 클릭하고 게시를 선택합니다. 그러면 게시 대화 상자가 나타나는데, 프로필 탭에서 사용자 지정을 선택한 다음, 프로필 이름을 입력합니다. 그리고 게시 방법파일 시스템으로 지정하고 게시를 수행하면 지정한 폴더에 게시 출력이 만들어집니다.

나노 서버 인스턴스 구성하기

다운로드 받은 VHD 파일을 이용해서 개발 머신에 새로운 Hyper-V 가상 머신을 생성하고 실행합니다. 생성한 가상 머신에 로그인하려면 먼저 관리자 비밀번호를 설정해야 합니다. 가상 머신의 콘솔에서 F11을 눌러서 관리자 비밀번호를 설정합니다.

로컬 비밀번호의 설정을 마친 뒤부터는, PowerShell Remoting을 이용해서 나노 서버를 구성하게 됩니다.

PowerShell Remoting으로 나노 서버 인스턴스에 연결하기

관리자 권한으로 PowerShell 창을 연 다음, 설치한 나노 머신의 원격 인스턴스를 TrustedHosts 목록에 추가합니다.

$nanoServerIpAddress = "10.83.181.14"
Set-Item WSMan:\localhost\Client\TrustedHosts "$nanoServerIpAddress" -Concatenate -Force

역주

만약 Set-Item 커맨드릿 실행 시 오류가 발생한다면 먼저 net start WinRM 명령을 실행해서 Windows Remote Management (WS-Management) 서비스부터 시작합니다.

노트

이 명령에서 $nanoServerIpAddress 변수 값은 나노 서버의 실제 IP 주소로 변경해야 합니다.

나노 서버의 인스턴스를 TrustedHosts에 등록하고 나면, 이제 PowerShell Remoting을 이용해서 나노 서버에 연결할 수 있습니다.

$nanoServerSession = New-PSSession -ComputerName $nanoServerIpAddress -Credential ~\Administrator
Enter-PSSession $nanoServerSession

정상적으로 나노 서버에 연결되면 [10.83.181.14]: PS C:\Users\Administrator\Documents> 같은 형태의 프롬프트가 나타나게 됩니다.

파일 공유 생성하기

게시된 응용 프로그램을 나노 서버로 복사하려면 파일 공유를 생성해야 합니다. 원격 세션에서 다음 명령을 실행합니다:

mkdir C:\PublishedApps\AspNetCoreSampleForNano
netsh advfirewall firewall set rule group="File and Printer Sharing" new enable=yes
net share AspNetCoreSampleForNano=c:\PublishedApps\AspNetCoreSampleForNano /GRANT:EVERYONE`,FULL

이 명령을 실행하고 나면 호스트 머신의 윈도우 탐색기에서 \\<nanoserver-ip-address>\AspNetCoreSampleForNano로 이동해서 공유에 접근할 수 있습니다.

방화벽 포트 열기

원격 세션에서 다음 명령을 실행해서 TCP 트래픽을 수신할 수 있도록 방화벽의 포트를 엽니다.

New-NetFirewallRule -Name "AspNet5 IIS" -DisplayName "Allow HTTP on TCP/8000" -Protocol TCP -LocalPort 8000 -Action Allow -Enabled True

IIS 설치하기

역주

본문의 앞 부분에서 설명한 것처럼 -ToVhd 옵션을 이용해서 이미 Microsoft-NanoServer-IIS-Package를 설치했다면 이번 절의 과정을 수행할 필요가 없습니다.

PowerShell 갤러리를 이용해서 NanoServerPackage 공급자를 추가합니다. 이 공급자를 설치한 다음 임포트하면, Windows 패키지를 설치할 수 있습니다.

열어 놓은 원격 PowerShell 세션에서 다음 명령을 실행합니다:

Install-PackageProvider NanoServerPackage
Import-PackageProvider NanoServerPackage
Install-NanoServerPackage -Name Microsoft-NanoServer-IIS-Package

정상적으로 IIS가 설치됐는지 확인할 수 있는 가장 간단한 방법은 http://<nanoserver-ip-address>/ URL을 방문해서 환영 페이지가 나타나는지를 살펴보는 것입니다. IIS가 설치되면 기본적으로 80번 포트를 수신하는 Default Web Site라는 웹 사이트가 만들어집니다.

ASP.NET Core Module(ANCM) 설치하기

ASP.NET Core Module은 ASP.NET Core HTTP 리스너의 프로세스 관리와 이 모듈이 관리하는 프로세스에 대한 프록시 요청을 담당하는 IIS 7.5+ 모듈입니다. 현재 릴리즈에서는 IIS에 ASP.NET Core Module을 설치하는 작업은 직접 수작업으로 처리해야 합니다. 먼저 일반적인 머신에 (나노 서버가 아닌) .NET Core Windows Server Hosting 번들 버전을 설치합니다. 그런 다음, 일반적인 머신에 설치된 다음 파일들을 앞의 절에서 만들었던 파일 공유에 복사합니다.

일반 머신에서 (나노 서버가 아닙니다) 다음 명령들을 실행합니다:

copy C:\windows\system32\inetsrv\aspnetcore.dll \\<nanoserver-ip-address>\AspNetCoreSampleForNano
copy C:\windows\system32\inetsrv\config\schema\aspnetcore_schema.xml \\<nanoserver-ip-address>\AspNetCoreSampleForNano

역주

.NET Core Windows Server Hosting 번들 버전을 설치하려면 IIS가 설치되어 있어야만 합니다.

그런 다음, 나노 머신에서 방금 파일 공유에 복사해 놓은 파일들을 다시 적절한 위치로 복사합니다. 다음과 같은 복사 명령을 실행합니다:

copy C:\PublishedApps\AspNetCoreSampleForNano\aspnetcore.dll C:\windows\system32\inetsrvcopy C:\PublishedApps\AspNetCoreSampleForNano\aspnetcore_schema.xml C:\windows\system32\inetsrv\config\schema\

그리고 원격 세션에서 다음 스크립트를 실행합니다:

# Backup existing applicationHost.config
copy C:\Windows\System32\inetsrv\config\applicationHost.config C:\Windows\System32\inetsrv\config\applicationHost_BeforeInstallingANCM.config

Import-Module IISAdministration

# Initialize variables
$aspNetCoreHandlerFilePath="C:\windows\system32\inetsrv\aspnetcore.dll"
Reset-IISServerManager -confirm:$false
$sm = Get-IISServerManager

# Add AppSettings section 
$sm.GetApplicationHostConfiguration().RootSectionGroup.Sections.Add("appSettings")

# Set Allow for handlers section
$appHostconfig = $sm.GetApplicationHostConfiguration()
$section = $appHostconfig.GetSection("system.webServer/handlers")
$section.OverrideMode="Allow"

# Add aspNetCore section to system.webServer
$sectionaspNetCore = $appHostConfig.RootSectionGroup.SectionGroups["system.webServer"].Sections.Add("aspNetCore")
$sectionaspNetCore.OverrideModeDefault = "Allow"
$sm.CommitChanges()

# Configure globalModule
Reset-IISServerManager -confirm:$false
$globalModules = Get-IISConfigSection "system.webServer/globalModules" | Get-IISConfigCollection
New-IISConfigCollectionElement $globalModules -ConfigAttribute @{"name"="AspNetCoreModule";"image"=$aspNetCoreHandlerFilePath}

# Configure module
$modules = Get-IISConfigSection "system.webServer/modules" | Get-IISConfigCollection
New-IISConfigCollectionElement $modules -ConfigAttribute @{"name"="AspNetCoreModule"}

# Backup existing applicationHost.config
copy C:\Windows\System32\inetsrv\config\applicationHost.config C:\Windows\System32\inetsrv\config\applicationHost_AfterInstallingANCM.config

노트

작업을 마친 뒤, 공유 폴더에서 aspnetcore.dll 파일과 aspnetcore_schema.xml 파일을 삭제합니다.

.NET Core 프레임워크 설치하기

이식 가능한 응용 프로그램(Portable Application)을 게시하기 위해서는 대상 머신에 .NET Core가 설치되어 있어야만 합니다. 원격 Powershell 세션에서 다음 Powershell 스크립트를 실행해서 나노 서버에 .NET 프레임워크를 설치합니다.

$SourcePath = "https://go.microsoft.com/fwlink/?LinkID=809115"
$DestinationPath = "C:\dotnet"

$EditionId = (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' -Name 'EditionID').EditionId

if (($EditionId -eq "ServerStandardNano") -or
    ($EditionId -eq "ServerDataCenterNano") -or
    ($EditionId -eq "NanoServer") -or
    ($EditionId -eq "ServerTuva")) {

    $TempPath = [System.IO.Path]::GetTempFileName()
    if (($SourcePath -as [System.URI]).AbsoluteURI -ne $null)
    {
        $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($TempPath, [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
                }
            }
        }
    }
    else
    {
        throw "Cannot copy from $SourcePath"
    }
    [System.IO.Compression.ZipFile]::ExtractToDirectory($TempPath, $DestinationPath)
    Remove-Item $TempPath
}

응용 프로그램 게시하기

파일 공유에 기존 응용 프로그램의 게시된 출력을 복사합니다.

그러나 그 전에 먼저, 나노 서버에 추출된 dotnet.exe 파일의 위치를 바라보도록 web.config 파일의 구성을 변경해야 합니다. 또는 Path에 dotnet.exe의 경로를 추가할 수도 있습니다.

가령 다음은 Path에 dotnet.exe의 경로가 존재하지 않는 경우를 가정하고 구성한 web.config 파일의 한 예입니다:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <handlers>
      <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
    </handlers>
    <aspNetCore processPath="C:\dotnet\dotnet.exe" arguments=".\AspNetCoreSampleForNano.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="true" />
  </system.webServer>
</configuration>

원격 세션에서 다음 명령들을 실행해서 IIS에 게시된 응용 프로그램을 위한 새로운 사이트를 생성합니다. 참고로 이 스크립트는 편의를 위해서 DefaultAppPool을 사용하고 있습니다. 응용 프로그램 풀에 대한 추가적인 고려사항들에 대해서는 Application Pools 문서를 참고하시기 바랍니다.

Import-module IISAdministration
New-IISSite -Name "AspNetCore" -PhysicalPath c:\PublishedApps\AspNetCoreSampleForNano -BindingInformation "*:8000:"

나노 서버에서 .NET Core CLI 실행시 발생하는 알려진 문제점 및 해결방안

나노 서버 Technical Preview 5 버전에서 .NET Core CLI를 사용하기 위해서는 c:\windows\system32\forwarders 폴더의 모든 DLL 파일들을 c:\windows\system32 폴더에 복사해야 합니다. 이 버그는 이후 릴리즈에서 해결되었습니다.

그리고 dotnet publish 명령을 사용하는 경우에도 역시 c:\windows\system32\forwarders 폴더의 모든 DLL 파일들을 게시 디렉터리에 복사해야 합니다.

만약 사용 중인 나노 서버 Preview 5 빌드가 업데이트 되거나 서비스 된다면, 해당 DLL들 중 일부도 업데이트 되었을 수 있으므로, 반드시 이 작업을 다시 수행해주시기 바랍니다.

응용 프로그램 실행하기

이제 브라우저에서 http://<nanoserver-ip-address>:8000 URL로 이동하면 게시된 웹 응용 프로그램에 정상적으로 접근할 수 있어야 합니다. Log creation and redirection 문서의 설명대로 로깅을 구성하면 C:\PublishedApps\AspNetCoreSampleForNano\logs 에서 로그를 확인할 수도 있습니다.

역주

저의 경우에는 아쉽지만 본 자습서의 모든 과정들을 정상적으로 수행한 다음에도 브라우저로 웹 사이트에 접근해보면 502.5 오류가 발생했습니다. 정확한 문제점을 파악하기 위해서 마지막 절의 링크에서 지시하는 방법에 따라 로깅을 설정하여 살펴봤습니다. 그 결과 로그에 다음과 같은 오류가 기록되어 있는 것을 확인할 수 있었습니다.

Failed to load the dll from [C:\dotnet\shared\Microsoft.NETCore.App\1.0.0\hostpolicy.dll], HRESULT: 0x8007007E
An error occurred while loading required library hostpolicy.dll from [C:\dotnet\shared\Microsoft.NETCore.App\1.0.0]

제가 사용한 방법이 올바른 방법인지 장담할 수는 없지만 로그의 내용을 감안하여 c:\windows\system32\forwarders 폴더의 모든 DLL 파일들을 c:\dotnet\shared\Microsoft.NETCore.App\1.0.0 폴더에 복사했으며 이후 웹 사이트가 정상적으로 실행되는 것을 확인할 수 있었습니다.