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"]
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.
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을 노출합니다.