0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

laravel+mysqlをazureでやりたい

0
Last updated at Posted at 2026-11-01

laravel+mysqlをazureでやりたい

composer require laravel/octane

laravelのconfig/database.phpを修正する必要がある。

config/database.php
<?php

use Illuminate\Support\Str;
use Pdo\Mysql;

return [

    /*
    |--------------------------------------------------------------------------
    | Default Database Connection Name
    |--------------------------------------------------------------------------
    */

    'default' => env('DB_CONNECTION', 'sqlite'),

    /*
    |--------------------------------------------------------------------------
    | Database Connections
    |--------------------------------------------------------------------------
    */

    'connections' => [

        /*
        |--------------------------------------------------------------------------
        | SQLite
        |--------------------------------------------------------------------------
        */

        'sqlite' => [
            'driver' => 'sqlite',
            'url' => env('DB_URL'),
            'database' => env(
                'DB_DATABASE',
                database_path('database.sqlite')
            ),
            'prefix' => '',
            'foreign_key_constraints' => env(
                'DB_FOREIGN_KEYS',
                true
            ),
            'busy_timeout' => null,
            'journal_mode' => null,
            'synchronous' => null,
            'transaction_mode' => 'DEFERRED',
        ],

        /*
        |--------------------------------------------------------------------------
        | MySQL
        |--------------------------------------------------------------------------
        |
        | Local:
        |   MYSQL_ATTR_SSL_CA=
        |
        | Azure:
        |   MYSQL_ATTR_SSL_CA=/usr/local/share/ca-certificates/azure/DigiCertGlobalRootG2.crt.pem
        |
        | AWS:
        |   MYSQL_ATTR_SSL_CA=/path/to/rds-combined-ca-bundle.pem
        |
        */

        'mysql' => [
            'driver' => 'mysql',

            'url' => env('DB_URL'),

            'host' => env('DB_HOST', '127.0.0.1'),
            'port' => env('DB_PORT', '3306'),

            'database' => env('DB_DATABASE', 'laravel'),

            'username' => env('DB_USERNAME', 'root'),
            'password' => env('DB_PASSWORD', ''),

            'unix_socket' => env('DB_SOCKET', ''),

            'charset' => env('DB_CHARSET', 'utf8mb4'),
            'collation' => env(
                'DB_COLLATION',
                'utf8mb4_unicode_ci'
            ),

            'prefix' => '',
            'prefix_indexes' => true,

            'strict' => true,
            'engine' => null,

            /*
            |--------------------------------------------------------------------------
            | SSL / TLS
            |--------------------------------------------------------------------------
            |
            | MYSQL_ATTR_SSL_CA が空の場合は、SSL CAオプションを
            | 設定しません。
            |
            | これにより、ローカルMySQLではSSLを強制しません。
            |
            | Azure / AWSでは環境変数からCAファイルを指定できます。
            |
            */

            'options' => extension_loaded('pdo_mysql')
                ? array_filter([
                    (
                        PHP_VERSION_ID >= 80500
                            ? Mysql::ATTR_SSL_CA
                            : PDO::MYSQL_ATTR_SSL_CA
                    ) => env('MYSQL_ATTR_SSL_CA'),
                ])
                : [],
        ],

        /*
        |--------------------------------------------------------------------------
        | MariaDB
        |--------------------------------------------------------------------------
        */

        'mariadb' => [
            'driver' => 'mariadb',

            'url' => env('DB_URL'),

            'host' => env('DB_HOST', '127.0.0.1'),
            'port' => env('DB_PORT', '3306'),

            'database' => env('DB_DATABASE', 'laravel'),

            'username' => env('DB_USERNAME', 'root'),
            'password' => env('DB_PASSWORD', ''),

            'unix_socket' => env('DB_SOCKET', ''),

            'charset' => env('DB_CHARSET', 'utf8mb4'),
            'collation' => env(
                'DB_COLLATION',
                'utf8mb4_unicode_ci'
            ),

            'prefix' => '',
            'prefix_indexes' => true,

            'strict' => true,
            'engine' => null,

            'options' => extension_loaded('pdo_mysql')
                ? array_filter([
                    (
                        PHP_VERSION_ID >= 80500
                            ? Mysql::ATTR_SSL_CA
                            : PDO::MYSQL_ATTR_SSL_CA
                    ) => env('MYSQL_ATTR_SSL_CA'),
                ])
                : [],
        ],

        /*
        |--------------------------------------------------------------------------
        | PostgreSQL
        |--------------------------------------------------------------------------
        */

        'pgsql' => [
            'driver' => 'pgsql',

            'url' => env('DB_URL'),

            'host' => env('DB_HOST', '127.0.0.1'),
            'port' => env('DB_PORT', '5432'),

            'database' => env('DB_DATABASE', 'laravel'),

            'username' => env('DB_USERNAME', 'root'),
            'password' => env('DB_PASSWORD', ''),

            'charset' => env('DB_CHARSET', 'utf8'),

            'prefix' => '',
            'prefix_indexes' => true,

            'search_path' => 'public',

            'sslmode' => env(
                'DB_SSLMODE',
                'prefer'
            ),
        ],

        /*
        |--------------------------------------------------------------------------
        | SQL Server
        |--------------------------------------------------------------------------
        */

        'sqlsrv' => [
            'driver' => 'sqlsrv',

            'url' => env('DB_URL'),

            'host' => env('DB_HOST', 'localhost'),
            'port' => env('DB_PORT', '1433'),

            'database' => env('DB_DATABASE', 'laravel'),

            'username' => env('DB_USERNAME', 'root'),
            'password' => env('DB_PASSWORD', ''),

            'charset' => env('DB_CHARSET', 'utf8'),

            'prefix' => '',
            'prefix_indexes' => true,

            // 'encrypt' => env('DB_ENCRYPT', 'yes'),
            // 'trust_server_certificate' => env(
            //     'DB_TRUST_SERVER_CERTIFICATE',
            //     'false'
            // ),
        ],
    ],

    /*
    |--------------------------------------------------------------------------
    | Migration Repository Table
    |--------------------------------------------------------------------------
    */

    'migrations' => [
        'table' => 'migrations',
        'update_date_on_publish' => true,
    ],

    /*
    |--------------------------------------------------------------------------
    | Redis Databases
    |--------------------------------------------------------------------------
    */

    'redis' => [

        'client' => env(
            'REDIS_CLIENT',
            'phpredis'
        ),

        'options' => [
            'cluster' => env(
                'REDIS_CLUSTER',
                'redis'
            ),

            'prefix' => env(
                'REDIS_PREFIX',
                Str::slug(
                    (string) env(
                        'APP_NAME',
                        'laravel'
                    )
                ) . '-database-'
            ),

            'persistent' => env(
                'REDIS_PERSISTENT',
                false
            ),
        ],

        /*
        |--------------------------------------------------------------------------
        | Default Redis Connection
        |--------------------------------------------------------------------------
        */

        'default' => [
            'url' => env('REDIS_URL'),

            'host' => env(
                'REDIS_HOST',
                '127.0.0.1'
            ),

            'username' => env(
                'REDIS_USERNAME'
            ),

            'password' => env(
                'REDIS_PASSWORD'
            ),

            'port' => env(
                'REDIS_PORT',
                '6379'
            ),

            'database' => env(
                'REDIS_DB',
                '0'
            ),

            'max_retries' => env(
                'REDIS_MAX_RETRIES',
                3
            ),

            'backoff_algorithm' => env(
                'REDIS_BACKOFF_ALGORITHM',
                'decorrelated_jitter'
            ),

            'backoff_base' => env(
                'REDIS_BACKOFF_BASE',
                100
            ),

            'backoff_cap' => env(
                'REDIS_BACKOFF_CAP',
                1000
            ),
        ],

        /*
        |--------------------------------------------------------------------------
        | Cache Redis Connection
        |--------------------------------------------------------------------------
        */

        'cache' => [
            'url' => env('REDIS_URL'),

            'host' => env(
                'REDIS_HOST',
                '127.0.0.1'
            ),

            'username' => env(
                'REDIS_USERNAME'
            ),

            'password' => env(
                'REDIS_PASSWORD'
            ),

            'port' => env(
                'REDIS_PORT',
                '6379'
            ),

            'database' => env(
                'REDIS_CACHE_DB',
                '1'
            ),

            'max_retries' => env(
                'REDIS_MAX_RETRIES',
                3
            ),

            'backoff_algorithm' => env(
                'REDIS_BACKOFF_ALGORITHM',
                'decorrelated_jitter'
            ),

            'backoff_base' => env(
                'REDIS_BACKOFF_BASE',
                100
            ),

            'backoff_cap' => env(
                'REDIS_BACKOFF_CAP',
                1000
            ),
        ],
    ],
];





main.tf

terraform {
  required_version = ">= 1.3.0"

  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 4.0"
    }

    random = {
      source  = "hashicorp/random"
      version = "~> 3.0"
    }
  }
}

provider "azurerm" {
  features {
    resource_group {
      prevent_deletion_if_contains_resources = false
    }
  }
}

# ============================================================
# 1. Resource Group
# ============================================================
resource "azurerm_resource_group" "rg" {
  name     = "rg-laravel"
  location = "japaneast"
}

# ============================================================
# 2. Log Analytics
# ============================================================
resource "azurerm_log_analytics_workspace" "law" {
  name                = "law-laravel"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name

  sku                 = "PerGB2018"
  retention_in_days = 30
}

# ============================================================
# 3. Azure Container Registry
# ============================================================
resource "azurerm_container_registry" "acr" {
  name                = "myappacr817263"
  resource_group_name = azurerm_resource_group.rg.name
  location            = azurerm_resource_group.rg.location

  sku           = "Basic"
  admin_enabled = true
}

# ============================================================
# 4. MySQL Password
# ============================================================
resource "random_password" "mysql" {
  length           = 24
  special          = true
  override_special = "!#&*"
}

# ============================================================
# 5. Laravel APP_KEY
# ============================================================
resource "random_id" "app_key" {
  byte_length = 32
}

# ============================================================
# 6. MySQL Flexible Server
# ============================================================
resource "azurerm_mysql_flexible_server" "mysql" {
  name                = "mysql-laravel-app-817263"
  resource_group_name = azurerm_resource_group.rg.name
  location            = azurerm_resource_group.rg.location

  administrator_login    = "laravel_admin"
  administrator_password = random_password.mysql.result

  version  = "8.0.21"
  sku_name = "B_Standard_B1ms"

  storage {
    size_gb = 20
  }

  backup_retention_days = 7
}

# ============================================================
# 7. MySQL Database
# ============================================================
resource "azurerm_mysql_flexible_database" "db" {
  name                = "laravel_production"
  resource_group_name = azurerm_resource_group.rg.name
  server_name         = azurerm_mysql_flexible_server.mysql.name

  charset   = "utf8mb4"
  collation = "utf8mb4_unicode_ci"
}

# ============================================================
# 8. MySQL Firewall
# ============================================================
resource "azurerm_mysql_flexible_server_firewall_rule" "allow_all" {
  name                = "allow-container-apps"
  resource_group_name = azurerm_resource_group.rg.name
  server_name         = azurerm_mysql_flexible_server.mysql.name

  start_ip_address = "0.0.0.0"
  end_ip_address   = "255.255.255.255"
}

# ============================================================
# 9. Container Apps Environment
# ============================================================
resource "azurerm_container_app_environment" "cae" {
  name                = "cae-laravel"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name

  log_analytics_workspace_id = azurerm_log_analytics_workspace.law.id
}

# ============================================================
# 10. Laravel Container App
# ============================================================
resource "azurerm_container_app" "laravel" {
  name                         = "ca-laravel"
  resource_group_name          = azurerm_resource_group.rg.name
  container_app_environment_id = azurerm_container_app_environment.cae.id

  revision_mode = "Single"

  secret {
    name  = "db-password"
    value = random_password.mysql.result
  }

  secret {
    name  = "acr-password"
    value = azurerm_container_registry.acr.admin_password
  }

  secret {
    name  = "app-key"
    value = "base64:${random_id.app_key.b64_std}"
  }

  registry {
    server               = azurerm_container_registry.acr.login_server
    username             = azurerm_container_registry.acr.admin_username
    password_secret_name = "acr-password"
  }

  ingress {
    external_enabled = true
    target_port      = 8000
    transport        = "auto"

    traffic_weight {
      percentage      = 100
      latest_revision = true
    }
  }

  template {
    min_replicas = 1
    max_replicas = 1

    container {
      name  = "laravel-app"
      image = "${azurerm_container_registry.acr.login_server}/myapp-app:latest"

      cpu    = 0.5
      memory = "1Gi"

      env {
        name  = "APP_ENV"
        value = "production"
      }

      env {
        name  = "APP_DEBUG"
        value = "false"
      }

      env {
        name        = "APP_KEY"
        secret_name = "app-key"
      }

      env {
        name  = "DB_CONNECTION"
        value = "mysql"
      }

      env {
        name  = "DB_HOST"
        value = azurerm_mysql_flexible_server.mysql.fqdn
      }

      env {
        name  = "DB_PORT"
        value = "3306"
      }

      env {
        name  = "DB_DATABASE"
        value = azurerm_mysql_flexible_database.db.name
      }

      env {
        name  = "DB_USERNAME"
        value = azurerm_mysql_flexible_server.mysql.administrator_login
      }

      env {
        name        = "DB_PASSWORD"
        secret_name = "db-password"
      }

      # ★ Azure MySQLへのSSL接続用パス(OS標準証明書を指定)
      env {
        name  = "MYSQL_ATTR_SSL_CA"
        value = "/etc/ssl/certs/ca-certificates.crt"
      }

      env {
        name  = "OTEL_SDK_DISABLED"
        value = "true"
      }
    }
  }

  lifecycle {
    ignore_changes = [
      template[0].container[0].image
    ]
  }

  depends_on = [
    azurerm_mysql_flexible_database.db,
    azurerm_mysql_flexible_server_firewall_rule.allow_all
  ]
}

# ============================================================
# 11. Outputs
# ============================================================
output "resource_group_name" {
  value = azurerm_resource_group.rg.name
}

output "acr_login_server" {
  value = azurerm_container_registry.acr.login_server
}

output "mysql_host" {
  value = azurerm_mysql_flexible_server.mysql.fqdn
}

output "container_app_url" {
  value = "https://${azurerm_container_app.laravel.ingress[0].fqdn}"
}

Dockerfile

FROM dunglas/frankenphp:php8.3

RUN apt-get update \
    && apt-get install -y --no-install-recommends \
        ca-certificates \
        curl \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

RUN install-php-extensions \
    pdo_mysql \
    gd \
    pcntl \
    zip \
    bcmath \
    opcache \
    opentelemetry

RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"

RUN { \
    echo 'opcache.enable=1'; \
    echo 'opcache.enable_cli=1'; \
    echo 'opcache.validate_timestamps=0'; \
    echo 'opcache.max_accelerated_files=20000'; \
    echo 'opcache.memory_consumption=256'; \
} > "$PHP_INI_DIR/conf.d/opcache-recommended.ini"

COPY --from=composer:2 /usr/bin/composer /usr/bin/composer

WORKDIR /app

COPY composer.json composer.lock ./

RUN composer install \
    --no-dev \
    --no-interaction \
    --prefer-dist \
    --no-scripts \
    --no-autoloader

COPY . .

# ローカルの .env の混入を防ぐ
RUN rm -f .env

RUN rm -f bootstrap/cache/*.php

RUN composer dump-autoload \
    --optimize \
    --no-dev

RUN mkdir -p \
        storage/framework/cache \
        storage/framework/sessions \
        storage/framework/views \
        storage/logs \
        bootstrap/cache

RUN chown -R www-data:www-data \
        /app/storage \
        /app/bootstrap/cache \
    && chmod -R 775 \
        /app/storage \
        /app/bootstrap/cache

ENV APP_ENV=production \
    APP_DEBUG=false \
    OTEL_SERVICE_NAME=myapp \
    OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf

EXPOSE 8000

# 起動時にキャッシュクリア、マイグレーション自動実行、Octane起動を行う
CMD php artisan config:cache && \
    php artisan event:cache && \
    php artisan migrate --force && \
    php artisan octane:start --server=frankenphp --host=0.0.0.0 --port=8000 --workers=auto --max-requests=500
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?