티스토리 뷰

2020.06.05 업데이트

본편의 실습에 도움이 될 수 있는 연관된 데모자료(동영상, 발표자료) 공유 드립니다. 
2020년 4월 25일 시행했던 Global Azure Virtual 행사에서 발표한 동영상 및 발표자료 공유 드립니다.

 

* 동영상 : 발표 동영상 보러가기

* 발표자료 : 발표 자료 다운로드

 

 

들어가기에 앞서

 

이번 글에서는 이전 실습에 이어 Application을 Dockerizing 하고 이를 Azure CI/CD 파이프라인을 통해 Azure Web App 서비스로 배포하는 과정을 간단하게 Demo 하고자 한다.

진행의 편의를 위해 Dockerfile을 생성하여 Git에 소스를 올려두었다.

내용상 잘못된 부분이 있거나 더 나은 제안 사항이 있다면 함게 공유해주길 바란다~^^

 

 

 

 

 

 

 

준비사항

 

 

 

 

 

 

git 소스 가져오기

 

먼저 git bash 터미널에서 git 소스를 내려받고 modernizing_app_demo 디렉토리로 이동한다.

git clone https://github.com/zer0big/webapp4container-cicd-demo.git

cd webapp4container-cicd-demo/

[root@ansible-vmc handson0223]# git clone https://github.com/zer0big/webapp4container-cicd-demo.git
Cloning into 'webapp4container-cicd-demo'...
remote: Enumerating objects: 86, done.
remote: Counting objects: 100% (86/86), done.
remote: Compressing objects: 100% (62/62), done.
remote: Total 86 (delta 18), reused 86 (delta 18), pack-reused 0
Unpacking objects: 100% (86/86), done.
[root@ansible-vmc handson0223]# cd webapp4container-cicd-demo/
[root@ansible-vmc webapp4container-cicd-demo]#

 

Dcokerfile에 대해 라인별로 간단하게 검토하면 다음과 같다.

#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
WORKDIR /src
COPY ["azuredevops-demo.web.csproj", ""]
RUN dotnet restore "./azuredevops-demo.web.csproj"
COPY . .
WORKDIR "/src/."
RUN dotnet build "azuredevops-demo.web.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "azuredevops-demo.web.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "azuredevops-demo.web.dll"]

 

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base

런타임 전용 기본 이미지를 지정하여 단계를 시작하고 참조를 위해 base라고 명명한다.

 

WORKDIR /app

이미지에 /app 디렉토리를 만든다.

 

EXPOSE 80
EXPOSE 443

80, 443 포트를 노출한다.

 

FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build

빌드/개시를 위한 이미지를 사용하여 새로운 단계를 시작한다. 참조를 위해 build라고 명명한다.

 

WORKDIR /src

이미지에 /src 디렉토리를 만든다.


COPY ["azuredevops-demo.web.csproj", ""]

패키지를 나중에 Restore 할 수 있도록 .csproj 프로젝트 파일을 복사한다.


RUN dotnet restore "./azuredevops-demo.web.csproj"

프로젝트(및 기타 프로젝트 종속성)를 restore 한다.


COPY . .

솔루션의 모든 디렉터리 트리.dockerignore 파일에 포함된 파일/디렉터리는 예외)를 이미지의 /src 디렉터리로 복사한다.


WORKDIR "/src/."

현재 디렉토리를 /src/.로 변경한다.


RUN dotnet build "azuredevops-demo.web.csproj" -c Release -o /app/build

프로젝트(및 기타 프로젝트 종속성)를 빌드하고 이미지의 /app/build 디렉터리에 출력한다.

 

FROM build AS publish

build에서 이어지는 새 단계를 시작한다. 참조를 위해 이를 publish라고 명명한다.


RUN dotnet publish "azuredevops-demo.web.csproj" -c Release -o /app/publish

프로젝트(및 종속성)를 게시하고 이미지의 /app/publish 디렉토리에 출력한다.

 

FROM base AS final

base에서 이어지는 새 단계를 시작하고 이를 final이라고 명명한다.


WORKDIR /app

현재 디렉토리를 /app으로 변경한다.


COPY --from=publish /app/publish .

publish 단계에서 현재 디렉터리로 /app/publish 디렉토리를 복사한다.


ENTRYPOINT ["dotnet", "azuredevops-demo.web.dll"]

컨테이너가 시작될 때 실행할 명령을 정의한다.

 

 

 

 

 

 

docker build & run 테스트

 

docker build 명령을 사용하여 이미지 빌드를 시행한다.

docker build -t wa4container-demo .

[root@ansible-vmc webapp4container-cicd-demo]# docker build -t wa4container-demo .
Sending build context to Docker daemon   5.72MB
Step 1/17 : FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
3.1-buster-slim: Pulling from dotnet/core/aspnet
bc51dd8edc1b: Already exists
94eed7e63070: Pull complete
3fc527d45e99: Pull complete
200b585e49cc: Pull complete
06bb6fd03962: Pull complete
Digest: sha256:f30a7e2bb615fcc98ad3b4c99183b7f297d27b68aa23ebe34f25548f1dfaac7a
Status: Downloaded newer image for mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim
 ---> 47da1e9634dc
Step 2/17 : WORKDIR /app
 ---> Running in da588335927d
Removing intermediate container da588335927d
 ---> f0611da36104
Step 3/17 : EXPOSE 80
 ---> Running in 046913d20ee4
Removing intermediate container 046913d20ee4
 ---> 423f35882f76
Step 4/17 : EXPOSE 443
 ---> Running in 16d7b6dbb8a8
Removing intermediate container 16d7b6dbb8a8
 ---> 58eeaf94beef
Step 5/17 : FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
3.1-buster: Pulling from dotnet/core/sdk
dc65f448a2e2: Pull complete
346ffb2b67d7: Pull complete
dea4ecac934f: Pull complete
8ac92ddf84b3: Pull complete
5739cea041bc: Pull complete
c672494e8688: Pull complete
5ef2f2a67e1c: Pull complete
Digest: sha256:d962de32226f09e04db9cafe0d60b9dce183d61c5c1e86607ad045986b41be83
Status: Downloaded newer image for mcr.microsoft.com/dotnet/core/sdk:3.1-buster
 ---> 4a651b73be3d
Step 6/17 : WORKDIR /src
 ---> Running in 272114870fbb
Removing intermediate container 272114870fbb
 ---> 5d175da61b84
Step 7/17 : COPY ["azuredevops-demo.web.csproj", ""]
 ---> b86f10a2b0e2
Step 8/17 : RUN dotnet restore "./azuredevops-demo.web.csproj"
 ---> Running in c66451608734
  Restore completed in 168.35 ms for /src/azuredevops-demo.web.csproj.
Removing intermediate container c66451608734
 ---> 67cf8ac0ef32
Step 9/17 : COPY . .
 ---> 92b135c45126
Step 10/17 : WORKDIR "/src/."
 ---> Running in 2ce8f51c6ff9
Removing intermediate container 2ce8f51c6ff9
 ---> e46661fcafe0
Step 11/17 : RUN dotnet build "azuredevops-demo.web.csproj" -c Release -o /app/build
 ---> Running in 065687c11993
Microsoft (R) Build Engine version 16.4.0+e901037fe for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.
 
  Restore completed in 148.2 ms for /src/azuredevops-demo.web.csproj.
  azuredevops-demo.web -> /app/build/azuredevops-demo.web.dll
  azuredevops-demo.web -> /app/build/azuredevops-demo.web.Views.dll
 
Build succeeded.
    0 Warning(s)
    0 Error(s)
 
Time Elapsed 00:00:05.78
Removing intermediate container 065687c11993
 ---> 7e8cba76fa1c
Step 12/17 : FROM build AS publish
 ---> 7e8cba76fa1c
Step 13/17 : RUN dotnet publish "azuredevops-demo.web.csproj" -c Release -o /app/publish
 ---> Running in 8533b42f3d42
Microsoft (R) Build Engine version 16.4.0+e901037fe for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.
 
  Restore completed in 32.78 ms for /src/azuredevops-demo.web.csproj.
  azuredevops-demo.web -> /src/bin/Release/netcoreapp3.1/azuredevops-demo.web.dll
  azuredevops-demo.web -> /src/bin/Release/netcoreapp3.1/azuredevops-demo.web.Views.dll
  azuredevops-demo.web -> /app/publish/
Removing intermediate container 8533b42f3d42
 ---> 71623a2e6368
Step 14/17 : FROM base AS final
 ---> 58eeaf94beef
Step 15/17 : WORKDIR /app
 ---> Running in 25a2306d0935
Removing intermediate container 25a2306d0935
 ---> aa11be37fa99
Step 16/17 : COPY --from=publish /app/publish .
 ---> ec4ac462fd08
Step 17/17 : ENTRYPOINT ["dotnet", "azuredevops-demo.web.dll"]
 ---> Running in 0884f52d248c
Removing intermediate container 0884f52d248c
 ---> 8b399b6aee00
Successfully built 8b399b6aee00
Successfully tagged wa4container-demo:latest

 

빌드가 성공적으로 이루어졌는지 docker images 명령을 통해 결과를 확인한다.

 

docker images

[root@ansible-vmc webapp4container-cicd-demo]# docker images
REPOSITORY                             TAG                 IMAGE ID            CREATED             SIZE
wa4container-demo                      latest              8b399b6aee00        41 seconds ago      212MB
<none>                                 <none>              71623a2e6368        43 seconds ago      702MB
mcr.microsoft.com/dotnet/core/sdk      3.1-buster          4a651b73be3d        4 days ago          690MB
mcr.microsoft.com/dotnet/core/aspnet   3.1-buster-slim     47da1e9634dc        4 days ago          207MB

 

 

Docker 실행

 

docker run명령을 시행하여 docker를 실행한다.

docker run -d -p 80:80 wa4container-demo 

[root@ansible-vmc webapp4container-cicd-demo]# docker run -d -p 80:80 wa4container-demo
bc3d062732c6a9d6787d8c6fbb45a237ca430895e6c55ef4dfd193dddf257bbd

 

Docker 실행 결과 검증

 

curl http://localhost 명령을 시행하여 정상동작 여부를 확인한다. 

curl http://localhost

 

[root@ansible-vmc webapp4container-cicd-demo]# curl http://localhost
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Home Page - azuredevops_demo.web</title>
    <link rel="stylesheet" href="/lib/bootstrap/dist/css/bootstrap.min.css" />
    <link rel="stylesheet" href="/css/site.css" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" href="/">azuredevops_demo.web</a>
                <button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" href="/">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" href="/Home/Privacy">Privacy</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
             
<div class="text-center">
    <h1 class="display-4">Feel the power of Azure DevOps CI/CD</h1>
    <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">Dokerizing Web apps with ASP.NET Core</a>.</p>
</div>
 
        </main>
    </div>
 
    <footer class="border-top footer text-muted">
        <div class="container">
            © 2020 - azuredevops_demo.web - <a href="/Home/Privacy">Privacy</a>
        </div>
    </footer>
    <script src="/lib/jquery/dist/jquery.min.js"></script>
    <script src="/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
    <script src="/js/site.js?v=BxFAw9RUJ1E4NycpKEjCNDeoSvr4RPHixdBq5wDnkeY"></script>
     
</body>
</html>

 

웹브라우저 상에서도 접속을 시도하여 결과를 확인한다.

 

 

 

 

 

 

 

Azure Container Registry(ACR) 생성

 

이제 로컬환경에서 검증된 도커 이미지를 Azure Container Registry로 push하도록 하겠다. 

az login을 통해 Azure 계정에 연결 되어 있어야 한다. 준비가 안되었다면 여기를 참조한다. 

다음 명령을 사용하여 ACR을 생성한다.

#  변수선언
rgName=handson0223
location=koreacentral
acrName=zeroacrdemo

#  리소스 그룹 생성
az group create --name $rgName --location $location

#  Azure Container Registry 생성
az acr create --name $acrName --resource-group $rgName --sku Basic --admin-enabled true

[root@ansible-vmc webapp4container-cicd-demo]# rgName=handson0223
[root@ansible-vmc webapp4container-cicd-demo]# location=koreacentral
[root@ansible-vmc webapp4container-cicd-demo]# acrName=zeroacrdemo
[root@ansible-vmc webapp4container-cicd-demo]# az group create --name $rgName --location $location
{
  "id": "/subscriptions/f8764f39-xxxx-xxxx-xxxx-77b286ed971b/resourceGroups/handson0223",
  "location": "koreacentral",
  "managedBy": null,
  "name": "handson0223",
  "properties": {
    "provisioningState": "Succeeded"
  },
  "tags": null,
  "type": "Microsoft.Resources/resourceGroups"
}
[root@ansible-vmc webapp4container-cicd-demo]# az acr create --name $acrName --resource-group $rgName --sku Basic --admin-enabled true
{
  "adminUserEnabled": true,
  "creationDate": "2020-02-23T00:42:54.568068+00:00",
  "id": "/subscriptions/f8764f39-xxxx-xxxx-xxxx-77b286ed971b/resourceGroups/handson0223/providers/Microsoft.ContainerRegistry/registries/zeroacrdemo",
  "location": "koreacentral",
  "loginServer": "zeroacrdemo.azurecr.io",
  "name": "zeroacrdemo",
  "networkRuleSet": null,
  "policies": {
    "quarantinePolicy": {
      "status": "disabled"
    },
    "retentionPolicy": {
      "days": 7,
      "lastUpdatedTime": "2020-02-23T00:42:56.806476+00:00",
      "status": "disabled"
    },
    "trustPolicy": {
      "status": "disabled",
      "type": "Notary"
    }
  },
  "provisioningState": "Succeeded",
  "resourceGroup": "handson0223",
  "sku": {
    "name": "Basic",
    "tier": "Basic"
  },
  "status": null,
  "storageAccount": null,
  "tags": {},
  "type": "Microsoft.ContainerRegistry/registries"
}

 

 

 

 

 

 

Azure Container Registry(ACR) 이미지 push

 

이미지를 ACR에 push하려면 개인 레지스트리를 사용하여 인증한다. 다음 명령을 사용하여 만든 레지스트리에서 자격 증명을 검색한다.

az login을 통해 Azure 계정에 연결 되어 있어야 한다. 준비가 안되었다면 여기를 참조한다. 

az acr credential show --name $acrName

[root@ansible-vmc webapp4container-cicd-demo]# az acr credential show --name $acrName
{
  "passwords": [
    {
      "name": "password",
      "value": "w=J6EB175DtjF3fWSoVzyJoLOTZ/8glE"
    },
    {
      "name": "password2",
      "value": "xyporQhpxM4Onazlttk2DyN0c/F0w2Mr"
    }
  ],
  "username": "zeroacrdemo"
}

 

출력 정보를 참고하여 다음 명령을 사용하여 ACR에 로그인 한다.

docker login $acrName.azurecr.io --username $acrName

[root@ansible-vmc webapp4container-cicd-demo]# docker login $acrName.azurecr.io --username $acrName
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
 
Login Succeeded

 

다음 명령을 사용하여 생성한 ACR의 loginServer를 쿼리해본다.

az acr list --resource-group $rgName --query "[].{acrLoginServer:loginServer}" --output table

결과는 다음과 같은 모습일 것이다.

[root@ansible-vmc webapp4container-cicd-demo]# az acr list --resource-group $rgName --query "[].{acrLoginServer:loginServer}" --output table
AcrLoginServer
----------------------
zeroacrdemo.azurecr.io

 

이제 로컬에서 빌드하여 테스트했던 이미지를 태깅하여  ACR에 push 한다.

 #  docker 이미지 태깅
docker tag wa4container-demo $acrName.azurecr.io/wa4container-demo

#  docker 이미지 푸시
docker push $acrName.azurecr.io/wa4container-demo

#  docker 이미지 푸시 결과 확인
az acr repository list --name $acrName --output table

 

 

[root@ansible-vmc webapp4container-cicd-demo]# docker tag wa4container-demo $acrName.azurecr.io/wa4container-demo
[root@ansible-vmc webapp4container-cicd-demo]# docker push $acrName.azurecr.io/wa4container-demo
The push refers to repository [zeroacrdemo.azurecr.io/wa4container-demo]
05d121a73f98: Pushed
248eda1d28f8: Pushed
2688285497ef: Pushed
383100ee58c3: Pushed
6e98de2e6b3f: Pushed
a9e56403c599: Pushed
488dfecc21b1: Pushed
latest: digest: sha256:e076c04ee57c135dbd5cf2541aafbfcc5fbf8b1e0affdb3886db85129861777d size: 1792
[root@ansible-vmc webapp4container-cicd-demo]# az acr repository list --name $acrName --output table
Result
-----------------
wa4container-demo

 

참고로 Azure 포털에서 중앙 상단의 검색창에서 "ACR"이라고 입력하고 검색 결과 중에서 생성한 ACR을 선택하여 이동하면 다음과 같이 정상적으로 이미지가 등록된 것을 확인할 수 있다.

 

 

 

 

 

 

 

Azure Web App 생성

 

먼저 App Service Plan을 생성하고 이 Plan에 Web App을 생성한다.

참골고 App Service의 앱은 App Service Plan에서 실행된다.  App Service Plan은 실행할 웹앱에 대한 컴퓨팅 리소스 세트를 정의한 것으로 기존 웹 호스팅에서의 섭버 팜 정도로 생각하면 될 것이다.

#  App Service Plan 생성
az appservice plan create --name zeroaspdemo --resource-group $rgName --sku B1 --is-linux

#  Web App 생성
az webapp create --resource-group $rgName --plan zeroaspdemo --name wa4container-demo --deployment-container-image-name $acrName.azurecr.io/wa4container-demo

#  Web App 기본 URL 확인
az webapp config hostname list --resource-group $rgName --webapp-name wa4container-demo --query "[].{ name: name}" --out tsv

[root@ansible-vmc webapp4container-cicd-demo]# az appservice plan create --name zeroaspdemo --resource-group $rgName --sku B1 --is-linux
{
  "freeOfferExpirationTime": "2020-03-24T00:51:14.263333",
  "geoRegion": "Korea Central",
  "hostingEnvironmentProfile": null,
  "hyperV": false,
  "id": "/subscriptions/f8764f39-xxxx-xxxx-xxxx-77b286ed971b/resourceGroups/handson0223/providers/Microsoft.Web/serverfarms/zeroaspdemo",
  "isSpot": false,
  "isXenon": false,
  "kind": "linux",
  "location": "Korea Central",
  "maximumElasticWorkerCount": 1,
  "maximumNumberOfWorkers": 3,
  "name": "zeroaspdemo",
  "numberOfSites": 0,
  "perSiteScaling": false,
  "provisioningState": "Succeeded",
  "reserved": true,
  "resourceGroup": "handson0223",
  "sku": {
    "capabilities": null,
    "capacity": 1,
    "family": "B",
    "locations": null,
    "name": "B1",
    "size": "B1",
    "skuCapacity": null,
    "tier": "Basic"
  },
  "spotExpirationTime": null,
  "status": "Ready",
  "subscription": "f8764f39-xxxx-xxxx-xxxx-77b286ed971b",
  "tags": null,
  "targetWorkerCount": 0,
  "targetWorkerSizeId": 0,
  "type": "Microsoft.Web/serverfarms",
  "workerTierName": null
}
[root@ansible-vmc webapp4container-cicd-demo]# az webapp create --resource-group $rgName --plan zeroaspdemo --name wa4container-demo --deployment-container-image-name $acrName.azurecr.io/wa4container-demo
No credential was provided to access Azure Container Registry. Trying to look up...
{
  "availabilityState": "Normal",
  "clientAffinityEnabled": true,
  "clientCertEnabled": false,
  "clientCertExclusionPaths": null,
  "cloningInfo": null,
  "containerSize": 0,
  "dailyMemoryTimeQuota": 0,
  "defaultHostName": "wa4container-demo.azurewebsites.net",
  "enabled": true,
  "enabledHostNames": [
    "wa4container-demo.azurewebsites.net",
    "wa4container-demo.scm.azurewebsites.net"
  ],
  "ftpPublishingUrl": "ftp://waws-prod-se1-003.ftp.azurewebsites.windows.net/site/wwwroot",
  "hostNameSslStates": [
    {
      "hostType": "Standard",
      "ipBasedSslResult": null,
      "ipBasedSslState": "NotConfigured",
      "name": "wa4container-demo.azurewebsites.net",
      "sslState": "Disabled",
      "thumbprint": null,
      "toUpdate": null,
      "toUpdateIpBasedSsl": null,
      "virtualIp": null
    },
    {
      "hostType": "Repository",
      "ipBasedSslResult": null,
      "ipBasedSslState": "NotConfigured",
      "name": "wa4container-demo.scm.azurewebsites.net",
      "sslState": "Disabled",
      "thumbprint": null,
      "toUpdate": null,
      "toUpdateIpBasedSsl": null,
      "virtualIp": null
    }
  ],
  "hostNames": [
    "wa4container-demo.azurewebsites.net"
  ],
  "hostNamesDisabled": false,
  "hostingEnvironmentProfile": null,
  "httpsOnly": false,
  "hyperV": false,
  "id": "/subscriptions/f8764f39-xxxx-xxxx-xxxx-77b286ed971b/resourceGroups/handson0223/providers/Microsoft.Web/sites/wa4container-demo",
  "identity": null,
  "inProgressOperationId": null,
  "isDefaultContainer": null,
  "isXenon": false,
  "kind": "app,linux,container",
  "lastModifiedTimeUtc": "2020-02-23T00:51:49.250000",
  "location": "Korea Central",
  "maxNumberOfWorkers": null,
  "name": "wa4container-demo",
  "outboundIpAddresses": "52.231.38.95,52.231.37.184,52.231.38.172,52.231.33.182,52.231.34.9",
  "possibleOutboundIpAddresses": "52.231.38.95,52.231.37.184,52.231.38.172,52.231.33.182,52.231.34.9,52.231.69.201,52.231.66.155",
  "redundancyMode": "None",
  "repositorySiteName": "wa4container-demo",
  "reserved": true,
  "resourceGroup": "handson0223",
  "scmSiteAlsoStopped": false,
  "serverFarmId": "/subscriptions/f8764f39-xxxx-xxxx-xxxx-77b286ed971b/resourceGroups/handson0223/providers/Microsoft.Web/serverfarms/zeroaspdemo",
  "siteConfig": null,
  "slotSwapStatus": null,
  "state": "Running",
  "suspendedTill": null,
  "tags": null,
  "targetSwapSlot": null,
  "trafficManagerHostNames": null,
  "type": "Microsoft.Web/sites",
  "usageState": "Normal"
}
[root@ansible-vmc webapp4container-cicd-demo]# az webapp config hostname list --resource-group $rgName --webapp-name wa4container-demo --query "[].{ name: name}" --out tsv
wa4container-demo.azurewebsites.net

 

출력된 URL 정보를 웹 브라우저 상에 입력하고 결과를 확인한다.

정상적으로 메시지가 출력됨을 확인할 수 있다.

App Service에서 프라이빗 이미지를 끌어오려면 레지스트리와 이미지에 대한 정보가 필요하다.

 

 

 

 

 

 

 

Web App에서 ACR 자격 증명 구성

 

acr_auth.sh 파일을 열어 ACR_NANE 부분을 각자의 상황에 맞게 수정하고 저장한다.

#!/bin/bash

 

# Modify for your environment.

# ACR_NAME: The name of your Azure Container Registry

# SERVICE_PRINCIPAL_NAME: Must be unique within your AD tenant

ACR_NAME=zeroacrdemo

SERVICE_PRINCIPAL_NAME=acr-service-principal

 

# Obtain the full registry ID for subsequent command args

ACR_REGISTRY_ID=$(az acr show --name $ACR_NAME --query id --output tsv)

 

# Create the service principal with rights scoped to the registry.

# Default permissions are for docker pull access. Modify the '--role'

# argument value as desired:

# acrpull:     pull only

# acrpush:     push and pull

# owner:       push, pull, and assign roles

#SP_PASSWD=$(az ad sp create-for-rbac --name http://$SERVICE_PRINCIPAL_NAME --scopes $ACR_REGISTRY_ID --role acrpull --query password --output tsv)

#SP_APP_ID=$(az ad sp show --id http://$SERVICE_PRINCIPAL_NAME --query appId --output tsv)

 

쉘을 실행하여 권한을 부여한다.

[root@ansible-vmc webapp4container-cicd-demo]# source acr_auth.sh
Found an existing application instance of "5a8ef423-769b-433d-bfd7-96896e451a89". We will patch it
Creating a role assignment under the scope of "/subscriptions/f8764f39-xxxx-xxxx-xxxx-77b286ed971b/resourceGroups/handson0223/providers/Microsoft.ContainerRegistry/registries/zeroacrdemo"

 

서비스 주체를 사용하여 ACI를 생성한다.

 #  서비스 주체를 사용하여 인증

az webapp config container set \
--name wa4container-demo \
--resource-group $rgName \
--docker-custom-image-name zeroacrdemo.azurecr.io/wa4container-demo \
--docker-registry-server-url https://zeroacrdemo.azurecr.io \
--docker-registry-server-user $SP_APP_ID \
--docker-registry-server-password $SP_PASSWD

[root@ansible-vmc webapp4container-cicd-demo]# az webapp config container set \
> --name wa4container-demo \
> --resource-group $rgName \
> --docker-custom-image-name $acrName.azurecr.io/wa4container-demo \
> --docker-registry-server-url https://zeroacrdemo.azurecr.io \
> --docker-registry-server-user $SP_APP_ID \
> --docker-registry-server-password $SP_PASSWD
[
  {
    "name": "WEBSITES_ENABLE_APP_SERVICE_STORAGE",
    "slotSetting": false,
    "value": "false"
  },
  {
    "name": "DOCKER_REGISTRY_SERVER_URL",
    "slotSetting": false,
    "value": "https://zeroacrdemo.azurecr.io"
  },
  {
    "name": "DOCKER_REGISTRY_SERVER_USERNAME",
    "slotSetting": false,
    "value": "5a8ef423-769b-433d-bfd7-96896e451a89"
  },
  {
    "name": "DOCKER_REGISTRY_SERVER_PASSWORD",
    "slotSetting": false,
    "value": null
  },
  {
    "name": "DOCKER_CUSTOM_IMAGE_NAME",
    "value": "DOCKER|zeroacrdemo.azurecr.io/wa4container-demo"
  }
]

 

 

 

 

 

 

 

Azure DevOps 파이프라인 구성

 

Build 파이프라인 구성

 

기존에 생성해 둔 프로젝트에서 Build 파이프라인 우측 상단에 Edit을 선택한다.

 

Agent job 1 우측의 + 아이콘을 누르고 "docker"라고 입력한 후 결과 중 Docker(buildAndPush)를 선택하여 Add 한다.

 

buildAndPush를 선택하고 Container Registry 셀랙트 박스 옆에 + New를 선택하고 서비스 커넥션을 구성하고 저장한다.

 

Save & queue를 선택 후 save 를 선택하여 구성을 저장한다.

 

Get sources -  GitHub를 선택하고 필요 시 인증을 거쳐 소스가 전재하는 해당 git 리포지토리를 선택한다.

 

Save & queue를 선택하여 빌드를 실행하여 구성을 검증한다.

빌드가 정상적으로 이루어졌다면 ACR의 리포지토리 내 push한 이미지가 정상적으로 보여질 것이다.

 

 

Release 파이프라인 구성

 

New pipeline을 선택하여 새로 생성한다.

바로 등장하는 템플릿 선택화면에서 Azure App Service deployment를 선택하고 Apply 한다.

 

Stage 이름을 임의로 수정하고 Add an artifact 화면에서 빌드 파이프라인의 소스 위치를 선택하고 Add 한다.

 

Deploy Azure App Service Task를 다음과 같이 선택/입력 후 Save 한다.

 

이제 Continuous deployment trigger를 설정하고 저장한다.

 

 

 

 

 

 

 

Azure DevOps 파이프라인 구성 검증

 

파이프라인 구성에 대한 검증을 위해 소스 코드를 수정하고 git add, commit 및 push를 수행한다. 

 

[root@ansible-vmc webapp4container-cicd-demo]# git add .
[root@ansible-vmc webapp4container-cicd-demo]# git commit -m "Updated Index.cshtml"
[master e24a609] Updated Index.cshtml
 1 file changed, 1 insertion(+), 1 deletion(-)
[root@ansible-vmc webapp4container-cicd-demo]# git push
Counting objects: 9, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (5/5), 456 bytes | 0 bytes/s, done.
Total 5 (delta 3), reused 0 (delta 0)
remote: Resolving deltas: 100% (3/3), completed with 3 local objects.
To https://github.com/zer0big/webapp4container-cicd-demo.git
   c169888..e24a609  master -> master

 

Azure DevOps에서 빌드 파이프라인이 실행된다.

 

CI 빌드가 정상적으로 이루어지면 릴리즈 파이프라인이 동작되어 배포가 이루어진다.

이제 다시 웹페이지를 새로고침하면 다음과 같이 정상적으로 의도한 결과가 반영됨을 확인할 수 있다.

 

 

 

 

 

 

 

기타 사항 

 

참고로 생성된 Web App - Container settings의 화면으로 이동해보면 이미지 처리에 대한 로그를 확인할 수 있는데, 페이지가 정상적으로 로딩되지 않는 경우 단서를 찾는데 활용할 수 있다.

 

또한 Web App -  Monitoring - Log stream을 통해서도 운영에 필요한 유용한 정보를 얻을 수 있으며

 

특히 다음과 같이 HTTP Result 코드 값, Thread Count 등등 여러 유용한 Metrics 정보가 기본으로 제공된다.  

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함