티스토리 뷰
<참조> https://azuredevopslabs.com/labs/vstsextend/docker/
개요
Docker 컨테이너 이미지는 코드, 런타임, 시스템 도구, 시스템 라이브러리 및 설정 등 애플리케이션을 실행하는 데 필요한 모든 것이 포함된 경량의 독립 실행형 소프트웨어 패키지이다.
이 랩에서는 ASP.NET Core 애플리케이션의 사용자 지정 Docker 이미지를 빌드하고 해당 이미지를 ACR(Azure Container Registry)의 프라이빗 리포지토리로 푸시하는 프로세스를 간략하게 설명한다. 이러한 이미지는 Azure DevOps를 사용하여 Azure App Service (Linux)의 Docker 컨테이너에 애플리케이션을 배포하는 데 사용된다.
Web App for Containers를 사용하면 사용자 지정 Docker 컨테이너 이미지를 만들고 Azure에서 쉽게 배포한 다음 실행할 수 있다. Azure DevOps와 Azure를 Docker와 통합하면 다음이 가능하다.
1. Azure DevOps Hosted Linux 에이전트를 사용하여 사용자 지정 Docker 이미지 빌드
2. Docker 이미지를 비공개 저장소에 푸시 및 저장
3. Docker 컨테이너 내에서 이미지 배포 및 실행
시작하기 전에
1. 이 실습의 전제 조건을 알아 보려면 시작하기 페이지를 참조한다.
2. Azure DevOps 데모 생성기 링크를 클릭하고 시작하기 페이지의 지침에 따라 프로젝트를 Azure DevOps에 프로비전 한다.
환경 설정하기
1. 이 실습을 위해 다음 리소스를 구성해야 한다.
-
Azure Container Registry
-
Azure Web App for Containers
-
Azure SQL Server Database
2. Azure Portal에서 Azure Cloud Shell을 시작하고 Bash를 선택한다.
3. Azure Container Registry을 생성한다.
3.1 리소스 그룹을 만든다 .<region>을 선택한 지역(예 : koreacentral)으로 바꾼다.
az group create --name DockerRG --location <region> |
zerobig_devops@Azure:~$ az group create --name DockerRG --location koreacentral
{
"id": "/subscriptions/a791ad38-xxxx-xxxx-xxxx-460ee318d917/resourceGroups/DockerRG",
"location": "koreacentral",
"managedBy": null,
"name": "DockerRG",
"properties": {
"provisioningState": "Succeeded"
},
"tags": null,
"type": "Microsoft.Resources/resourceGroups"
}
3.2 ACR을 만든다.
az acr create -n <unique-acr-name> -g DockerRG --sku Standard --admin-enabled true |
<중요> 고유한 ACR 이름을 입력한다. ACR 이름은 영숫자만 포함 할 수 있으며 5 자에서 50 자 사이 여야한다.
zerobig_devops@Azure:~$ az acr create -n zerobigacrdemo -g DockerRG --sku Standard --admin-enabled true
{- Finished ..
"adminUserEnabled": true,
"creationDate": "2020-08-22T03:07:58.512015+00:00",
"dataEndpointEnabled": false,
"dataEndpointHostNames": [],
"encryption": {
"keyVaultProperties": null,
"status": "disabled"
},
"id": "/subscriptions/a791ad38-xxxx-xxxx-xxxx-460ee318d917/resourceGroups/DockerRG/providers/Microsoft.ContainerRegistry/registries/zerobigacrdemo",
"identity": null,
"location": "koreacentral",
"loginServer": "zerobigacrdemo.azurecr.io",
"name": "zerobigacrdemo",
"networkRuleSet": null,
"policies": {
"quarantinePolicy": {
"status": "disabled"
},
"retentionPolicy": {
"days": 7,
"lastUpdatedTime": "2020-08-22T03:08:01.040179+00:00",
"status": "disabled"
},
"trustPolicy": {
"status": "disabled",
"type": "Notary"
}
},
"privateEndpointConnections": [],
"provisioningState": "Succeeded",
"publicNetworkAccess": "Enabled",
"resourceGroup": "DockerRG",
"sku": {
"name": "Standard",
"tier": "Standard"
},
"status": null,
"storageAccount": null,
"tags": {},
"type": "Microsoft.ContainerRegistry/registries"
}
4. 컨테이너 용 Azure Web App 만든다.
4.1 Linux 앱 서비스 플랜을 만든다.
az appservice plan create -n myappserviceplan -g DockerRG --is-linux |
zerobig_devops@Azure:~$ az appservice plan create -n zerobigasp -g DockerRG --is-linux
{- Finished ..
"freeOfferExpirationTime": "2020-09-21T03:10:43.986666",
"geoRegion": "Korea Central",
"hostingEnvironmentProfile": null,
"hyperV": false,
"id": "/subscriptions/a791ad38-xxxx-xxxx-xxxx-460ee318d917/resourceGroups/DockerRG/providers/Microsoft.Web/serverfarms/zerobigasp",
"isSpot": false,
"isXenon": false,
"kind": "linux",
"location": "Korea Central",
"maximumElasticWorkerCount": 1,
"maximumNumberOfWorkers": 3,
"name": "zerobigasp",
"numberOfSites": 0,
"perSiteScaling": false,
"provisioningState": "Succeeded",
"reserved": true,
"resourceGroup": "DockerRG",
"sku": {
"capabilities": null,
"capacity": 1,
"family": "B",
"locations": null,
"name": "B1",
"size": "B1",
"skuCapacity": null,
"tier": "Basic"
},
"spotExpirationTime": null,
"status": "Ready",
"subscription": "a791ad38-xxxx-xxxx-xxxx-460ee318d917",
"tags": null,
"targetWorkerCount": 0,
"targetWorkerSizeId": 0,
"type": "Microsoft.Web/serverfarms",
"workerTierName": null
}
4.2 사용자 지정 Docker 컨테이너 웹앱 만들기 : 웹앱을 만들고 사용자 지정 Docker 컨테이너를 실행하도록 구성하려면 다음 명령을 실행한다.
az webapp create -n <unique-appname> -g DockerRG -p myappserviceplan -i elnably/dockerimagetest |
zerobig_devops@Azure:~$ az webapp create -n zerobigwa -g DockerRG -p zerobigasp -i elnably/dockerimagetest
{- Finished ..
"availabilityState": "Normal",
"clientAffinityEnabled": true,
"clientCertEnabled": false,
"clientCertExclusionPaths": null,
"cloningInfo": null,
"containerSize": 0,
"dailyMemoryTimeQuota": 0,
"defaultHostName": "zerobigwa.azurewebsites.net",
"enabled": true,
"enabledHostNames": [
"zerobigwa.azurewebsites.net",
"zerobigwa.scm.azurewebsites.net"
],
"ftpPublishingUrl": "ftp://waws-prod-se1-003.ftp.azurewebsites.windows.net/site/wwwroot",
"hostNameSslStates": [
{
"hostType": "Standard",
"ipBasedSslResult": null,
"ipBasedSslState": "NotConfigured",
"name": "zerobigwa.azurewebsites.net",
"sslState": "Disabled",
"thumbprint": null,
"toUpdate": null,
"toUpdateIpBasedSsl": null,
"virtualIp": null
},
{
"hostType": "Repository",
"ipBasedSslResult": null,
"ipBasedSslState": "NotConfigured",
"name": "zerobigwa.scm.azurewebsites.net",
"sslState": "Disabled",
"thumbprint": null,
"toUpdate": null,
"toUpdateIpBasedSsl": null,
"virtualIp": null
}
],
"hostNames": [
"zerobigwa.azurewebsites.net"
],
"hostNamesDisabled": false,
"hostingEnvironmentProfile": null,
"httpsOnly": false,
"hyperV": false,
"id": "/subscriptions/a791ad38-xxxx-xxxx-xxxx-460ee318d917/resourceGroups/DockerRG/providers/Microsoft.Web/sites/zerobigwa",
"identity": null,
"inProgressOperationId": null,
"isDefaultContainer": null,
"isXenon": false,
"kind": "app,linux,container",
"lastModifiedTimeUtc": "2020-08-22T03:13:17.800000",
"location": "Korea Central",
"maxNumberOfWorkers": null,
"name": "zerobigwa",
"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": "zerobigwa",
"reserved": true,
"resourceGroup": "DockerRG",
"scmSiteAlsoStopped": false,
"serverFarmId": "/subscriptions/a791ad38-xxxx-xxxx-xxxx-460ee318d917/resourceGroups/DockerRG/providers/Microsoft.Web/serverfarms/zerobigasp",
"siteConfig": {
"acrUseManagedIdentityCreds": false,
"acrUserManagedIdentityID": null,
"alwaysOn": null,
"apiDefinition": null,
"apiManagementConfig": null,
"appCommandLine": null,
"appSettings": null,
"autoHealEnabled": null,
"autoHealRules": null,
"autoSwapSlotName": null,
"azureMonitorLogCategories": null,
"azureStorageAccounts": null,
"connectionStrings": null,
"cors": null,
"customAppPoolIdentityAdminState": null,
"customAppPoolIdentityTenantState": null,
"defaultDocuments": null,
"detailedErrorLoggingEnabled": null,
"documentRoot": null,
"experiments": null,
"fileChangeAuditEnabled": null,
"ftpsState": null,
"functionAppScaleLimit": null,
"functionsRuntimeScaleMonitoringEnabled": null,
"handlerMappings": null,
"healthCheckPath": null,
"http20Enabled": null,
"httpLoggingEnabled": null,
"ipSecurityRestrictions": [
{
"action": "Allow",
"description": "Allow all access",
"ipAddress": "Any",
"name": "Allow all",
"priority": 1,
"subnetMask": null,
"subnetTrafficTag": null,
"tag": null,
"vnetSubnetResourceId": null,
"vnetTrafficTag": null
}
],
"javaContainer": null,
"javaContainerVersion": null,
"javaVersion": null,
"limits": null,
"linuxFxVersion": null,
"loadBalancing": null,
"localMySqlEnabled": null,
"logsDirectorySizeLimit": null,
"machineKey": null,
"managedPipelineMode": null,
"managedServiceIdentityId": null,
"metadata": null,
"minTlsVersion": null,
"minimumElasticInstanceCount": 0,
"netFrameworkVersion": null,
"nodeVersion": null,
"numberOfWorkers": null,
"phpVersion": null,
"powerShellVersion": null,
"preWarmedInstanceCount": null,
"publishingPassword": null,
"publishingUsername": null,
"push": null,
"pythonVersion": null,
"remoteDebuggingEnabled": null,
"remoteDebuggingVersion": null,
"requestTracingEnabled": null,
"requestTracingExpirationTime": null,
"routingRules": null,
"runtimeADUser": null,
"runtimeADUserPassword": null,
"scmIpSecurityRestrictions": [
{
"action": "Allow",
"description": "Allow all access",
"ipAddress": "Any",
"name": "Allow all",
"priority": 1,
"subnetMask": null,
"subnetTrafficTag": null,
"tag": null,
"vnetSubnetResourceId": null,
"vnetTrafficTag": null
}
],
"scmIpSecurityRestrictionsUseMain": null,
"scmMinTlsVersion": null,
"scmType": null,
"tracingOptions": null,
"use32BitWorkerProcess": null,
"virtualApplications": null,
"vnetName": null,
"vnetRouteAllEnabled": null,
"webSocketsEnabled": null,
"websiteTimeZone": null,
"winAuthAdminState": null,
"winAuthTenantState": null,
"windowsFxVersion": null,
"xManagedServiceIdentityId": null
},
"slotSwapStatus": null,
"state": "Running",
"suspendedTill": null,
"tags": null,
"targetSwapSlot": null,
"trafficManagerHostNames": null,
"type": "Microsoft.Web/sites",
"usageState": "Normal"
}
5. Azure SQL 서버 및 데이터베이스 만들기 : Azure SQL 서버를 만든다 .
az sql server create -l <region> -g DockerRG -n <unique-sqlserver-name> -u sqladmin -p P2ssw0rd1234 |
zerobig_devops@Azure:~$ az sql server create -l koreacentral -g DockerRG -n zerobigsqldemo -u sqladmin -p P2ssw0rd1234
{- Finished ..
"administratorLogin": "sqladmin",
"administratorLoginPassword": null,
"fullyQualifiedDomainName": "zerobigsqldemo.database.windows.net",
"id": "/subscriptions/a791ad38-xxxx-xxxx-xxxx-460ee318d917/resourceGroups/DockerRG/providers/Microsoft.Sql/servers/zerobigsqldemo",
"identity": null,
"kind": "v12.0",
"location": "koreacentral",
"minimalTlsVersion": null,
"name": "zerobigsqldemo",
"privateEndpointConnections": [],
"publicNetworkAccess": "Enabled",
"resourceGroup": "DockerRG",
"state": "Ready",
"tags": null,
"type": "Microsoft.Sql/servers",
"version": "12.0"
}
데이터베이스를 만든다.
az sql db create -g DockerRG -s <unique-sqlserver-name> -n mhcdb --service-objective S0 |
<중요> 유한 SQL 서버 이름을 입력한다. Azure SQL 서버 이름이 UPPER / Camel 케이싱 명명 규칙을 지원하지 않으므로 DB 서버 이름 필드 값에 소문자를 사용한다.
zerobig_devops@Azure:~$ az sql db create -g DockerRG -s zerobigsqldemo -n mhcdb --service-objective S0
{- Finished ..
"autoPauseDelay": null,
"catalogCollation": "SQL_Latin1_General_CP1_CI_AS",
"collation": "SQL_Latin1_General_CP1_CI_AS",
"createMode": null,
"creationDate": "2020-08-22T03:22:40.353000+00:00",
"currentServiceObjectiveName": "S0",
"currentSku": {
"capacity": 10,
"family": null,
"name": "Standard",
"size": null,
"tier": "Standard"
},
"databaseId": "23a9d20a-05eb-458d-95a7-e4f30f70ae41",
"defaultSecondaryLocation": "koreasouth",
"earliestRestoreDate": "2020-08-22T03:52:40.353000+00:00",
"edition": "Standard",
"elasticPoolId": null,
"elasticPoolName": null,
"failoverGroupId": null,
"id": "/subscriptions/a791ad38-xxxx-xxxx-xxxx-460ee318d917/resourceGroups/DockerRG/providers/Microsoft.Sql/servers/zerobigsqldemo/databases/mhcdb",
"kind": "v12.0,user",
"licenseType": null,
"location": "koreacentral",
"longTermRetentionBackupResourceId": null,
"managedBy": null,
"maxLogSizeBytes": null,
"maxSizeBytes": 268435456000,
"minCapacity": null,
"name": "mhcdb",
"pausedDate": null,
"readReplicaCount": 0,
"readScale": "Disabled",
"recoverableDatabaseId": null,
"recoveryServicesRecoveryPointId": null,
"requestedServiceObjectiveName": "S0",
"resourceGroup": "DockerRG",
"restorableDroppedDatabaseId": null,
"restorePointInTime": null,
"resumedDate": null,
"sampleName": null,
"sku": {
"capacity": 10,
"family": null,
"name": "Standard",
"size": null,
"tier": "Standard"
},
"sourceDatabaseDeletionDate": null,
"sourceDatabaseId": null,
"status": "Online",
"tags": null,
"type": "Microsoft.Sql/servers/databases",
"zoneRedundant": false
}
6. Azure 서비스에서 액세스를 허용하는 SQL Server에 대한 방화벽 규칙을 만든다.
az sql server firewall-rule create --resource-group DockerRG --server <your-sqlserver-name> --name AllowAllAzureIps --start-ip-address 0.0.0.0 --end-ip-address 0.0.0.0 |
zerobig_devops@Azure:~$ az sql server firewall-rule create --resource-group DockerRG --server zerobigsqldemo --name AllowAllAzureIps --start-ip-address 0.0.0.0 --end-ip-address 0.0.0.0
{
"endIpAddress": "0.0.0.0",
"id": "/subscriptions/a791ad38-xxxx-xxxx-xxxx-460ee318d917/resourceGroups/DockerRG/providers/Microsoft.Sql/servers/zerobigsqldemo/firewallRules/AllowAllAzureIps",
"kind": "v12.0",
"location": "Korea Central",
"name": "AllowAllAzureIps",
"resourceGroup": "DockerRG",
"startIpAddress": "0.0.0.0",
"type": "Microsoft.Sql/servers/firewallRules"
}
7. 웹 앱의 연결 문자열을 업데이트 한다.
az webapp config connection-string set -g DockerRG -n <your-appservice-name> --connection-string-type SQLAzure --settings defaultConnection='Data Source=tcp:<your-sqlserver-name>.database.windows.net,1433;Initial Catalog=mhcdb;User Id=sqladmin;Password=P2ssw0rd1234;' |
위 명령에서 앱 서비스 이름과 SQL 서버 이름을 업데이트 한다. 이 명령은 defaultConnection이라는 이름으로 앱 서비스에 연결 문자열을 추가한다.
zerobig_devops@Azure:~$ az webapp config connection-string set -g DockerRG -n zerobigwa --connection-string-type SQLAzure --settings defaultConnection='Data Source=tcp:zerobigsqldemo.database.windows.net,1433;
Initial Catalog=mhcdb;User Id=sqladmin;Password=P2ssw0rd1234;'
{
"defaultConnection": {
"type": "SQLAzure",
"value": "Data Source=tcp:zerobigsqldemo.database.windows.net,1433;Initial Catalog=mhcdb;User Id=sqladmin;Password=P2ssw0rd1234;"
}
}
8. 리소스 그룹으로 이동한다. 다음 구성 요소가 프로비저닝 된 것을 볼 수 있다.
9. mhcdb SQL 데이터베이스를 클릭하고 헤더 Server name 아래에 서버 세부 정보를 기록해 둔다.
10. 리소스 그룹으로 다시 이동한다. 컨테이너 레지스트리를 클릭하고 로그인 헤더 Login server 아래에 서버 세부 정보를 기록해 둔다. 이러한 세부 사항은 실습 2에서 필요하다.
실습 1: Continuous Integration(CI) 및 Continuous Delivery(CD) 구성
이제 필요한 리소스가 프로비저닝되었으므로 새 정보를 가지고 Pipelines 및 Release 정의를 수동으로 구성해야 한다. dacpac은 또한 mhcdb 데이터베이스에 배포되어 스키마와 데이터가 백엔드 용으로 구성된다.
1. 파이프라인 탭에서 Pipelenes 옵션으로 이동한다. 빌드 정의 MHCDocker.build의 Edit 옵션을 선택한다.
2. Run services, Build services and Push services 태스크에서 Azure 구독에 권한을 부여하고 (첫 번째 작업에만 해당) 드롭 다운의 엔트포인트 구성 요소로 Azure Container Registry를 업데이트하고 Save를 클릭한다.
3. 파이프 라인 탭 아래의 Releases 섹션으로 이동한다. 릴리즈 정의 MHCDocker.release의 Edit 옵션을 클릭 한 다음 Tasks 섹션을 클릭한다.
4. 에이전트의 사용 세부 정보는 다음과 같다.
5. Execute Azure SQL: DacpacTask 섹션의 드롭 다운에서 Azure Subscription을 선택한다.
Execute Azure SQL: DacpacTask: 이 태스크는 스키마와 데이터가 백엔드에 대해 구성되도록 dacpac을 mhcdb 데이터베이스에 배포한다.
6. AAzure App Service Deploy 태스크에서 드롭 다운의 엔드포인트 구성 요소를 사용하여 Azure subscription 및 Azure App Service name 을 업데이트 한다.
7. Variables 섹션을 클릭하고 환경을 구성하는 동안 앞서 언급한 세부 정보로 ACR 세부 정보와 SQLserver 세부 정보를 업데이트한 다음 Save 버튼을 클릭한다.
Database Name은 mhcdb로 설정되며 Server Admin Login은 sqladmin 그리고 Password는 현재 P2ssw0rd1234로 설정된다.
실습 2: 코드 커밋을 통해 CI 빌드 및 배포 시작
이 실습에서는 CI-CD를 트리거하도록 소스 코드를 수정한다.
1. Repos 탭에서 Files 섹션을 클릭하고 Docker/src/MyHealth.Web/Views/Home 폴더로 이동 한 다음 편집 할 Index.cshtml 파일을 연다.
2. 28번 줄에서 JOIN US 텍스트를 CONTACT US로 수정 한 다음 Commit 버튼을 클릭한다. 이 동작은 소스 코드에 대한 자동 빌드를 시작시킬 것이다.
3. Builds 탭을 클릭하면 MHCDoker.build buils가 대기 또는 실행되는 것을 볼 수 있다. 빌드 번호 또는 커밋을 두 번 클릭하여 진행중인 빌드를 확인한다.
4. 빌드는 웹 애플리케이션의 Docker 이미지를 생성하고 Azure Container Registry에 푸시한다. 빌드가 완료되면 빌드 요약이 표시된다.
5. Azure Portal로 이동하여이 실습을 시작할 때 생성 된 App Service를 클릭한다. Container Settings 옵션을 선택하고 제안된 정보를 제공 한 다음 Save 버튼을 클릭한다.
<팁> 새 Docker 이미지가 Azure Portal 자체의 레지스트리로 푸시 될 때마다 웹앱을 지정된 서버에 배포하도록 연속 배포를 구성 할 수 있다. 그러나 Azure DevOps CD 파이프 라인을 설정하면 애플리케이션 배포에 대해 더 나은 유연성과 추가 제어(approvals, release gates 등)가 제공된다.
6. 생성 된 Azure Container 레지스트리로 이동 한 다음 Repositories 옵션을 선택하여 생성된 Docker 이미지를 본다.
7. Pipelines 탭 아래의 Releases 섹션으로 이동하고 페이지에 표시된 최신 릴리즈를 두 번 클릭한다. 진행중인 릴리즈의 세부 정보를 보려면 로그를 클릭한다.
8. 릴리즈는 Docker 이미지로 태그가 지정된 BuildID를 기반으로 App Service에 Docker 이미지를 배포한다. 릴리즈가 완료되면 릴리즈 로그가 표시된다.
9. Azure Portal로 돌아가서 App Service의 Overview 섹션을 클릭한다. URL 필드 아래에 표시된 링크를 클릭하여 애플리케이션을 찾아보고 변경 사항을 본다.
10. 자격 증명 사용자 Username: user와 Password: P2ssw0rd@1을 사용하여 HealthClinic 웹 애플리케이션에 로그인한다.
요약
Azure DevOps 및 Azure를 통해 Azure DevOps Ubuntu Hosted Agent에서 활성화된 Docker 기능을 활용하여 Docker화된 애플리케이션을 구성했다.
'Azure와 함께 하는 DevOps' 카테고리의 다른 글
48. Django 기반 파이썬 앱을 위한 CD 파이프라인 배포하기 (0) | 2020.09.07 |
---|---|
47. Azure DevOps 프로젝트로 .NET용 CI/CD 파이프라인 생성 (0) | 2020.08.31 |
45. LaunchDarkly와 Azure Devops로 기능 플래그 관리 (0) | 2020.08.17 |
44. Azure 보드와 GitHub 통합 (0) | 2020.08.10 |
43. Azure 파이프라인과 GitHub 통합 2편 (0) | 2020.08.03 |