재우니의 블로그

 

 

 

최신 .NET 5.0 or 8.0 을 사용하여 Docker Desktop으로 ASP.NET Core 5 or 8 버전의 웹 사이트를 만드는 방법을 알아볼까 합니다.

 

 

  • ASP.NET Core 5.0 웹 사이트 만들기 및 실행
  • 첫 번째 컨테이너 구축
  • 웹 사이트를 로컬 컨테이너로 실행
  • 기본 명령 이해
  • 문제 해결

 

요구 사항

이 게시물에서는 다음 요구 사항이 설치되어 있는지 확인합니다.

 

.NET Core Docker SDK 다운로드

Docker는 dotnet의 Docker SDK를 가져와 로컬 저장소에 저장합니다.

C:\SourceSample>docker pull mcr.microsoft.com/dotnet/aspnet:5.0

 

Docker Desktop이 올바르게 설치되었는지 확인하는 테스트입니다. 이미지를 빌드 할 때 볼 수 있듯이 Docker는 이미지가 로컬에 있는 경우 원격 호스트에서 이미지를 제거하는 것을 알아서 건너 뛰므로, 지금 실행하는 과정은 걱정 안하셔도 됩니다.

이미지가 로컬 저장소에 있는지 확인하려면 다음을 실행해 보죠.

C:\SourceSample>docker image ls

 

아래 목록이 보이면 성공적으로 설치 된 것을 의미합니다.

mcr.microsoft.com/dotnet/aspnet   5.0       7fafba04799a   2 days ago       205MB

 

이제 app 을 만들어 보겠습니다.

cmd 창에서  dotnet CLI, 를 통해 asp.net 5 를 생성해 보겠습니다. webapp 라는 폴더가 생성되면서 자동적으로 asp.net 5 솔루션 샘플 소스가 제공됩니다.

C:\SourceSample>dotnet new mvc -o webapp

 

생성된 폴더로 들어가서 실행해 봅니다. 실행은 dotnet run 입니다.

cd webapp
dotnet run

https://localhost:5001 를 브라우저에 실행하면 간단한 asp.net 5 로 개발된 화면을 보실 수 있습니다.

웹 애플리케이션 Containerizing (컨테이너화)

 

이제 애플리케이션을 컨테이너화 하겠습니다. 이것을 배우는 것은 microservices 에 관심이 있는 사람들에게 필요한 단계입니다. 컨테이너는 새로운 배포 단위이므로 Docker 이미지 내에 빌드를 캡슐화하고 모든 것을 Docker 파일에 래핑 할 수 있습니다.

Dockerfile 파일 생성하기

 

webapp 폴더 내부에 확장자 없는 dockerfile 이라는 파일을 생성합니다.

 

메모장이나 에디터를 열어서 아래 구문을 입력하여 저장합니다. 저는 ASP.NET 5 를 설치했으므로 SDK5.0 을 셋팅하였습니다.

버전에 맞는 dotnet 의 sdk 를 사용하여 image 를 빌드합니다.

ASP.NET CORE 3.1 : FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build

ASP.NET 5 : FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim AS build

 

그리고 asp.net runtime 를 사용하여 실행합니다.

ASP.NET CORE 3.1 : FROM mcr.microsoft.com/dotnet/core/aspnet:3.1

ASP.NET 5 : FROM mcr.microsoft.com/dotnet/aspnet:5.0-buster-slim AS base

# builds our image using dotnet's sdk
#FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build
FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim AS build
WORKDIR /source
COPY . ./webapp/
WORKDIR /source/webapp
RUN dotnet restore
RUN dotnet publish -c release -o /app --no-restore

# runs it using aspnet runtime
#FROM mcr.microsoft.com/dotnet/core/aspnet:3.1
FROM mcr.microsoft.com/dotnet/aspnet:5.0-buster-slim AS base
WORKDIR /app
COPY --from=build /app ./
ENTRYPOINT ["dotnet", "webapp.dll"]



 

 

아래는 asp.net core 8 에 맞게 작성한 dockerfile 입니다.

# https://hub.docker.com/_/microsoft-dotnet
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /source

# copy csproj and restore as distinct layers
COPY . ./webapp/
WORKDIR /source/webapp
RUN dotnet restore
RUN dotnet publish -c release -o /app --no-restore

# final stage/image
FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /app
COPY --from=build /app ./
ENTRYPOINT ["dotnet", "webapp.dll"]

 

참고 사이트 : https://learn.microsoft.com/ko-kr/aspnet/core/host-and-deploy/docker/building-net-docker-images?view=aspnetcore-8.0

 

 

 

이제 IMAGE 을 빌드 해 봅니다.

PS E:\sampleSource\Docker\webapp> docker build . -t webapp
[+] Building 7.7s (15/15) FINISHED                                                                       docker:default
 => [internal] load .dockerignore                                                                                  0.0s
 => => transferring context: 2B                                                                                    0.0s
 => [internal] load build definition from dockerfile                                                               0.0s
 => => transferring dockerfile: 452B                                                                               0.0s
 => [internal] load metadata for mcr.microsoft.com/dotnet/aspnet:8.0                                               0.2s
 => [internal] load metadata for mcr.microsoft.com/dotnet/sdk:8.0                                                  0.2s
 => [build 1/6] FROM mcr.microsoft.com/dotnet/sdk:8.0@sha256:0b4b20f78ab869a9fa6a8496053b4e2cb7339b8f748775c8c502  0.0s
 => [stage-1 1/3] FROM mcr.microsoft.com/dotnet/aspnet:8.0@sha256:91c325d4dd9f26a457824b1c5d1583e236b7178d85c1367  0.0s
 => CACHED [stage-1 2/3] WORKDIR /app                                                                              0.0s
 => [internal] load build context                                                                                  0.0s
 => => transferring context: 10.04kB                                                                               0.0s
 => CACHED [build 2/6] WORKDIR /source                                                                             0.0s
 => [build 3/6] COPY . ./webapp/                                                                                   0.1s
 => [build 4/6] WORKDIR /source/webapp                                                                             0.1s
 => [build 5/6] RUN dotnet restore                                                                                 2.1s
 => [build 6/6] RUN dotnet publish -c release -o /app --no-restore                                                 4.6s
 => [stage-1 3/3] COPY --from=build /app ./                                                                        0.1s
 => exporting to image                                                                                             0.1s
 => => exporting layers                                                                                            0.1s
 => => writing image sha256:f8fdae6d17f3335dcbbfa4ae5e7c150868c92a4547584a52f4109a8cefb89d1c                       0.0s
 => => naming to docker.io/library/webapp                                                                          0.0s

View build details: docker-desktop://dashboard/build/default/default/355xouee5rfuwyidzfyoyjakh

What's Next?
  View a summary of image vulnerabilities and recommendations → docker scout quickview

 

 

IMAGE 가 생성되어 있는지 docker image ls 로 확인해 봅니다.

 

 

아래 webapp 의 DOCKER IMAGE 가 보이면 설치된것으로 보시면 됩니다.

webapp                            latest    57aa5b439675   About an hour ago   210MB

 

 

 

이제 DOCKER IMAGE 를 실행해 보도록 하겠습니다.

C:\SourceSample\webapp>docker run --rm -it -p 8000:80 webapp

-- asp.net core 8 경우 80880 으로 지정하였음
C:\SourceSample\webapp>docker run --rm -it -p 8000:8080 webapp

 

 

 

PS E:\sampleSource\Docker\webapp> docker run --rm -it -p 8000:8080 webapp
warn: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[60]
      Storing keys in a directory '/root/.aspnet/DataProtection-Keys' that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed. For more information go to https://aka.ms/aspnet/dataprotectionwarning
warn: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35]
      No XML encryptor configured. Key {6d69ca49-21b8-4481-84d5-d7aa58d9b1a2} may be persisted to storage in unencrypted form.
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://[::]:8080
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Production
info: Microsoft.Hosting.Lifetime[0]
      Content root path: /app
warn: Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionMiddleware[3]
      Failed to determine the https port for redirect.

 

 

 http://localhost:8080 을 실행하면 컨테이너화된 웹사이트를 보실 수 있습니다.

 

 

 

ASP.NET CORE 8 경우, containers 와 images 화면

 

 

생성된 images 를 보실 수 있습니다.

 

 

webapp 의 images 에 대해 container 생성시 8080 port 로 지정하였으므로 아래와 같이 보이며, 이를 클릭하면 브라우저에서 실행되는 것을 확인 할 수 있습니다.

 

 

 

정리를 하자면..

 

Dockerfile을 빌드 할 때 두 개의 이미지 ( SDK  ASP.NET 이미지 )를 활용 했습니다. 처음 사용해 보시는 분들에게는 다소 덜 직관적이지만 이미지 크기가 더 작고 배포 된 코드가 적어 공격 표면??? (attack surface) 을 줄임으로써 더 안전 해 지므로 실제로는 좋은 습관입니다. 오늘 사용한 명령은 다음과 같습니다.

 

  • FROM <src> : Docker에게 이미지에 필요한 기본 이미지를 가져 오도록 지시합니다. SDK IMAGE 는 프로젝트와 빌드하는 데 필요한 도구가 포함되어 ASP.NET IMAGE 를 실행합니다.
  • COPY . : 현재 디렉토리의 내용을 컨테이너 내부에 지정된 위치에 복사합니다.
  • RUN <cmd> : 컨테이너 내부에서 명령을 실행합니다.
  • WORKDIR <path> : 후속 지침에 대한 작업 디렉토리를 설정하고 컨테이너 자체의 시작 위치로 설정합니다.
  • ENTRYPOINT [arg1, arg2, argN] : 컨테이너가 배열 형식으로 시작될 때 실행할 명령을 지정합니다. 우리의 경우 게시 된 웹 사이트를 외부에서 실행하는 것처럼 컨테이너에서 dotnet webapp.dll 을 실행합니다.

 

Docker 빌드

다음으로 docker build. -t webapp 은 다음을 의미합니다.

  • docker build . : Docker에게 현재 폴더 (.)의 내용을 기반으로 IMAGE 를 빌드하도록 지시합니다. 이 명령은 이 경우에 제공하지 않은 선택적 Dockerfile 도 허용합니다. 제공되지 않으면 Docker는 이 명령을 실행하기 전에 복사하여 붙여 넣은 현재 폴더에 Dockerfile을 예상 합니다.
  • -t webapp : 명령을 실행할 수 있도록 IMAGE 에 webapp 으로 태그 지정

 

Docker 실행

완료하려면 docker run --rm -it -p 8000 : 80 webapp 의미를 이해하겠습니다 .

  • docker run : 이미지 인스턴스 (컨테이너)를 실행합니다.
  • --rm : 완료된 직후 IMAGE 를 제거합니다. 이 명령을 여러 번 실행하고 각 실행이 새 컨테이너를 생성하므로 로컬 환경을 오염시키지 않기 위해 이렇게했습니다. Docker는 이미지가 삭제 된 후 이미지에 대한 로그를 보존하지 않으므로 개발시에만 사용해야합니다.
  • --it : 로그를보고 Ctrl-C로 취소 할 수 있도록 터미널에 연결하여 계속 실행합니다 .
  • -p 8000 : 80 : 포트 8000 의 로컬 호스트에서 컨테이너의 포트 80을 노출합니다. 
  • webapp : IMAGE 의 태그명

 

참고사이트 

blog.hildenco.com/2020/10/how-to-create-aspnet-core-website-with.html

 

Creating ASP.NET Core websites with Docker

.Net, Alpine, C#, Debian, Development, Docker, Microservices, Open Source, Ubuntu, Debian, Alpine, Asp.Net,

blog.hildenco.com