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?

More than 5 years have passed since last update.

PHP Slim 環境構築(12) 前回構築した環境をEC2上に

Posted at

PHP Slim 環境構築(12) 前回構築した環境をEC2上に

Introduction

前回は、DockerコンテナにNginxとPHP-FPMの両方を格納した構成をローカル環境に構築しました。
今回は、それをEC2上に構築します。

この一連のシリーズは、自分への備忘録が第一目的のため、相当不親切です。
すみません・・・

変更点

今回構築した環境では、ローカルPC上に構築したものをlocal環境、EC2上に構築したものをdevelopment環境と呼ぶことにしています。
今回は、前回作成したlocal環境をdevelopment環境にも適用するとともに、ソースを少し整理しました。

ソースツリー

今回の変更箇所です。

$(PROJECTROOT)
  /aws
    ec2-userdata.txt                       (新規)
  /compose
    /web_front
      development.conf
    /web_hoge
      Dockerfile
      settings.php                         (削除)
      settings-development.yml             (新規)
      settings-local.yml                   (新規)
  /src
    /hoge
      /lib
        /Controller
          DynamodbController.php
          StorageController.php
        MyContainerBuilder.php              (新規)
      /public
        index.php
      /test
        RequestTest.php
      composer.json
      composer.lock

/aws/ec2-userdata.txt

EC2のユーザーデータをリポジトリに追加しました。

/aws/ec2-userdata.txt
#!/bin/bash
cat <<'SYS_EOF' >> /etc/sysctl.conf
net.core.somaxconn=65535
SYS_EOF

sysctl -p /etc/sysctl.conf

cat > /etc/security/limits.d/20-filelimits.conf <<'FLIMIT_EOF'
*    soft    nofile    32768
*    hard    nofile    32768
FLIMIT_EOF
ulimit -n 32768

amazon-linux-extras install docker -y
systemctl enable docker
usermod -a -G docker ec2-user
service docker start

curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-Linux-x86_64" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose

yum install -yq git

cd /home/ec2-user
git clone https://github.com/dynamitecoolguy/slimtemplate.git
cd slimtemplate
git checkout chapter12
chown -R ec2-user:ec2-user .

cd compose
docker-compose -f docker-compose-common.yml -f docker-compose-development.yml up -d

/compose/web_front/development.conf

前回変更したlocal.confと同様に、nginxは単なるreverse proxyになります。

/compose/web_front/development.conf
ssl_certificate /etc/certs/server.crt;
ssl_certificate_key /etc/certs/server.key;

ssl_prefer_server_ciphers on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

server {
  listen 3128 default_server;
  listen 8443 ssl default_server;
  server_name _;
  access_log /dev/stdout;
  error_log /dev/stderr;

  proxy_set_header Host            $host;
  proxy_set_header X-Real-IP       $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

  location / {
    proxy_pass http://web_hoge:3128/;
  }
}

/compose/web_hoge/Dockerfile

環境用設定ファイルをPHP直書きから、ymlに変更しました。
また、各環境用の設定ファイルを用意することにしました。

/compose/web_hoge/Dockerfilee
...(略)...
# COPY settings.php /var/www/settings.php
COPY settings-${environment}.yml /var/www/settings.yml
...(略)...

/compose/web_hoge/settings-development.yml, settings-local.yml

以前までのsettings.phpをymlに変更しました。また、ソースに直書きしていたキーなどもこのファイルに抜き出しました。
なお、settings-development.ymlとsettings-local.ymlの内容は同じです。

/compose/web_hoge/settings-development.yml
userdb:
  host: mysql
  dbname: userdb
  user: scott
  password: tiger

logdb:
  host: postgresql
  dbname: logdb
  user: root
  password: hogehoge

redis:
  host: redis

dynamodb:
  endpoint: http://dynamodb:8000
  region: ap-northeast-1
  key: dummy-key
  secret: dummy-secret
  table: hogehoge

storage:
  endpoint: http://storage:9000
  region: ap-northeast-1
  key: minio
  secret: miniminio
  bucket: dummy

/src/hoge/lib/Controller/DynamodbController.php, StorageController.php

ソースコードに直接記述していたdynamoDBのテーブル名、S3のバケット名を設定ファイルを参照するようにしました。

/src/hoge/lib/Controller/DynamodbController.php
...()...
$result = $dynamodb->describeTable([
    //'TableName' => 'hogehoge'
    'TableName' => $this->getTable()
]);

...()...
...('hogehoge'を変更した箇所が後3か所)...
...()...

private function getTable(): string
{
    $setting = $this->container->get('settings')['dynamodb'];
    return $setting['table'];
}
...()...
/src/hoge/lib/Controller/StorageController.php
...()...
//$s3->headBucket(['Bucket' => 'dummy']);
$s3->headBucket(['Bucket' => $this->getBucket()]);

...()...
...('dummy'を変更した箇所が後3か所)...
...()...

private function getBucket(): string
{
    $setting = $this->container->get('settings')['storage'];
    return $setting['bucket'];
}
...()...

/src/hoge/lib/MyContainerBuilder.php

設定用ymlファイルを読み込み、必要な定義を組み込み済みのContainerBuilderです。
DI\ContainerBuilderを継承しています。

/src/hoge/lib/MyContainerBuilder.php
<?php

namespace Hoge;

use Aws\Sdk;
use PDO;
use Psr\Container\ContainerInterface;

use DI\Container;
use DI\ContainerBuilder;
use Redis;

class MyContainerBuilder extends ContainerBuilder
{
    public function __construct(string $containerClass = Container::class)
    {
        parent::__construct($containerClass);

        $this->addDefaultDefinitions();
    }

    private function addDefaultDefinitions(): void
    {
        $parsed = yaml_parse_file(__DIR__ . '/../../settings.yml');

        $this->addDefinitions(['settings' => $parsed]);
        $this->addDefinitions([
            'userdb' => function (ContainerInterface $container)
            {
                $settings = $container->get('settings')['userdb'];
                $dsn = 'mysql:host=' . $settings['host'] . ';dbname=' . $settings['dbname'];
                $options = [
                    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
                    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
                    PDO::ATTR_EMULATE_PREPARES => false
                ];
                return new PDO($dsn, $settings['user'], $settings['password'], $options);
            },
            'logdb' => function (ContainerInterface $container)
            {
                $settings = $container->get('settings')['logdb'];
                $dsn = 'pgsql:host=' . $settings['host'] . ';dbname=' . $settings['dbname'];
                $options = [
                    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
                    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
                    PDO::ATTR_EMULATE_PREPARES => false
                ];
                return new PDO($dsn, $settings['user'], $settings['password'], $options);
            },
            'redis' => function (ContainerInterface $container)
            {
                $settings = $container->get('settings')['redis'];
                $redis = new Redis();
                $redis->connect($settings['host']);
                $redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_IGBINARY);

                return $redis;
            },
            'dynamodb' => function (ContainerInterface $container)
            {
                $settings = $container->get('settings')['dynamodb'];

                $sdk = new Sdk([
                    'endpoint' => $settings['endpoint'],
                    'region' => $settings['region'],
                    'version' => '2012-08-10',
                    'credentials' => [
                        'key' => $settings['key'],
                        'secret' => $settings['secret']
                    ]
                ]);

                $dynamodb = $sdk->createDynamoDb();
                return $dynamodb;
            },
            'storage' => function (ContainerInterface $container)
            {
                $settings = $container->get('settings')['storage'];
                $sdk = new Sdk([
                    'endpoint' => $settings['endpoint'],
                    'region' => $settings['region'],
                    'version' => '2006-03-01',
                    'credentials' => [
                        'key' => $settings['key'],
                        'secret' => $settings['secret']
                    ],
                    'use_path_style_endpoint' => true
                ]);
                $s3 = $sdk->createS3();
                return $s3;
            }
        ]);
    }
}

/src/hoge/public/index.php

DI部分を上記のMyContainerBuilderに分割したので、必要ない部分を削除しました。

/src/hoge/public/index.php
<?php

use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;
use Slim\Routing\RouteCollectorProxy;

use Hoge\ExampleAfterMiddleware;
use Hoge\ExampleBeforeMiddleware;
use Hoge\MyContainerBuilder;
use Hoge\Controller\PlayerController;
use Hoge\Controller\PlayerCreatedLogController;
use Hoge\Controller\RedisController;
use Hoge\Controller\DynamodbController;
use Hoge\Controller\StorageController;

/** @var Composer\Autoload\ClassLoader $loader */
$loader = require __DIR__ . '/../../vendor/autoload.php';
$loader->addPsr4('Hoge\\', __DIR__ . '/../lib');

$containerBuilder = new MyContainerBuilder();
$container = $containerBuilder->build();

AppFactory::setContainer($container);
$app = AppFactory::create();

// Middleware
$contentLengthMiddleware = new \Slim\Middleware\ContentLengthMiddleware();
$app->add($contentLengthMiddleware);

$app->get('/', function (Request $request, Response $response, array $args) {
    $response->getBody()->write('Hello, World!');
    return $response;
})
    ->add(new ExampleBeforeMiddleware())
    ->add(new ExampleAfterMiddleware());

$app->group('/player', function (RouteCollectorProxy $group) {
    $group->get('/{id}', PlayerController::class . ':get');
    $group->post('', PlayerController::class . ':post');
    $group->put('/{id}', PlayerController::class . ':put');
});

$app->group('/player_created', function (RouteCollectorProxy $group) {
    $group->get('/{id}', PlayerCreatedLogController::class . ':get');
    $group->get('', PlayerCreatedLogController::class . ':list');
});

$app->group('/redis', function (RouteCollectorProxy $group) {
    $group->get('/{key}', RedisController::class . ':get');
    $group->post('', RedisController::class . ':post');
    $group->put('/{key}', RedisController::class . ':put');
    $group->delete('/{key}', RedisController::class . ':delete');
});

$app->group('/dynamodb', function (RouteCollectorProxy $group) {
    $group->get('/{key}', DynamodbController::class . ':get');
    $group->post('', DynamodbController::class . ':post');
});

$app->group('/storage', function (RouteCollectorProxy $group) {
    $group->get('/{filename}', StorageController::class . ':get');
    $group->post('', StorageController::class . ':post');
});

$app->run();

/src/hoge/test/RequestTest.php

テスト用コードも、設定用ymlから情報を取り込むように変更しました。
(ソースコード略)。

/src/hoge/composer.json, compser.lock

yamlの使用に伴い、composer require yamlを行いました。

composer.json
{
    "require": {
        "slim/slim": "4.2.0",
        "slim/psr7": "0.5.0",
        "php-di/php-di": "6.0.9",
        "ext-pdo": "^7.2",
        "ext-json": "^1.6",
        "ext-redis": "^3.1",
        "ext-curl": "*",
        "ext-yaml": "*",
        "aws/aws-sdk-php": "^3.112"
    },
    "require-dev": {
        "phpunit/phpunit": "^8.4"
    }
}

ここまでのソース

こちらでどうぞ。

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?