53. Azure에 Java 기반 톰캣 애플리케이션 배포하기
<참조> https://azuredevopslabs.com/labs/vstsextend/tomcat/
개요
이 랩에서는 Azure Pipelines를 사용하여 Azure에서 MySQL 데이터베이스를 사용하여 Apache Tomcat에 Java 웹 애플리케이션을 배포하는 방법을 알아본다. Apache Tomcat은 ASF (Apache Software Foundation)에서 개발한 오픈 소스 Java Servlet 컨테이너이다. MySQL은 매우 인기있는 오픈 소스 관계형 데이터베이스 관리 시스템이다.
이 랩에서는 Azure App Service 및 Azure Database for MySQL을 사용하게 될 것이며, Azure Database for MySQL은 오픈 소스 MySQL Server 엔진을 기반으로 하는 관계형 데이터베이스 서비스로 예측 가능한 성능과 동적 확장성을 통해 미션 크리티컬 워크로드를 처리 할 수 있는 완전 관리형 서비스형 데이터베이스이다.
추가 학습을 원한다면 Microsoft Learn에서 Java 컨테이너 배포 자동화 모듈을 확인한다.
이 랩에서 다루는 것
이 실습을 마치면 다음을 수행 할 수 있게 될 것이다.
- MySQL 데이터베이스 서버와 함께 새 Azure App Service를 만들고 Apache Tomcat을 사용하도록 웹앱 구성
- Azure App Service Task를 사용하여 WAR 파일 배포
시작하기 전에
1. 랩 실습을 시작하기 전에 시작하기 페이지를 참조한다.
2. MyShuttle을 템플릿으로 사용하여 Azure DevOps 데모 생성기를 사용하여 새 Azure DevOps 프로젝트를 프로 비전한다.
실습 1: Azure 웹앱 및 MySQL 데이터베이스 만들기
1. 포털에서 Azure Cloud Shell을 시작한다. 리소스 그룹에 배포하려면 다음 명령을 입력한다.
az group create --name ZeroResourceGroup --location koreacentral |
zerobig_devops@Azure:~$ az group create --name ZeroResourceGroup --location koreacentral
{
"id": "/subscriptions/a791ad38-xxxx-xxxx-xxxx-460ee318d917/resourceGroups/ZeroResourceGroup",
"location": "koreacentral",
"managedBy": null,
"name": "ZeroResourceGroup",
"properties": {
"provisioningState": "Succeeded"
},
"tags": null,
"type": "Microsoft.Resources/resourceGroups"
}
2. App 서비스 플랜을 만들기 위해 다음을 입력한다.
az appservice plan create --resource-group ZeroResourceGroup --name MyPlan --sku S1 |
zerobig_devops@Azure:~$ az appservice plan create --resource-group ZeroResourceGroup --name ZeroPlan --sku S1
{- Finished ..
"freeOfferExpirationTime": null,
"geoRegion": "Korea Central",
"hostingEnvironmentProfile": null,
"hyperV": false,
"id": "/subscriptions/a791ad38-xxxx-xxxx-xxxx-460ee318d917/resourceGroups/ZeroResourceGroup/providers/Microsoft.Web/serverfarms/ZeroPlan",
"isSpot": false,
"isXenon": false,
"kind": "app",
"location": "Korea Central",
"maximumElasticWorkerCount": 1,
"maximumNumberOfWorkers": 10,
"name": "ZeroPlan",
"numberOfSites": 0,
"perSiteScaling": false,
"provisioningState": "Succeeded",
"reserved": false,
"resourceGroup": "ZeroResourceGroup",
"sku": {
"capabilities": null,
"capacity": 1,
"family": "S",
"locations": null,
"name": "S1",
"size": "S1",
"skuCapacity": null,
"tier": "Standard"
},
"spotExpirationTime": null,
"status": "Ready",
"subscription": "a791ad38-xxxx-xxxx-xxxx-460ee318d917",
"tags": null,
"targetWorkerCount": 0,
"targetWorkerSizeId": 0,
"type": "Microsoft.Web/serverfarms",
"workerTierName": null
}
3. 포털에서 Azure Cloud Shell을 시작한다. 리소스 그룹에 배포하려면 다음 명령을 입력한다.
az webapp create --resource-group ZeroResourceGroup --plan ZeroPlan --name Zerobigwebapp --runtime "java|1.8|Tomcat|9.0" |
경고 :
원문의 내용과 같이 --runtime 옵션 없이 webapp을 생성하면 실습2의 1의 Stack settings 설정이 불가하다. Stack에서 Java만 선택이 안된다. 버그로 추정된다.
az webapp create --resource-group MyResourceGroup --plan MyPlan --name MyUniqueAppName
zerobig_devops@Azure:~$ az webapp create --resource-group ZeroResourceGroup --plan ZeroPlan --name Zerobigwebapp --runtime "java|1.8|Tomcat|9.0"
{- Finished ..
"availabilityState": "Normal",
"clientAffinityEnabled": true,
"clientCertEnabled": false,
"clientCertExclusionPaths": null,
"cloningInfo": null,
"containerSize": 0,
"dailyMemoryTimeQuota": 0,
"defaultHostName": "zerobigwebapp.azurewebsites.net",
"enabled": true,
"enabledHostNames": [
"zerobigwebapp.azurewebsites.net",
"zerobigwebapp.scm.azurewebsites.net"
],
"ftpPublishingUrl": "ftp://waws-prod-se1-001.ftp.azurewebsites.windows.net/site/wwwroot",
"hostNameSslStates": [
{
"hostType": "Standard",
"ipBasedSslResult": null,
"ipBasedSslState": "NotConfigured",
"name": "zerobigwebapp.azurewebsites.net",
"sslState": "Disabled",
"thumbprint": null,
"toUpdate": null,
"toUpdateIpBasedSsl": null,
"virtualIp": null
},
{
"hostType": "Repository",
"ipBasedSslResult": null,
"ipBasedSslState": "NotConfigured",
"name": "zerobigwebapp.scm.azurewebsites.net",
"sslState": "Disabled",
"thumbprint": null,
"toUpdate": null,
"toUpdateIpBasedSsl": null,
"virtualIp": null
}
],
"hostNames": [
"zerobigwebapp.azurewebsites.net"
],
"hostNamesDisabled": false,
"hostingEnvironmentProfile": null,
"httpsOnly": false,
"hyperV": false,
"id": "/subscriptions/a791ad38-xxxx-xxxx-xxxx-460ee318d917/resourceGroups/ZeroResourceGroup/providers/Microsoft.Web/sites/Zerobigwebapp",
"identity": null,
"inProgressOperationId": null,
"isDefaultContainer": null,
"isXenon": false,
"kind": "app",
"lastModifiedTimeUtc": "2020-10-10T05:29:58.210000",
"location": "Korea Central",
"maxNumberOfWorkers": null,
"name": "Zerobigwebapp",
"outboundIpAddresses": "52.231.32.121,52.231.32.122,52.231.32.123,52.231.32.124",
"possibleOutboundIpAddresses": "52.231.32.121,52.231.32.122,52.231.32.123,52.231.32.124,52.231.90.246,20.41.74.214,20.41.73.5,20.41.73.65,20.41.73.185,52.231.32.120,52.231.18.128",
"redundancyMode": "None",
"repositorySiteName": "Zerobigwebapp",
"reserved": false,
"resourceGroup": "ZeroResourceGroup",
"scmSiteAlsoStopped": false,
"serverFarmId": "/subscriptions/a791ad38-xxxx-xxxx-xxxx-460ee318d917/resourceGroups/ZeroResourceGroup/providers/Microsoft.Web/serverfarms/ZeroPlan",
"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"
}
4. 마지막으로 고유한 서버 이름으로 MySQL 서버를 만든다.
|
zerobig_devops@Azure:~$ az mysql server create --resource-group ZeroResourceGroup --name zerosqldbserver --admin-user mysqldbuser --admin-password P2ssw0rd@123 --sku-name GP_Gen5_2
{- Finished ..
"administratorLogin": "mysqldbuser",
"byokEnforcement": "Disabled",
"earliestRestoreDate": "2020-10-10T05:41:17.390000+00:00",
"fullyQualifiedDomainName": "zerosqldbserver.mysql.database.azure.com",
"id": "/subscriptions/a791ad38-xxxx-xxxx-xxxx-460ee318d917/resourceGroups/ZeroResourceGroup/providers/Microsoft.DBforMySQL/servers/zerosqldbserver",
"identity": null,
"infrastructureEncryption": "Disabled",
"location": "koreacentral",
"masterServerId": "",
"minimalTlsVersion": "TLSEnforcementDisabled",
"name": "zerosqldbserver",
"privateEndpointConnections": [],
"publicNetworkAccess": "Enabled",
"replicaCapacity": 5,
"replicationRole": "None",
"resourceGroup": "ZeroResourceGroup",
"sku": {
"capacity": 2,
"family": "Gen5",
"name": "GP_Gen5_2",
"size": null,
"tier": "GeneralPurpose"
},
"sslEnforcement": "Enabled",
"storageProfile": {
"backupRetentionDays": 7,
"geoRedundantBackup": "Disabled",
"storageAutogrow": "Enabled",
"storageMb": 5120
},
"tags": null,
"type": "Microsoft.DBforMySQL/servers",
"userVisibleState": "Ready",
"version": "5.7"
}
중요 :
고유한 SQL 서버 이름을 입력한다. Azure SQL Server 이름은 UPPER / Camel 대/소문자 명명 규칙을 지원하지 않으므로 DB 서버 이름 필드 값에 소문자를 사용한다.
5. 생성한 리소스 그룹으로 이동한다. Azure Database for MySQL Server가 프로 비전 된 것을 볼 수 있다. 데이터베이스 서버를 선택한다.
6. Properties를 선택한다. Server name 및 Server admin login name을 메모장에 저장한다.
이 예에서 서버 이름은 zerosqldbserver.mysql.database.azure.com이고 관리자 사용자 이름은 mysqldbuser@zerosqldbserver이다.
7. Connection security을 선택한다. Allow access to Azure services을 토글하고 변경 사항을 Save 한다. 이는 MySQL 서버의 모든 데이터베이스에 대한 Azure 서비스에 대한 액세스를 제공한다.
실습 2: 웹앱의 App 설정 업데이트 하기
다음으로 생성 한 웹앱으로 이동한다. Java 애플리케이션을 배포 할 때 웹 앱의 웹 컨테이너를 Apache Tomcat으로 변경해야 한다.
1. Configuration을 선택한다. 아래 이미지와 같이 Stack settings을 설정하고 Save를 클릭한다.
(이미 az webapp create 명령 수행 시 옵션으로 전달되어 설정이 불필요하다.)
2. Overview를 선택하고 Browse를 클릭한다.
웹 페이지는 아래 이미지와 같을 것이다.
다음으로 웹앱이 데이터베이스에 올바르게 연결되도록 connection strings을 업데이트해야 한다. 이렇게 할 수 있는 방법은 여러 가지가 있지만, 이 랩의 목적을 위해 Azure 포털에서 직접 업데이트함으로써 간단한 접근법을 취할 것이다.
3. Azure Portal에서 프로비저닝 한 웹앱을 선택한다. Configuration | Application settings | Connection strings을 클릭하고 + New connection string을 클릭한다.
4. Add/Edit connection string 창에서 이름으로 MyShuttleDb를 사용하여 새 MySQL 연결 문자열을 추가하고 값으로 다음 문자열을 붙여넣고 MySQL Server Name, your user name 및 your password를 적절한 값으로 바꾼다. Update를 클릭한다.
|
- MySQL 서버 이름 : 이전에 MySQL 서버 속성에서 복사 한 값
- your user name : 이전에 MySQL 서버 속성에서 복사 한 값
- your password : MySQL 데이터베이스 서버를 만드는 동안 제공한 값
5. 저장을 클릭하여 연결 문자열을 Save 한다.
참고:
여기에 구성된 연결 문자열은 Java 앱 (PHP, Python 및 Node 앱용)에 대한 연결 유형 접두사가 붙은 환경 변수로 사용할 수 있다. src/main/java/com/microsoft/example 폴더 아래의 DataAccess.java 파일에서 다음 코드를 사용하여 연결 문자열을 검색한다.
String conStr = System.getenv("MYSQLCONNSTR_MyShuttleDb");
이제 MyShuttle 애플리케이션을 배포하고 실행하는 데 필요한 모든 리소스를 설정하고 구성했다.
실습 3: 웹앱에 변경사항 배포하기
빌드가 완료되면 CD 파이프라인을 구성한다. Pipelines 섹션의 Releases로 이동하여 릴리즈 정의를 확인한다. 이 릴리즈는 Azure CLI를 사용하여 Azure 웹 앱을 프로비저닝하고 zip 파일을 관련 빌드에서 생성된 웹 앱에 배포한다.
1. Pipelines 탭의 Pipelines을 선택한다. MyShuttleBuild 빌드를 선택하고 파이프 라인 편집을 클릭하여 빌드 정의를 본다.
랩은 표준 Maven 빌드 템플릿을 사용하여 코드를 컴파일하고 배포를 위해 결과 아티팩트를 복사 및 게시한다. 여기에 복사되는 추가 파일은 MySQL 데이터베이스를 만들고 배포 중에 몇 개의 레코드를 삽입하는 CreateMYSQLDB.sql 파일이다.
2. Queue를 클릭하여 빌드를 트리거하고 빌드가 완료 될 때까지 기다린다.
3. 빌드가 성공하면 Pipelines에서 Releases를 선택한다.
4. MyShuttle Release를 선택하고 Edit을 클릭하여 릴리즈 정의를 연다.
5. 아티팩트가 아래와 같이 Build 아티팩트를 가리키는지 확인한다. Jenkins 핸즈온 랩에서 이 랩을 수행하는 경우 아티팩트가 Jenkins를 가리키는지 확인한다.
6. Tasks를 클릭한다. Execute Azure MySQL : SqlTaskFile 태스크를 선택하고 다음 세부 정보를 제공한다.
- Azure 구독 정보 : 적절한 구독을 선택한다. Authorize를 클릭하고 팝업 창에서 Azure 구독에 로그인 한다.
- 호스트 이름 : 생성 된 MySQL Database server 호스트 이름을 선택한다.
- 서버 관리자 로그인 : 이전에 기록해 둔 Server admin login name을 제공한다.
- 암호 : Azure Portal에서 MySQL 서버를 만드는 동안 만든 암호를 제공한다.
7. Deploy Azure App Service 태스크를 선택하고 Azure subscription 세부 정보를 선택한 다음 드롭 다운에서 App Service name을 선택한다.
참고:
우리는 Azure App Service 배포 태스크를 사용하고 있다. 이 작업은 Azure 앱 서비스를 업데이트하여 웹 앱과 WebJobs를 Azure에 배포하는 데 사용된다. 이 태스크는 윈도우즈, 리눅스 또는 Mac을 실행하는 교차 플랫폼 에이전트에서 작동하며 Web Deploy 및 Kudu의 기본 배포 기술을 사용한다. 그 일은 ASP에 효과가 있다.네트, ASP.NET Core 1 및 Node.js 기반 웹 애플리케이션. 이 태스크는 Azure Resource Manager API에서만 작동한다는 점에 유의한다.
(원문에는 다음이 누락 되었다. Run on agent를 선택하여 Agent pool과 Agent Specification을 다음과 같이 선택하고 Save를 클릭한다.)
8. Save를 클릭한 다음 +Release | Create Release를 클릭하여 새 릴리즈를 시작한다.
9. 릴리즈가 완료 될 때까지 기다린다. 그런 다음 웹앱으로 이동하고 overview 블레이드에서 URL을 선택합니다. /myshuttledev 컨텍스트를 URL에 추가한다.
예를 들어,
https://zerobigwebapp.azurewebsites.net/myshuttledev/login
10. 로그인을 선택하고 다음 자격 증명 중 하나로 사이트에 로그인 해본다.
Username | Password |
fred | fredpassword |
barney | barneypassword |
11. 데이터베이스가 올바르게 설정되었고 연결 매개 변수가 유효한 경우 포털에 로그인 할 수 있어야 한다.
경고 :
The specified CGI application encountered an error and the server terminated the process 메시지와 함께 에러가 발생한다면 앱 설정 변수 및 값 (데이터베이스 연결 용)을 올바르게 입력했는지 확인한다.