docker-composeでnginx+php(cakeph4)+MySQLの環境を構築する
構成(雑)
手順
docker-compose.yml
version: "3" services: # web web: # コンテナ名 container_name: web # image image: nginx:alpine # 他のコンテナ起動後に起動するように制御 depends_on: - php - db # ポート開放 ports: - "80:80" # ボリューム volumes: - "./nginx/conf.d:/etc/nginx/conf.d" - "./app:/var/www/html" # app php: # コンテナ名 container_name: php # ビルド build: ./dockers/php # コンテナに入るようにできる tty: true # 他のコンテナが起動後に動くように制御 depends_on: - db # ボリューム volumes: - "./app:/var/www/html" # ポート ports: - 9000:9000 - 4321:4321 # 環境変数 environment: TZ: "Asia/Tokyo" # DB db: # コンテナ名 container_name: mysql # イメージ image: mysql # tty: true # 再起動 restart: always # 環境変数 environment: MYSQL_ROOT_USER: "root" MYSQL_ROOT_PASSWORD: "password" MYSQL_DATABASE: sample MYSQL_USER: hoge MYSQL_PASSWORD: foofoo TZ: "Asia/Tokyo" # ボリューム volumes: - mysql_data:/var/lib/mysql # ポート ports: - 3306:3306 # 名前付きボリュームをdockerホストの管理下で作成 volumes: mysql_data: {}
nginx/conf.d/vhost1.conf
server { listen 80; listen [::]:80; server_name example.com; root /var/www/html/webroot; index index.php; #access_log /var/www/example.com/log/access.log; #error_log /var/www/example.com/log/error.log; location / { try_files $uri $uri/ /index.php?$args; } location ~ \.php$ { try_files $uri =404; include fastcgi_params; fastcgi_pass php:9000; fastcgi_index index.php; fastcgi_intercept_errors on; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; } }
dockers/php/Dockerfile
# PHPイメージ FROM php:7.4.23-fpm-buster # 関連パッケージをインストール RUN apt-get update && \ apt-get install -y vim && \ apt-get install -y unzip && \ apt-get install -y libicu-dev && \ docker-php-ext-install intl && \ docker-php-ext-install pdo_mysql # composerをインストール COPY --from=composer /usr/bin/composer /usr/bin/composer
※phpイメージ用のDockerfileでphpのパッケージインストーラーであるcomposerをインストールしておく
↓
参考
Docker の Nginx + MySQL 環境で CakePHP 4 を動かす / Twin Turbo Computing
CakePHP4 の開発環境をDockerを使って構築する - Qiita
github
AzurよりSendGridを使用してメールを送信する
Azureでのメール送信はSendGridらしい
詳しくは知らないけどSendGridの送信手段を調べてみました。
環境
CentOS7
PHP7
Azure設定
サービスを追加
アプリ名やパスワードを設定
料金プランを設定
アクセス情報を設定
同意確認を行う
作成ボタンを押下
ダッシュボードに作成されたことを確認
Azureの管理画面より「Manage」を押下してSendGridの管理ページへジャンプ
メールを送信して認証チェックを行う
メール送信完了画面
自分のメールクライアントよりメールを受信してボタンを押下
認証後はそのまま管理画面を表示
APIキー作成画面を表示
作成ボタンを押下して作成画面を表示
APIキー名と権限を設定
キーの値をクリックしてコピーする
Azureの設定画面で資格情報を取得
※パスワードは設定したもの、ユーザ名はこれを使用することでメール送信のパラメータとなります。
送信用設定
yum
udo rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm sudo rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm sudo yum install --enablerepo=remi,remi-php70 php php-devel php-mbstring php-pdo php-gd php-xml php-intl
composer
mkdir -p sample1 cd sample1 php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" php -r "if (hash_file('SHA384', 'composer-setup.php') === '669656bab3166a7aff8a7506b8cb2d1c292f042046c5a994c43155c0be6190fa0355160742ab2e1c88d40d5be660b410') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" php composer-setup.php php -r "unlink('composer-setup.php');" php composer.phar require swiftmailer/swiftmailer
composer.json
{ "require": { "swiftmailer/swiftmailer": "5.3.0" } }
実装
sendmail1.php
<?php include_once "vendor/autoload.php"; // 本文 $text = "Hi!\nHow are you?\n"; // 送信元 $from = array( '送信元メールアドレス' => 'sample_from' ); // 送信先 $to = array( '送信先メールアドレス' => 'sample_to', ); // タイトル $subject = 'Example PHP Email'; // ユーザ情報 $username = '資格情報のユーザ名'; $password = '資格情報のパスワード'; // 送信設定 $transport = Swift_SmtpTransport::newInstance('smtp.sendgrid.net', 587); $transport->setUsername($username); $transport->setPassword($password); $swift = Swift_Mailer::newInstance($transport); // メッセージ生成 $message = new Swift_Message($subject); // 送信情報設定 $message->setFrom($from); $message->setBody($text, 'text/plain'); $message->setTo($to); // 送信処理 if ($recipients = $swift->send($message, $failures)) { echo "送信成功"; } else { echo "送信失敗"; }
sendmail2.php
<?php // 接続情報 $url = 'https://api.sendgrid.com/'; $user = '資格情報より取得したユーザ名'; $pass = '資格情報より取得したパスワード'; // 送信情報 $params = array( 'api_user' => $user, 'api_key' => $pass, 'to' => '送信先のメールアドレス', 'subject' => 'testing from curl', 'text' => 'testing body', 'from' => '送信元のメールアドレス', ); // リクエスト先設定 $request = $url.'api/mail.send.json'; // curl初期化 $session = curl_init($request); // curl設定(POST送信) curl_setopt ($session, CURLOPT_POST, true); // curl設定(パラメータ設定) curl_setopt ($session, CURLOPT_POSTFIELDS, $params); // curl設定(ヘッダー不要、レスポンス必要?) curl_setopt($session, CURLOPT_HEADER, false); curl_setopt($session, CURLOPT_RETURNTRANSFER, true); // 送信して終了 $response = curl_exec($session); curl_close($session); // 処理結果 print_r ($response);
※WEB APIを使用してメール送信するサンプルでもユーザとパスワードは資格情報のものを使用します。
所感
参考にしたドキュメントの通りにやることでなんとかできた。
最近は日本語のドキュメントが豊富なので環境を用意するのも簡単で助かります。
一部英語でわからないこともあるけど
まあなんとかなるかな…
Azure Strage File ApiをPHPでBLOBを取得
仕事がやっと
落ち着いた感じがする。
特別忙しいというわけではないがタイミングなどの問題もあってブログを書くことを忘れてしまっているのはマズイ
忘れていることもあるので勉強を再開してみる。
Azure Strage File
簡単にいうとAWSのS3と思う、厳密には違うと思うけど一部のデータを保存したり取得したりするのでそのレベルの認識で覚えておく
今回は設定して登録したデータをphpで取得することを行う。
Azureの設定
ストレージアカウントを選択する
追加ボタンを押下
アカウント名と他の設定を行い、作成ボタンを押下
作成されたことを確認し、選択する
コンテナを追加する
コンテナ名を設定してOKを押下
アクセスキーをコピーする
準備
php
sudo rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm sudo rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm sudo yum install --enablerepo=remi,remi-php70 php php-devel php-mbstring php-pdo php-gd php-xml
compoer
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" php -r "if (hash_file('SHA384', 'composer-setup.php') === '669656bab3166a7aff8a7506b8cb2d1c292f042046c5a994c43155c0be6190fa0355160742ab2e1c88d40d5be660b410') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" php composer-setup.php php -r "unlink('composer-setup.php');"
compoer.json
{ "require": { "microsoft/windowsazure": "^0.4" } }
設定情報
setting.php
<?php $connectionString = "DefaultEndpointsProtocol=https;AccountName=mshige1979sample1;AccountKey=事前にコピーしたアクセスキー";
ファイルを追加
sample_add.php
<?php require_once 'vendor/autoload.php'; require_once 'setting.php'; use WindowsAzure\Common\ServicesBuilder; use MicrosoftAzure\Storage\Common\ServiceException; // 接続文字列を使用して、Blobサービスのインスタンスを作成する $blobRestProxy = ServicesBuilder::getInstance()->createBlobService($connectionString); // 取得処理 try { // ファイル名 $date = "testdata_" . date("YmdHis") . ".txt"; echo $date . "\n"; // データの中身 $data = md5(uniqid());; echo $data . "\n"; // 追加処理 $blobRestProxy->createBlockBlob("test01", $date, $data); } catch(ServiceException $e) { // 例外処理 $code = $e->getCode(); $error_message = $e->getMessage(); echo $code.": ".$error_message."\n"; }
↓
$ php sample_add.php testdata_20170716233116.txt 08a8e1964d2c0dadc558bd4f54b3de5a $ php sample_add.php testdata_20170716233127.txt 6ff9937a10cbc58bee43367299f49a80 $
一覧取得
sample1.php
<?php require_once 'vendor/autoload.php'; require_once 'setting.php'; use WindowsAzure\Common\ServicesBuilder; use MicrosoftAzure\Storage\Common\ServiceException; // 接続文字列を使用して、Blobサービスのインスタンスを作成する $blobRestProxy = ServicesBuilder::getInstance()->createBlobService($connectionString); // 取得処理 try { // コンテナのオブジェクトを取得 $blob_list = $blobRestProxy->listBlobs("test01"); $blobs = $blob_list->getBlobs(); // 一覧を出力 foreach ($blobs as $blob) { echo $blob->getName().": ".$blob->getUrl()."\n"; } } catch(ServiceException $e) { // 例外処理 $code = $e->getCode(); $error_message = $e->getMessage(); echo $code.": ".$error_message."\n"; }
↓
$ php sample_list.php testdata_20170716233116.txt: https://mshige1979sample1.blob.core.windows.net/test01/testdata_20170716233116.txt testdata_20170716233127.txt: https://mshige1979sample1.blob.core.windows.net/test01/testdata_20170716233127.txt $
読込処理
sample_get.php
<?php require_once 'vendor/autoload.php'; require_once 'setting.php'; use WindowsAzure\Common\ServicesBuilder; use MicrosoftAzure\Storage\Common\ServiceException; // 接続文字列を使用して、Blobサービスのインスタンスを作成する $blobRestProxy = ServicesBuilder::getInstance()->createBlobService($connectionString); // 取得処理 try { // ファイル名 $date = "testdata_20170716233116.txt"; // 取得処理 $blob = $blobRestProxy->getBlob("test01", $date); echo stream_get_contents($blob->getContentStream()) . "\n"; } catch(ServiceException $e) { // 例外処理 $code = $e->getCode(); $error_message = $e->getMessage(); echo $code.": ".$error_message."\n"; }
↓
$ php sample_get.php 08a8e1964d2c0dadc558bd4f54b3de5a $
参考
CentOS6/CentOS7にPHP5.6/PHP7をyumでインストール - Qiita
Composer
15分で出来るPHPからAzure BLOBストレージを使用する方法 | ナレコムazureレシピ
Azure Storageへのアクセス方法 【Shared Access Signatures (SAS)】 - Qiita
まとめ
AWSとAzureはそれぞれ勝手が違う。
このレベルのことは基本として理解しておきたい、やっていないからわかりませんということは仕方がないにしても
ITに携わるものとして新しい技術に触れ続けていくことは重要と思うので…
IBM BluemixでCloud Foundry アプリケーションのアプリを作成する
イメージはHeroku
と同じである程度の環境を持っているものと考えています。
デプロイ
CFツールによるデプロイこれとは別にもう一つデプロイする方法がある
ログイン
$ cf login API エンドポイント: https://api.au-syd.bluemix.net Email> hogehoge Password> 認証中です... OK 組織 hogehogeをターゲットにしました スペース dev をターゲットにしました API エンドポイント: https://api.au-syd.bluemix.net (API バージョン: 2.54.0) ユーザー: hogehoge 組織: hogehoge スペース: dev $
プッシュ
$ cf push sample-php01 $
所感
アプリサーバになんか特殊なことが必要でないのであれば手堅く終わらせる必要がある。
この方法で有償になる感じですけど短期間なら問題なさそうに見える。
SSLの制限があるか確認する必要がる。
php5.6にvldをインストールして試す
これ
PHPはどのように動くのか ~PHPコアから読み解く仕組みと定石
- 作者: 蒋池東龍
- 出版社/メーカー: 技術評論社
- 発売日: 2015/09/17
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (1件) を見る
インストール
phpのためのリポジトリ
sudo rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-6.noarch.rpm sudo rpm -Uvh https://mirror.webtatic.com/yum/el6/latest.rpm
phpインストール
sudo yum install \ php56w php56w-bcmath php56w-cli php56w-common \ php56w-dba php56w-devel php56w-embedded php56w-enchant \ php56w-fpm php56w-gd php56w-imap php56w-interbase php56w-intl \ php56w-ldap php56w-mbstring php56w-mcrypt php56w-mssql php56w-mysqlnd \ php56w-odbc php56w-opcache php56w-pdo php56w-pear php56w-pecl-apcu \ php56w-pecl-gearman php56w-pecl-geoip php56w-pecl-imagick php56w-pecl-memcache \ php56w-pecl-xdebug php56w-pgsql php56w-phpdbg php56w-process \ php56w-pspell php56w-recode php56w-snmp php56w-soap php56w-tidy \ php56w-xml php56w-xmlrpc
vldインストール
sudo pecl install channel://pecl.php.net/vld-0.13.0
↓
Build process completed successfully Installing '/usr/lib64/php/modules/vld.so' install ok: channel://pecl.php.net/vld-0.13.0 configuration option "php_ini" is not set to php.ini location You should add "extension=vld.so" to php.ini
php.iniにモジュールを追加
sudo vi /etc/php.ini ---- ; vld extension=vld.so ----
実行1
sample1.php
<?php echo "hello, world";
sample1を実行
$ php -d vld.active=1 -d vld.execute=0 sample1.php Finding entry points Branch analysis from position: 0 Jump found. Position 1 = -2 filename: /home/vagrant/sample1.php function name: (null) number of ops: 3 compiled vars: none line #* E I O op fetch ext return operands ------------------------------------------------------------------------------------- 2 0 E > EXT_STMT 1 ECHO 'hello%2C+world' 4 2 > RETURN 1 branch: # 0; line: 2- 4; sop: 0; eop: 2; out1: -2 path #1: 0, $
実行2
sample2.php
<?php $aaa = 10; echo $aaa; $aaa .= "ccc"; print $aaa; $bbb = [111, 222, 333]; echo $bbb[0]; echo $bbb[1]; echo $bbb[2];
sample2を実行
$ php -d vld.active=1 -d vld.execute=0 sample2.php Finding entry points Branch analysis from position: 0 Jump found. Position 1 = -2 filename: /home/vagrant/sample2.php function name: (null) number of ops: 24 compiled vars: !0 = $aaa, !1 = $bbb line #* E I O op fetch ext return operands ------------------------------------------------------------------------------------- 2 0 E > EXT_STMT 1 ASSIGN !0, 10 3 2 EXT_STMT 3 ECHO !0 5 4 EXT_STMT 5 ASSIGN_CONCAT 0 !0, 'ccc' 6 6 EXT_STMT 7 PRINT ~2 !0 8 FREE ~2 8 9 EXT_STMT 10 INIT_ARRAY ~3 111 11 ADD_ARRAY_ELEMENT ~3 222 12 ADD_ARRAY_ELEMENT ~3 333 13 ASSIGN !1, ~3 9 14 EXT_STMT 15 FETCH_DIM_R $5 !1, 0 16 ECHO $5 10 17 EXT_STMT 18 FETCH_DIM_R $6 !1, 1 19 ECHO $6 11 20 EXT_STMT 21 FETCH_DIM_R $7 !1, 2 22 ECHO $7 13 23 > RETURN 1 branch: # 0; line: 2- 13; sop: 0; eop: 23; out1: -2 path #1: 0, $
所感
そこまで厳密に理解する気はないけどあったら便利かもくらいは理解しておきたい。
最近はもうパフォーマンスが上がってきているのでそこまで気にすることはないような気もするので
centos6.8にphp7をyumでインストールする
インストール
リポジトリ
sudo rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-6.noarch.rpm sudo rpm -Uvh https://mirror.webtatic.com/yum/el6/latest.rpm
※リポジトリを設定する
yum
sudo yum install php70w php70w-bcmath php70w-cli php70w-common \ php70w-dba php70w-devel php70w-embedded php70w-enchant \ php70w-fpm php70w-gd php70w-imap php70w-interbase php70w-intl \ php70w-ldap php70w-mbstring php70w-mcrypt \ php70w-mysqlnd php70w-odbc php70w-opcache php70w-pdo \ php70w-pdo_dblib php70w-pear php70w-pecl-apcu php70w-pecl-imagick \ php70w-pecl-redis php70w-pecl-xdebug php70w-pgsql php70w-phpdbg \ php70w-process php70w-pspell php70w-recode php70w-snmp php70w-soap \ php70w-tidy php70w-xml php70w-xmlrpc
※とりあえず必要そうなものを調べるの面倒なんでいれられそうなやつ全部
結果
$ php -v PHP 7.0.10 (cli) (built: Aug 20 2016 08:13:48) ( NTS ) Copyright (c) 1997-2016 The PHP Group Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies $
cakephp3で複数データをインサート
データを登録する際
1件ずつ登録するか、一括で登録するか…
環境
CentOS7.x
php7.0.3
cakephp3.2.3
一括で登録
sample1
src/Shell/Sample1Shell.php
<?php namespace App\Shell; use Cake\Console\Shell; use Cake\ORM\TableRegistry; /** * Sample1 shell command. */ class Sample1Shell extends Shell { /** * main() method. * * @return bool|int Success or error code. */ public function main() { // サンプルデータ準備 $postList = [ [ "title" => "aaa1", "body" => "hogehoge1", "created" => date("Y-m-d H:i:s", strtotime("now")), "modified" => date("Y-m-d H:i:s", strtotime("now")), ], [ "title" => "aaa2", "body" => "hogehoge2", "created" => date("Y-m-d H:i:s", strtotime("now")), "modified" => date("Y-m-d H:i:s", strtotime("now")), ], [ "title" => "aaa3", "body" => "hogehoge3", "created" => date("Y-m-d H:i:s", strtotime("now")), "modified" => date("Y-m-d H:i:s", strtotime("now")), ], ]; // テーブルオブジェクトを取得 $posts = TableRegistry::get("Posts"); // クエリーオブジェクトを取得 $oQuery = $posts->query(); // 配列単位にデータを設定 foreach($postList as $post){ // 1行ずつ設定 $oQuery ->insert(['title', 'body', 'created', 'modified']) // キーを指定 ->values($post); // 明細を設定 } // 実行 $oQuery->execute(); } }
※モデルのsaveではないのでcreatedやmodifiedは任意で設定する必要があります。
SQL
INSERT INTO posts ( title, body, created, modified ) VALUES ('aaa1', 'hogehoge1', '2016-03-08 13:08:31', '2016-03-08 13:08:31'), ('aaa2', 'hogehoge2', '2016-03-08 13:08:31', '2016-03-08 13:08:31'), ('aaa3', 'hogehoge3', '2016-03-08 13:08:31', '2016-03-08 13:08:31')
一括で実行されています
一件ずつ登録
sample2
src/Shell/Sample2Shell.php
<?php namespace App\Shell; use Cake\Console\Shell; use Cake\ORM\TableRegistry; /** * Sample2 shell command. */ class Sample2Shell extends Shell { /** * main() method. * * @return bool|int Success or error code. */ public function main() { // サンプルデータ準備 $postList = [ [ "title" => "bbb1", "body" => "foofoo1", ], [ "title" => "bbb2", "body" => "foofoo2", ], [ "title" => "bbb3", "body" => "foofoo3", ], ]; // テーブルオブジェクトを取得 $posts = TableRegistry::get("Posts"); // データを設定して複数のエンティティを取得 $postsEntities = $posts->newEntities($postList); // データ数分保存する foreach($postsEntities as $entity){ // 保存 $posts->save($entity, ['atomic' => false]); } } }
※createdなどは自動設定してくれる
SQL
INSERT INTO posts (title, body, created, modified) VALUES ('bbb1', 'foofoo1', '2016-03-08 13:23:24', '2016-03-08 13:23:24') INSERT INTO posts (title, body, created, modified) VALUES ('bbb2', 'foofoo2', '2016-03-08 13:23:24', '2016-03-08 13:23:24') INSERT INTO posts (title, body, created, modified) VALUES ('bbb3', 'foofoo3', '2016-03-08 13:23:24', '2016-03-08 13:23:24')
一件ずつ実行
参考
[PHP]CakePHP 3.x でも、複数行INSERTできるよ! - Qiita
Saving Data — CakePHP Cookbook 3.x documentation
Inserting Multiple Rows with CakePHP 3 | Chris Nizzardini
所感
一括で登録できた方が楽なのでそちらを使う事になると思われる。変なデータになっていないかは別の方法でチェックして対応する
ビジネスロジックの場所に困りそうな状況になりつつあるけどまあ最初はコントローラーを困らせていこう(^ ^)