😀
Terraform で Azure App Service と MySQL を作成してアプリのデプロイまでやってみた
Azure CLI で環境構築するのに慣れていても、何十回も作ったり消したりしていると、もっと簡単にできないかと考えたりします。Azure CLI を Bash スクリプト化しておけば良いのですが、今回は Terraform でやってみます。構築する Azure App Service と Azure Database for MySQL のフレキシブルサーバーは、VNET 統合した構成で用意し、ローカルにある PHP のソース(今回は WordPress を想定)を ZIP デプロイするところまでを Terraform で実行します。これでちょっとした設定変更も Terraform で簡単にできるよになりました。
Terraform コード
main.tf
provider "azurerm" {
features {}
}
variable "prefix" {
type = string
default = "mnrwptfz"
}
variable "region" {
type = string
default = "eastus"
}
resource "azurerm_resource_group" "rg" {
name = "${var.prefix}-rg"
location = var.region
}
resource "azurerm_virtual_network" "vnet" {
name = "${var.prefix}-vnet"
address_space = ["10.0.0.0/24"]
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
}
resource "azurerm_subnet" "app-subnet" {
name = "app-subnet"
resource_group_name = azurerm_resource_group.rg.name
virtual_network_name = azurerm_virtual_network.vnet.name
address_prefixes = ["10.0.0.0/26"]
delegation {
name = "delegation"
service_delegation {
name = "Microsoft.Web/serverFarms"
actions = [
"Microsoft.Network/virtualNetworks/subnets/action",
]
}
}
}
resource "azurerm_subnet" "db-subnet" {
name = "db-subnet"
resource_group_name = azurerm_resource_group.rg.name
virtual_network_name = azurerm_virtual_network.vnet.name
address_prefixes = ["10.0.0.64/26"]
delegation {
name = "delegation"
service_delegation {
name = "Microsoft.DBforMySQL/flexibleServers"
actions = [
"Microsoft.Network/virtualNetworks/subnets/join/action",
]
}
}
}
resource "azurerm_network_security_group" "nsg" {
name = "${var.prefix}-nsg"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
}
resource "azurerm_subnet_network_security_group_association" "app-subnet" {
subnet_id = azurerm_subnet.app-subnet.id
network_security_group_id = azurerm_network_security_group.nsg.id
}
resource "azurerm_subnet_network_security_group_association" "db-subnet" {
subnet_id = azurerm_subnet.db-subnet.id
network_security_group_id = azurerm_network_security_group.nsg.id
}
resource "azurerm_private_dns_zone" "mysql" {
name = "${var.prefix}.private.mysql.database.azure.com"
resource_group_name = azurerm_resource_group.rg.name
}
resource "azurerm_private_dns_zone_virtual_network_link" "mysql" {
name = "mysql"
private_dns_zone_name = azurerm_private_dns_zone.mysql.name
virtual_network_id = azurerm_virtual_network.vnet.id
resource_group_name = azurerm_resource_group.rg.name
registration_enabled = true
depends_on = [azurerm_subnet.db-subnet]
}
resource "azurerm_mysql_flexible_server" "mysql" {
name = "${var.prefix}-mysql"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
administrator_login = "admin"
administrator_password = "DummyP@ss1234"
backup_retention_days = 7
delegated_subnet_id = azurerm_subnet.db-subnet.id
private_dns_zone_id = azurerm_private_dns_zone.mysql.id
sku_name = "B_Standard_B1s"
version = "5.7"
depends_on = [azurerm_private_dns_zone_virtual_network_link.mysql]
lifecycle {
ignore_changes = [zone]
}
}
resource "azurerm_mysql_flexible_database" "mysql" {
name = "wpdb"
resource_group_name = azurerm_resource_group.rg.name
server_name = azurerm_mysql_flexible_server.mysql.name
charset = "utf8mb4"
collation = "utf8mb4_general_ci"
}
resource "azurerm_mysql_flexible_server_configuration" "require_secure_transport" {
name = "require_secure_transport"
value = "off"
resource_group_name = azurerm_resource_group.rg.name
server_name = azurerm_mysql_flexible_server.mysql.name
}
resource "azurerm_service_plan" "plan" {
name = "${var.prefix}-plan"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
os_type = "Linux"
sku_name = "B1"
}
resource "azurerm_linux_web_app" "app" {
name = "${var.prefix}-app"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
service_plan_id = azurerm_service_plan.plan.id
https_only = false
virtual_network_subnet_id = azurerm_subnet.app-subnet.id
zip_deploy_file = data.archive_file.source.output_path
site_config {
always_on = true
ftps_state = "Disabled"
application_stack {
php_version = "8.0"
}
}
app_settings = {
SCM_DO_BUILD_DURING_DEPLOYMENT = true
}
}
data "archive_file" "source" {
type = "zip"
source_dir = "source"
output_path = "archive/source-0.0.1.zip"
}
参考
Azure App Service で WordPress を動かすための wp-config.php サンプル。
下記のコードを wp-config-sample.php に追加して、source
内に用意しておけば、初期設定ウィザードで DB や WordPress アドミンユーザーを設定する事が可能になりました。
wp-config-sample.php
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')
$_SERVER['HTTPS'] = 'on';
$http_protocol='http://';
if (!preg_match("/^localhost(:[0-9])*/", $_SERVER['HTTP_HOST']) && !preg_match("/^127\.0\.0\.1(:[0-9])*/", $_SERVER['HTTP_HOST'])) {
$http_protocol='https://';
}
//Relative URLs for swapping across app service deployment slots
define('WP_HOME', $http_protocol . $_SERVER['HTTP_HOST']);
define('WP_SITEURL', $http_protocol . $_SERVER['HTTP_HOST']);
define('WP_CONTENT_URL', '/wp-content');
define('DOMAIN_CURRENT_SITE', $_SERVER['HTTP_HOST']);
私の場合は検証環境なので、自動バージョンアップしないように、下記のコードも追加しておきました。
define('AUTOMATIC_UPDATER_DISABLED', true);
Discussion