[CakePHP4.x] 3系との違いを考える

$ php composer.phar create-project –prefer-dist cakephp/app:4.* blog
$ bin/cake server -H 192.168.56.10 -p 8000
$ bin/cake migrations migrate

migrations migrate
migrations migrate -t migrationID
migrations rollback
migrations rollback -t migrationID
migrations status

PostsTable.php

    public function validationDefault(Validator $validator): Validator
    {
        $validator
            ->integer('id')
            ->allowEmptyString('id', null, 'create');

        $validator
            ->scalar('title')
            ->maxLength('title', 150, '150文字以上で入力してください。')
            ->minLength('title', 5, '5文字以上で入力してください。')
            ->notEmptyString('title', 'タイトルは必ず入力してください');

        $validator
            ->scalar('description')
            ->maxLength('description', 255, '150文字以上で入力してください。')
            ->allowEmptyString('description');

        $validator
            ->scalar('body')
            ->allowEmptyString('body');

        $validator
            ->boolean('published')
            ->notEmptyString('published');

        return $validator;
    }

OK、続いて、デプロイ周りか…

[CakePHP] 3.xの復習

– データベースの作成から(mysql)
create database cake3
use cake3

create table posts (
id int unsigned auto_increment primary key,
title varchar(255),
body text,
created datetime default null,
modified datetime default null
);
insert into posts (title, body, created) values
(‘title 1’, ‘body 1’, now()),
(‘title 2’, ‘body 2’, now()),
(‘title 3’, ‘body 3’, now());
select * from posts;

– cakephpのインストール
composerでインストールする
$ php composer.phar create-project –prefer-dist cakephp/app:3.* myapp

### ディレクトリ構成の変更
– srcフォルダ新設
– webrootがWebブラウザからアクセスしたときに見るフォルダ

### 2系と3系の違い
1
ディレクトリ構成の変更
app, lib, plugins, vendors
bin, config, plugins, src, tests, tmp, vendor, webroot
-srcの中に、controller, model viewが入る
-webrootにpublicなファイルを配置
2
intl拡張モジュール
不要
必要
php-intlインストール
2
ビルトインサーバー
なし
bin/cake server -H 192.168.56.10 -p 8000

3
データベースの設定
app/Config/database.php
config/app.php

4
タイムゾーンの設定
app/Config/core.php
config/app.php

5
MVCファイルの作成
手動
bin/cake bake all ${app}

6
Modelファイル
app/Model/Post.php
src/Model/Table/PostsTable.php

7
Modelの書き方
class Post extends AppModel{
}
name space App\Model\Table
use Cake\ORM\Table;
class PostsTable extends Table{
}
名前空間を定義
ORM, Validation等を使用
Classの中にinitializeで初期化
8
Viewファイル
app/View/Posts/index.ctp
src/Template/Posts/index.ctp
titleなどはviewの中に記載
elementを追加できる
9
Controllerファイル
app/Controller/PostsController.php
src/Controller/PostsController.php

10
Controllerの書き方

namespace App\Controller;
class PostsController extends AppController { 
}
レコードの作成は$this->Posts->newEntity();と書く
11
Controllerでのfindの書き方
$this->Post->find(‘all’, $params);
$this->Post->find(‘all’)->order([‘title’=>’DESC’]);
繋げて条件を指定できる
12
Routing
app/Config/routes.php
config/routes.php

13
Template
app/View/Layouts/default.ctp
src/Template/Layout/default.ctp
controllerに$this->viewBuilder()->layout(‘my_layout‘);で独自テンプレートを表示できる
14
Validation
modelでarrayで定義
modelでValidationDefaultで定義

うーむ、これ3系と4系の違いもやらんといけんのか…

[CakePHP] 2.xの復習

公式サイト
https://cakephp.org/jp
ドキュメント
https://book.cakephp.org/4/ja/index.html

PHP/MySQL/HTMLCSSJS

– 覚えておいた方が良い用語
MVC -> Model, View, Controller
CoC: Convention over Configuration

CakePHP 2.xをインストールしようと思ったが…
$ git clone -b 2.x git://github.com/cakephp/cakephp.git
Cloning into ‘cakephp’…
fatal: remote error:

composerで入れるか…
$ curl -sS https://getcomposer.org/installer | php
$ php composer.phar create-project –prefer-dist ‘cakephp/app:2.10.*’ myapp
Creating a “cakephp/app:2.10.*” project at “./myapp”

[InvalidArgumentException]
Could not find package cakephp/app with version 2.10.*.

composerでももはや無理なので、githubから無理やり取得します
https://github.com/cakephp/cakephp/tree/2.10.22

ここまででそこそこ時間がかかってしまった…orz
$ cd cakephp-2.10.22

appを使う
controller, model, view

書き込み権限
$ sudo chown -R vagrant app/tmp/

create table posts(
id int not null auto_increment primary key,
title varchar(50),
body text,
created datetime default null,
modified datetime default null
);

insert into posts (title, body, created, modified) values
(‘title 1’, ‘body 1’, now(), now()),
(‘title 2’, ‘body 2’, now(), now()),
(‘title 3’, ‘body 3’, now(), now());

Model/Post.php

class Post extends AppModel {
	
}

Controller/PostsController.php

class PostsController extends AppController {

	public $helpers = array('Html', 'Form');

	public function index(){
		$params = array (
			'order' => 'modified desc',
			'limit' => 2
		);
		$this->set('posts', $this->Post->find('all', $params));
		$this->set('title', '記事一覧');
	}
}

/View/posts/index.ctp

<h2></h2>

<ul>
<?php foreach ($posts as $post) : ?>
<li>
<?php
// debug($post);
echo h($post['Post']['title']);
?>
</li>
<?php endforeach; ?>
</ul>

config/core.php

	Configure::write('debug', 0);

config/routes.php

	Router::connect('/', array('controller' => 'posts', 'action' => 'index'));

View/Layouts/default.ctp
-> templateが書かれている

URL -> /${controller}/${method}/

postscontroller.php

	public function view($id = null){
		$this->Post->id = $id;
		$this->set('post', $this->Post->read());
	}

/View/posts/view.ctp

<h2><?php echo h($post['Post']['title']); ?></h2>

<p><?php echo h($post['Post']['body']); ?></p>

index.ctp

echo $this->Html->link($post['Post']['title'], '/posts/view/'.$post['Post']['id']);

<h2>Add Post</h2>
<?php echo $this->Html->link('Add post', array('controller'=>'posts', 'action'=>'add')); ?>

add.ctp

<h2>Add post</h2>

<?php
echo $this->Form->create('Post');

echo $this->Form->input('title');
echo $this->Form->input('body', array('rows'=>3));
echo $this->Form->end('Save Post');
?>

エラーチェックはmodelにvalidationを書いていく
Mode/Post.php

class Post extends AppModel {
	public $validate = array(
		'title' => array(
			'rule' => 'notEmpty',
		),
		'body' => array(
			'rule' => 'notEmpty',
		)
	);
}

Posts/edit.ctp

<h2>Edit Post</h2>

<?php
echo $this->Form->create('Post'. array('action'=>'edit'));

echo $this->Form->input('title');
echo $this->Form->input('body', array('rows'=>3));
echo $this->Form->end('Save!');

2系はかなり古いか…
Cake自体があまり人気ないかも…

Event BridgeでAWS Batchを動かしたい

5分おきの場合は
0/5 * ? * * * で設定する。Day of monthが?になるのは何故かわからん。

次の画面で、targetに Batch job queueを選択する
job queue, job definitionはarn, job nameは任意に入れる

Ruleができたら、cloud watchで確認する

うん、event bridgeからも実行できているのがわかります。

[AWS Batch] 触って理解する

### 機能の流れ
Batchで実行したい処理を定義する(自動的にECSにクラスタが作られる)
-> Batchで処理を走らせる(EC2にインスタンスが立ち上がり、処理が完了したら自動でインスタンスが削除される)
– CloudWatch内のイベント機能で定期実行するようにする

1. Job definitionsでジョブを定義する
– platform: fargate, ecsTaskExecutionRole
– Job configuration: public.ecr.aws/amazonlinux/amazonlinux:latest
L Command syntax: Bash
L Command: echo ‘hello world

2. Compute environments 作成

3. test_job_queues作成

4. Jobsを作成

CannotPullContainerError: inspect image has been retried 5 time(s): failed to resolve ref “public.ecr.aws/amazonlinux/amazonlinux:latest”: failed to do request: Head https://public.ecr.aws/v2/amazonlinux/amazonlinux/manifests/latest: dial tcp 99.83.145…

うーん、うまくいかんな…

CannotPullContainerError: inspect image has been retried 5 time(s): failed to resolve ref “docker.io/library/busybox:latest”: failed to do request:

インターネットゲートウェイは設定されてると思うんだが...

色々試した結果、Assign public IPがENABLEDだと上手くいった
cloudwatch logsの /aws/batch/job で確認した結果

んで、これをcloudwatch eventsで実行させたい

[Docker] コンテンツ入りのhttpdコンテナを作る

1. httpdコンテナを起動する
$ sudo docker run -dit –name webcontent -p 8080:80 httpd:2.4
$ sudo docker cp tmp/index.html webcontent:/usr/local/apache2/htdocs

2. コンテナをイメージ化する
docker commitコマンドを使う
$ sudo docker commit webcontent mycustomed_httpd
$ sudo docker images;
REPOSITORY TAG IMAGE ID CREATED SIZE
mycustomed_httpd latest 3239a258d78d 10 seconds ago 144MB
$ sudo docker image history mycustomed_httpd
IMAGE CREATED CREATED BY SIZE COMMENT
3239a258d78d About a minute ago httpd-foreground 219B
b9bd7e513e0f 3 days ago /bin/sh -c #(nop) CMD [“httpd-foreground”] 0B
3 days ago /bin/sh -c #(nop) EXPOSE 80 0B

3. カスタムなイメージを使う
$ sudo docker run -dit –name webcontent_new -p 8081:80 mycustomed_httpd
$ sudo docker ps
$ sudo docker exec -it webcontent_new /bin/bash
root@6bbe9d0c262d:/usr/local/apache2# cat /usr/local/apache2/htdocs/index.html

4. 後始末
$ sudo docker stop webcontent webcontent_new
$ sudo docker rm webcontent webcontent_new
$ sudo docker rmi mycustomed_httpd

ニャルほどー
3連休、こればっかりやってるけど、進んでる感じがしないなー
まあ、理解はかなり進んだが…

[Docker] イメージの自作

httpdイメージには、PHPをインストールするためのパッケージやビルドするための環境などが含まれていない

### よく使われるベースイメージ
debian: なんでもしたいときはdebianが多い
ubuntu: ubuntuフルセット
alpine: muslとBusyBoxをベース パッケージマネージャが付属しているため、busyboxよりこちらの方が使い勝手が良い
busybox: 組み込み目的で作られた小さいLinux

※2.4-alpineなどはalpineをベースに作られたもの
Linuxカーネルは、その下で動いているUbuntuのものなどが使われる。コンテナの中にカーネルはない

– レイヤーの確認(mysqlのレイヤーを確認する)
$ sudo docker image rm mysql:5.7
$ sudo docker pull mysql:5.7
5.7: Pulling from library/mysql
a4b007099961: Pull complete
e2b610d88fd9: Pull complete
38567843b438: Pull complete
5fc423bf9558: Pull complete
aa8241dfe828: Pull complete
cc662311610e: Pull complete

「a4b007…」「e2b610…」「38567…」がレイヤーに相当するイメージ

– Dockerの流儀に従って作る
Dockerfileのベストプラクティス
https://docs.docker.jp/engine/articles/dockerfile_best-practice.html
– 1つのコンテナは1つの処理しかしない
– 利用するポートを明確にする
– 永続化すべき場所を明確にする
– 設定は環境変数で渡す
– ログは標準出力に書き出す
– メインプログラムが終了するとコンテナが終了

ベースイメージに何を使うべきなのかずっと疑問だったが、ある程度理解できた。
バッチのところがやや課題か…

[Docker] Docker Composeの仕組み

Docker Composeは、あらかじめコンテナの起動方法やボリューム、ネットワーク構成などを書いた定義ファイルを用意しておき、その定義ファイルっを読み込ませることでまとめて実行する方法
Docker ComposeはPython製のツール

$ sudo docker-compose –version

docker-compose.yml

version: '3'

services:
  wordpress-db:
    image: mysql:5.7
    networks:
      - wordpressnet
    volumes:
      - wordpress_db_volume:/var/lib/mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: myrootpassword
      MYSQL_DATABASE: wordpressdb
      MYSQL_USER: wordpressuser
      MYSQL_PASSWORD: wordpresspass

  wordpress-app:
    depends_on:
      - wordpress-db
    image: wordpress
    networks:
      - wordpressnet
    ports:
      - 8080:80
    restart: always
    environment:
      WORDPRESS_DB_HOST: wordpress-db
      WORDPRESS_DB_NAME: wordpressdb
      WORDPRESS_DB_USER: wordpressuser
      WORDPRESS_DB_PASSWORD: wordpresspass

networks:
  wordpressnet:

volumes:
  wordpress_db_volume:

### Docker Compose操作
$ sudo docker-compose up -d
$ sudo docker-compose ps
Name Command State Ports
———————————————————————————————————
wordpress_wordpress-app_1 docker-entrypoint.sh apach … Up 0.0.0.0:8080->80/tcp,:::8080->80/tcp
wordpress_wordpress-db_1 docker-entrypoint.sh mysqld Up 3306/tcp, 33060/tcp
$ sudo docker network ls
$ sudo docker volume ls

### コンテナを停止して破棄
$ sudo docker-compose down

### Docker-compose.ymlの書き方
1. サービス
2. ネットワーク
3. ボリューム

image:wordpress
image:
wordpress
depends_on: この定義によって、後に起動できる

– ネットワークの指定省略
明示的にネットワークを指定しなかったときは、記述しているサービスが繋がるDockerネットワークを自動的に作成し、全てのサービスをそのネットワークに接続するように構成する

– サービスを個別に操作
docker-compose logs
docker-compose rm
docker-compose run
docker-compose exec
docker-compose start
docker-compose stop

うむー進むのだけは早い

[Docker] WordPressを構築する

1. Dockerネットワークを作成
$ sudo docker network create wordpressnet
$ sudo docker network ls

2. ボリュームの作成
$ sudo docker volume create wordpress_db_volume
$ sudo docker volume ls

3. mysqlコンテナを起動
$ sudo docker run –name wordpress-db -dit -v wordpress_db_volume:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=myrootpassword -e MYSQL_DATABASE=wordpressdb -e MYSQL_USER=wordpressuser -e MYSQL_PASSWORD=wordpresspass –net wordpressnet mysql:5.7

4. WordPressコンテナを起動
$ sudo docker run –name wordpress-app -dit -p 8080:80 -e WORDPRESS_DB_HOST=wordpress-db -e WORDPRESS_DB_NAME=wordpressdb -e WORDPRESS_DB_USER=wordpressuser -e WORDPRESS_DB_PASSWORD=wordpresspass –net wordpressnet wordpress

$ sudo docker stop wordpress-db wordpress-app
$ sudo docker rm wordpress-db wordpress-app
$ sudo docker network rm wordpressnet
$ sudo docker volume rm wordpress_db_volume

うん、割と簡単

[Docker] Dockerネットワーク

Dockerネットワークを作ることで、コンテナ名で通信できるようになる

### Dockerネットワークの作成
$ sudo docker network create mydockernet
$ sudo docker network ls
$ sudo docker network inspect mydockernet

明示的にipアドレスの範囲を指定することもできる
$ sudo docker network create examplenet –subnet 10.0.0.0/16 –gateway 10.0.0.1

### Dockerネットワークにコンテンツを作る
$ sudo docker run -dit –name web01 -p 8080:80 –net mydockernet httpd:2.4
$ sudo docker run -dit –name web02 -p 8081:80 –net mydockernet httpd:2.4
$ sudo docker network inspect mydockernet
※connectやdisconnectを使って、コンテナを破棄せずに接続したり切断できる
$ sudo docker run –rm -it –net mydockernet ubuntu /bin/bash
# apt update
# apt -y upgrade
# apt install -y iproute2 iputils-ping curl
# ping -c 4 web01
# curl http://web01/

### Dockerネットワークの削除
$ sudo docker stop web01 web02
$ sudo docker rm web01 web02
$ sudo docker network rm mydockernet

ok, そこそこ進んでるような気がする…