- 投稿日:2020-08-09T19:23:21+09:00
Laravelのpluck()でunicodeが表示される。
問題
formに初期値を入れたくて、LaravelのEloquentで取得した行から
該当するカラムを取得する際に、unicodeでエンコードされた文字列が出力される。controller.php$content = Model::where('id', $id)->first()->pluck('content'); return view('admin.event_chat') ->with('content', $content)view.blade.php<form action="/Admin/eventChatSend" method="POST"> @csrf @if (isset($content)) <input type="text" name="content" value="{{ $content }}"> @else <input type="text" name="content" placeholder="定型文はありません"> @endif <input type="submit" value="送信"> </form>このように実装した場合、unicodeでエンコードされた文字列
content
が挿入されます。解決案
まぁ、pluck()を通すとunicodeでエンコードされるということは
当たり前のようにpluck()を使わなければいいのでView側で取ってくるか$content = $row->content
で取得すればいいです。前者で実装してみました。controller.php$row = Model::where('id', $id)->first(); return view('admin.event_chat') ->with('row', $row)view.blade.php<form action="/Admin/eventChatSend" method="POST"> @csrf @if (isset($row)) <input type="text" name="content" value="{{ $row->content }}"> @else <input type="text" name="content" placeholder="定型文はありません"> @endif <input type="submit" value="送信"> </form>
$row
がある時は必ず、content
がある程での実装となっています。まとめ
Laravelでカラムを取得するpluck()を通すとunicodeでエンコードされてしまうので
$row->content
で回避するか、View川で取得すると
utf8でエンコードされた文字列が返ってきます。
どなたかpluck()
で文字列をutf8でエンコードする方法をご存知の方はコメントお願いします!!
- 投稿日:2020-08-09T17:43:21+09:00
絶対に失敗しないDockerでLaravel6.8+Vueの実行環境(LEMP環境)を構築する方法〜後編〜
1.バージョン
Laravel 6.8
Vue.js 2.6.11
Docker Desktop 2.3.0.32.はじめに
DockerでLaravel+Vue.jsの実行環境を構築する方法をまとめます。
この記事は
絶対に失敗しないDockerでLaravel+Vueの実行環境(LEMP環境)を構築する方法〜前編〜
の後編です。前編を読んでない方はまず前編を読んでいただければと思います。
前編の続きで以下についてまとめます。
- Dockerfileを作成する(PHPコンテナのイメージの設計書)
- Nginxの設定ファイルを作成する
- イメージの構築(build)
- コンテナの起動(up)
- Laravelをインストールする
- Vue.jsをインストール
3.ディレクトリ構造(完成形)
my-application(*) ├─ docker(*) │ ├─ php(*) │ │ └─ Dockerfile │ └─ web(*) │ └─ default.conf │ ├─ laravel-vue-app(*) │ └─ ここにLaravelのPJディレクトリが作られる │ └─ docker-compose.yml(*)のディレクトリ名は任意です。
4.Dockerfileを作成する(PHPコンテナのイメージの設計書)
PHP
コンテナにはLaravel
をインストールするためのパッケージ管理ツールであるComposer
とVue.js
をインストールするためのパッケージ管理ツールであるnpm
をそれぞれインストールする必要があります。※フロントエンドに
Vue.js
を使わない場合は該当箇所は追記せずに進めてもらってOKです。
※例えばフロントエンドはJavaScript、jQueryのみの場合そのため、カスタマイズしたイメージを使うのでイメージの設計書である
Dockerfile
を作成します。4-1.Dockerfileの完成形
以下の
php
ディレクトリ(名前は任意)配下にDockerfile
を作成してください。(拡張子不要)my-application(*) ├─ docker(*) │ ├─ php(*) │ │ └─ Dockerfile←ココ完成形のDockerfileが以下です↓
Dockerfile#イメージのベースを指定 FROM php:7.2-fpm #パッケージ管理ツールapt-getの更新と必要パッケージのインストール RUN apt-get update \ && apt-get install -y \ git \ zip \ unzip \ vim \ libpq-dev #composerをインストール RUN cd /usr/bin \ && curl -s http://getcomposer.org/installer | php && ln -s /usr/bin/composer.phar /usr/bin/composer #npmインストール RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - \ && apt-get install -y nodejs #MySQLを使えるようにする RUN docker-php-ext-install pdo_mysql pdo_pgsql #コンテナ内に入った時のディレクトリを指定 WORKDIR /var/www/htmlDockerfileの内容の詳しい説明は割愛します(というか自信がないw)が、ざっくり説明します。
4-2.イメージのベースを指定
FROM php:7.2-fpm今回構築する
PHP
コンテナはphp:7.2-fpm
のイメージをベースに作成します。
(PHP7系です)4-3.パッケージ管理ツールapt-getの更新と必要パッケージのインストール
RUN apt-get update \ && apt-get install -y \ git \ zip \ unzip \ vim \ libpq-devDocker for Macの場合は
apt-get
というパッケージ管理ツールを使って必要なパッケージ・ライブラリをインストールします。
その前に一度apt-get
を最新にするためにRUN apt-get update
を実行してます。(
RUN
でイメージ構築時にLaravelコマンドを実行します)4-4.composerをインストール
RUN cd /usr/bin \ && curl -s http://getcomposer.org/installer | php && ln -s /usr/bin/composer.phar /usr/bin/composer
Laravel
はComposer
というパッケージ管理ツールでインストールするのでComposer
をインストールします。4-5.npmインストール
#npmインストール RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - \ && apt-get install -y nodejs
Vue.js
はnode.jsのパッケージ管理ツールであるnpm
を使ってインストールするのでnpm
をインストールします。※フロントエンドに
Vue.js
を使わない方はこちらは飛ばしてOKです。なお、
npm
、Vue.js
のインストールにはこちらの記事を参考にしましたので合わせて読んでいただければと思います。お手軽laravel Vue.js docker-compose環境構築
4-6.MySQLを使えるようにする
RUN docker-php-ext-install pdo_mysql pdo_pgsql
docker-php-ext-install
でPHPの拡張モジュールをインストールすることができます。4-7.コンテナ内に入った時のディレクトリを指定
WORKDIR /var/www/html
WORKDIR
はWork Directoryの略で、PHPコンテナ(app)に入った時のカレントディレクトリになります。
つまり、docker-compose exec app bash
でappコンテナの中に入った場合、/var/www/html
がカレントディレクトリになります。
Laravel
で使うコマンドである$ php artisan 〜
を使うためには、後に作るlaravel-vue-app
ディレクトリに移動する必要があるので、/var/www/htmml
を/var/www/html/laravel-vue-app
に変更しても問題ありません。
(むしろそっちの方が後々楽かも...)4.Nginxの設定ファイルを作成する
次にNginxの設定ファイル
default.conf
を、web
ディレクトリ配下に作成します。my-application(*) ├─ docker(*) │ ├─ php(*) │ │ └─ Dockerfile │ └─ web(*) │ └─ default.conf←ココ全体のコードはこちらです↓
default.confserver { listen 80; root /var/www/html/laravel-vue-app/public; index index.php index.html index.htm; access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; location / { try_files $uri $uri/ /index.php$is_args$args; } location ~ \.php$ { fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass app:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } }この設定ファイルで注意するところは2箇所です。
まず1つ目はこちら↓listen 80;
docker-compose.yml
で設定したportsオプションのコンテナ側のポート番号と一致させてください。web: image: nginx:1.15.6 ports: - '8000:80'←ココ2つ目は
root /var/www/html/laravel-vue-app/public; index index.php index.html index.htm;ここはLaravelのプロジェクトファイルを作成するディレクトリを使います。
my-application(*) ├─ docker(*) │ ├─ php(*) │ │ └─ Dockerfile │ └─ web(*) │ └─ default.conf │ ├─ laravel-vue-app(*)←ココ │ └─ ここにLaravelのPJディレクトリが作られる今回は
laravel-vue-app
というディレクトリにしているので/var/www/html/larave-vue-app/public;ですね。
(
laravel-vue-app
ディレクトリはLaravelのインストール時に自動的に作られるので今作っておく必要はありません)
/var/www/html
はdocker-compose.yml
のappコンテナでもローカルと対応づけしてましたよね。app: build: ./docker/php volumes: - .:/var/www/html←ココローカルの
./laravel-vue-app
つまりmy-application/laravel-vue-app
は/var/www/html/laravel-vue-app
と対応付けされます。(これをマウントするとも言います)ちなみに
public
はLaravelのプロジェクトを作成すると自動的に作られます。2行目のこちら↓ですが、「Nginxにアクセスした時に初めに
/public/index.php
が処理されます」という設定です。index index.php index.html index.htm;
index.php
がなければindex.html
が、それもなければindex.htm
が処理されますが、index.php
がないことはないのでindex.php
だけでもいいかもしれませんが念のために書いておきます。Laravelプロジェクトで
public/index.php
がどのような処理をしているかはこちらの記事に詳しく書いてますが、環境構築するに当たってはあまり必要ないかなと思います。public/index.phpからミドルウェア/コントローラーが実行されるまで - Laravelコードリーディング
これで環境構築に必要な各種設定ファイルの作成は終了です!
(長かったですね...お疲れ様です)5.イメージの構築(build)
それではまずは
Dockerfile
からイメージを構築します。ターミナルで
my-application
ディレクトリに移動します。$ cd my-application配下のディレクトリ・ファイルを確認します。
$ lsここで以下の表示が出ればOKです。
docker docker-compose.yml
docker-compose
コマンドは`docker-compose.ymlがあるディレクトリでなければ実行できません。それでは以下のコマンドでイメージを構築(build)します。
$ docker-compose build時間がかかると思いますが、以下の表示が出ればbuild成功です。
Successfully built 27d58ffbe8e1 Successfully tagged my-application_app:latestこれでPHPコンテナ用のイメージが完成です。
(他のコンテナは既存のイメージをそのまま使うのでbuild不要)※builtの後の数字がランダムなので人それぞれ変わります。
6.コンテナの起動(up)
それではイメージを元にコンテナを起動します。
docker-compose build
を実行したディレクトリで以下のコマンドを実行します。$ docker-compose up -d実行後、以下の表示が出ればコンテナの起動は完了です。
Creating network "my-application_default" with the default driver Creating volume "my-application_mysql-volume" with default driver Creating my-application_app_1 ... done Creating my-application_db_1 ... done Creating my-application_web_1 ... doneこれで各種コンテナの起動完了です。
7.Laravelのインストール
構築したDocker環境にLaravelをインストールします。
以下の手順で進めます。
- Composerのバージョン確認
- Laravelの新規プロジェクト作成
7-1.Composerのバージョン確認
まずは
Composer
がインストールできているか確認します。
(これはLaravelのインストールに必要というよりLaravelの新規プロジェクトを作成できる状態なのか、の確認です)先ほどまでと同じディレクトリで以下のコマンドを実行し、
app
コンテナの中に入ります。$ docker-compose exec app bash実行すると以下のように/var/www/htmlディレクトリに変わります。(これは既にコンテナ内部にいます)
root@d1138847703d:/var/www/html#以下のコマンドで
Composer
のバージョンを確認します。$ composer --versionバージョンが表示されればOKです。
7-2.Laravelの新規プロジェクトを作成
ディレクトリは変えずに以下のコマンドを実行します。
composer create-project --prefer-dist "laravel/laravel=6.8.*" laravel-vue-appこれでLaravel6.8を指定して
laravel-vue-app
という新規プロジェクトが作成されます。
laravel-vue-app
というディレクトリも一緒にmy-application
ディレクトリに配下に作成され、コンテナ内の/var/www/html
ディレクトリ配下にマウントされます。Laravelの5系を使いたい方は
6.8
のところを適宜変えてください。
(ただし、動作確認はこちらではしていませんのでご了承ください)時間がかかりますが、以下のコマンドが表示されればOKです。
Package manifest generated successfully.その後に以下のコマンドが表示されていても問題ありません。
39 packages you are using are looking for funding. Use the `composer fund` command to find out more! > @php artisan key:generate --ansi Application key set successfully.ローカルの
my-application
配下及びコンテナの/var/www/html
配下にlaravel-vue-app
ディレクトリとlaravelプロジェクトのディレクトリがたくさんできています。7-3.LaravelとMySQLとの接続を設定する
Laravleでの開発が行えるようにMySQLとの接続を設定します。
エディターで
laravel-vue-app
を開いて.env
を開きます。9〜14行目からを以下のように修正します↓
.envDB_CONNECTION=mysql DB_HOST=db(←コンテナ名) DB_PORT=3306(←コンテナ側のポート番号) DB_DATABASE=db_name DB_USERNAME=db_user DB_PASSWORD=db_passwordこれは
docker-compose.yml
のdb
コンテナの設定と合わせます。db: image: mysql:5.7 ports: - '3306:3306' environment: MYSQL_DATABASE: db_name MYSQL_USER: db_user MYSQL_PASSWORD: db_password
.env
の5行目も以下の通り修正します。APP_URL=http://localhost:8000次にコンテナ内で
larave-vue-app
ディレクトリに移動します。$ cd laravel-vue-appそこで以下のコマンドを実行します
$ php artisan migrate以下のコマンドが表示されればOKです。
Migration table created successfully. Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table (0.07 seconds) Migrating: 2014_10_12_100000_create_password_resets_table Migrated: 2014_10_12_100000_create_password_resets_table (0.04 seconds) Migrating: 2019_08_19_000000_create_failed_jobs_table Migrated: 2019_08_19_000000_create_failed_jobs_table (0.02 seconds)では、一度コンテナから出て、再度コンテナの停止(破壊も行われる)・起動を実行します。
$ exit $ docker-compose down $ docker-compose up -dブラウザで
localhost:8000
にアクセスするとLaravelのページが表示されます。これで Dockerを使ったlaravelの実行環境(LEMP環境)の構築は完了です!
8.Vue.jsのインストール
次に
Vue.js
を使えるようにします。
laravel-vue-app
配下のpackage.json
の19行目から以下の通り編集します。package.json"sass-loader": "^7.1.0",(←カンマ追記) "vue": "^2.6.11",(←追記) "vue-template-compiler": "^2.6.11"(←追記)追記したら
app
コンテナに入り、laravel-vue-app
に移動します。$ docker-compose exec app bash $ cd laravel-vue-app以下のコマンドを実行します。
$ npm installこれで
Vue.js
のインストールも完了です。9.まとめ
これでDockerでLaravel6.8+Vueの実行環境(LEMP環境)の構築ができました。
間違っていることや不明点があればお気軽にコメントいただければと思います。
前編はこちら↓
絶対に失敗しないDockerでLaravel6.8+Vueの実行環境(LEMP環境)を構築する方法〜前編〜
- 投稿日:2020-08-09T17:42:05+09:00
絶対に失敗しないDockerでLaravel+Vueの実行環境(LEMP環境)を構築する方法〜前編〜
1.バージョン
Laravel 6.8
Vue.js 2.6.11
Docker Desktop 2.3.0.32.はじめに
DockerでLaravel+Vue.jsの実行環境を構築する方法をまとめます。
ネットにはDockerdでLaravel実行環境を構築する方法はありますが、多くの記事が設定コードを載せているだけで詳しい説明がなかったので、「この記事だけ読めばある程度意味を理解でき、絶対に環境構築が成功する」という記事を執筆しようと思いました。
構築する環境はLEMP環境で構成は以下の通りです。
ミドルウェアの種類 頭文字 ミドルウェア名 備考 OS L Linux (※) Webサーバー E Nginx エンジンエックスと読む データベース M MySQL 特になし アプリケーション P PHP フレームワークはLaravelを使う
Nginx
、MySQL
、PHP
の3つをコンテナの設定を行います。(※)僕がググる中で「あれ、Linuxのコンテナは要らないの?」と疑問に思ってたのですが、Docker for Macを使うとMacOSに標準装備されているHyperKitという仮想化ツールによってLinuxの仮想マシンが自動で起動してくれるので後述するコンテナの設定ファイルにはOSに関する記述は不要です。(詳しくは下の記事)
Docker for Macでおこなっていることのまとめ(メモ)
3.注意点
- この記事を見ながら環境構築する場合はMacOSをオススメします。
- この記事で使うDocker imageのバージョン(tag No.)以外のバージョンでの動作確認はしておりません。
- DockerやDocker-Composeの概要に関する説明ほとんどしませんのでDockerに対する理解が浅い方は以下の記事などを参考に勉強しておくことをオススメします。
4.全体の手順
- DockerとDocker Composeを使えるようにする
- docker-compose.yml(コンテナの設定ファイル)を作成する
- Dockerfileを作成する(PHPコンテナのイメージの設計書)
- Nginxの設定ファイルを作成する
- イメージの構築(buid)
- コンテナの起動(up)
- Laravelをインストールする
- Vue.jsをインストール
5.DockerとDocker Composeを使えるようにする
まずは
Docker
とDocker-Compose
をお使いのPCで使えるようにします。
Docker
を使えるようにするためにVagrantでLinux系のOSの仮想マシンを構築→仮想マシンにDockerをインストール→Dockerを使えるようにする方法(Docker on Vagrant)でも良いですが、Docker
とDocker Compose
のインストールが簡単にできるDocker Desktop(Docker for Mac)を使います。
(僕は実務でもDocker Desktopを使っています)Docker Desktopのインストール方法はググればたくさん出てくるのでここでは説明しませんが、下の記事を見れば問題なくインストールできると思います。
DockerをMacにインストールする(更新: 2019/7/13)
インストールが終わったらターミナルで以下のコマンドを実行してバージョン情報が表示されればインストールは正常にできています。
Dockerのバージョン確認↓
$ docker -vDocker-Composeのバージョン確認↓
$ docker-compose -v6.ディレクトリ構造
6-1.完成形のディレクトリ構造
my-application(*) ├─ docker(*) │ ├─ php(*) │ │ └─ Dockerfile │ └─ web(*) │ └─ default.conf │ ├─ laravel-vue-app(*) │ └─ ここにLaravelのPJディレクトが作られる │ └─ docker-compose.yml(*)のディレクトリ名は任意でOKです。
(default.confも好きなファイル名でよかったかも...です)なお、ディレクトリ構造はこれでなければできないなんてことは全くありません。
僕が環境構築したディレクトリ構造をそのまま載せてますのでお好みで編集していただいて構いません。※ディレクトリ構造を変更すると、後ほど作成するdocker-compose.ymlの設定内容を適宜修正する必要がありますのでちょっと自身がないな、という方はそのままマネして作ってもらえたらOKです。
6-1.必要なディレクトリを作成する
まず、好きな場所(デスクトップでもユーザーディレクトリでもOK)に
my-application
(名前は自由)ディレクトリを作成します。その下に
docker
ディレクトリを作成します。
次にdocker
ディレクトリの中に以下2つのディレクトリを作成します。
- php(名前は自由)
- web(名前は自由)
すると、以下のディレクトリ構造になると思います。
my-application(*) └─docker(*) ├─ php(*) └─ web(*)これで準備はOKです。
これからの各作業によって完成形のディレクトリ構造にします。
- phpの中にはPHPコンテナ用のDockerfileを作成する
- webの中にNginxの設定ファイル(default.conf)を作成する
- laravel-vue-appディレクトリはLaravelインストール時に自動的に作られる
- docker-compose.ymlは次のセクションで作成する
7.docker-compose.yml(コンテナの設定ファイル)を作成する
ではここから各種コンテナの設定をしていきます。
ミドルウェア毎に複数のコンテナを作成・管理する場合はコンテナの設定ファイルであるdocker-compose.ymlを作成します。
my-application
ディレクトリ配下に作成してください。7-1.全体のコード(完成形)
まずは全体のコードはこちらです。
docker-compose.yml#docker-compose.ymlのバージョン version: '3' #docker volumeの設定 volumes: mysql-volume: #services以下に各コンテナの設定を書く services: #Webサーバーのコンテナ web: image: nginx:1.15.6 ports: - '8000:80' depends_on: - app volumes: - ./docker/web/default.conf:/etc/nginx/conf.d/default.conf - .:/var/www/html #アプリケーションのコンテナ app: build: ./docker/php volumes: - .:/var/www/html #データベースのコンテナ db: image: mysql:5.7 ports: - '3306:3306' environment: MYSQL_DATABASE: db_name MYSQL_USER: db_user MYSQL_PASSWORD: db_password MYSQL_ROOT_PASSWORD: root TZ: 'Asia/Tokyo' volumes: - mysql-volume:/var/lib/mysql7-2.docker-compopse.ymlのバージョン
まずはこちらのコードです。
version: '3'今docker-compose.ymlファイルを作成する場合は
version: '3'
と書いておけば間違いないです。このバージョンはdocker-compose.yml(Composeファイル)のバージョンであり
Docker Compose
のバージョンとは違います。
(公式サイトにも一応書いてます)まあ、お決まり事みたいなことなのでそんなに深く考えなくていいかなと思います。
7-3.Webサーバー(Nginx)コンテナの設定について
Webサーバーには
Nginx
を使います。Nginxコンテナの設定はこちら↓
web: image: nginx:1.15.6 ports: - '8000:80' depends_on: - app volumes: - ./docker/web/default.conf:/etc/nginx/conf.d/default.conf - .:/var/www/html7-3-1.コンテナ名
web:はコンテナ名を表します。
今回はweb
というコンテナ名にしました。
こちらも決まりはないので好きに命名してOKですが、web
やweb_server
がわかりやすくて無難かなと思います。7-3-2.イメージ
image
オプションはコンテナの元になるイメージを設定します。このimgae:
の右に書いたイメージをDokcerHub(Docker imageを共有するプラットフォーム)
から持ってきます(pullすると言う)。image: nginx:1.15.6Nginxコンテナは
DockerHub
からnginx 1.15.6
のpullしてそれを元に起動します。7-3-3.ports
ports
はローカルとDockerコンテナ間のポート番号の対応付けを設定するオプションです。ports: - '8000:80'ローカルのポート番号8000とコンテナ内のNginxのポート番号80(Nginxのデフォルトのポート番号)をリンクさせています。
これでNginxコンテナが起動している状態でローカルのlocalhost:8000にアクセスするとNginxの80番ポートにアクセスすることができます。
7-3-4.depends_on
depends_on
はコンテナ間の依存関係を設定するオプションです。depends_on: - app
app
はPHP(アプリケーション)コンテナです。
NginxはPHPを実行するため、PHP→Nginxの順にコンテナを起動するようにdepends_on
でコンテナ同士の関係を設定しています。depends_on: - 先に起動するコンテナ名初めて環境構築する方でちょっと内容が難しいと感じる方はここはあまり深く考えずに進んでもOKです。
7-3-5.volumes
volumes
はローカルとDockerコンテナ間のファイル共有を設定するオプションです。volumes: - ./docker/web/default.conf:/etc/nginx/conf.d/default.conf - .:/var/www/htmlここでは
./docker/web/default.conf
と/etc/nginx/conf.d/default.conf
をリンク(対応)付け、
.
と/var/www/html
をリンク(対応)付けしてます。(.
はカレントディレクトリです)volumesオプションはローカルのディレクトリとDockerコンテナ内のディレクトリを
:
で対応させます。volumesでディレクトリをリンクさせることにより、Dockerコンテナ内で
/var/www/html/
に移動した時にローカルの.
以下のディレクトリ、ファイルがそこにあるように(実際にはない)共有することができます。
(ちょっとここ言葉で上手く説明するのが難しいのでわかりにくかったらすみません...)また、ローカルで
.
以下のファイルを修正するとDockerコンテナ内にもその修正が反映されます。書き方は以下の通りです↓
volumes: - (ローカル):(Dockerコンテナ内)ここはDocker環境を構築する上でもしっかり理解しておくべき内容だと思います。
7-4.アプリケーション(PHP)コンテナの設定について
アプリケーションはLaravelを使うのでもちろん
PHP
にします。
PHPコンテナの設定はこちら↓app: build: ./docker/php volumes: - .:/var/www/html7-4-1.コンテナ名
コンテナ名は
app
にしてます。ここも任意ですが、他にはphp
やphp_server
が無難かと。7-4-2.build
build
はDockerHubのイメージをそのまま引用するのではなく、DockerHubのイメージをベースにオリジナルのイメージを作成する(buildする)ときに用います。build: ./docker/phpこれで
./docker/php
の配下にあるDockerfile
というテキストファイルの内容にのっとってイメージを構築していくという設定をしています。ディレクトリ構造の抜粋↓
my-application(*) ├─ docker(*) │ ├─ php(*) │ │ └─ Dockerfile
docker-compose.yml
から見て./docker/php
の配下にちゃんとDockerfile
がありますね。
Dockerfile
の内容については後ほど解説します。7-4-3.volumes
volumes: - .:/var/www/htmlローカルの
.
とDockerコンテナ内の/var/www/html
をリンクさせています。
Webサーバーの時も/var/www/html
が出ましたがこれは覚えておいて良いと思います。
(以下の記事を読んでみても良いかも)7-5.データベース(MySQL)コンテナの設定について
DBは
MySQL
を使います。
MySQLコンテナの設定はこちら↓db: image: mysql:5.7 ports: - '3306:3306' environment: MYSQL_DATABASE: db_name MYSQL_USER: db_user MYSQL_PASSWORD: db_password MYSQL_ROOT_PASSWORD: root TZ: 'Asia/Tokyo' volumes: - mysql-data:/var/lib/mysql7-5-1.コンテナ名
コンテナ名は
db
にしてます。ここも任意ですが、他にはmysql
やdb_server
が無難かと。7-5-2.イメージ
image: mysql:5.7MySQLコンテナもNginxコンテナ同様、DockerHubからイメージをpullして使います。
今回はmysql:5.7
のイメージを使用します。7-5-3.ports
ports: - '3306:3306'Nginxコンテナの設定方法と同様で、ローカルの3306番ポートとDockerコンテナの3306番ポートを共有しています。(3306はMySQLのデフォルトのポート番号)
注意点として、他のアプリケーションでローカルのMySQLに3306番ポートで接続している場合、同じポート番号は使用することができないので
:
より左側の3306
を適当な番号にしてください。(僕はカブっていたので変えました)MySQLコンテナのポート番号(
:
より右側)は3306で問題ありません。7-5-4.environment
environment
は文字通りですが、MySQLの環境変数を設定するオプションです。environment: MYSQL_DATABASE: db_name MYSQL_USER: db_user MYSQL_PASSWORD: db_password MYSQL_ROOT_PASSWORD: root TZ: 'Asia/Tokyo'
- MYSQL_DATABASE:DBの名前(好きな名前でOK)
- MYSQL_USER:MySQLのユーザー名(好きな名前でOK)
- MYSQL_PASSWORD:MySQLのパスワード(好きな名前でOK)
- MYSQL_ROOT_PASSWORD:ルート権限のパスワード(rootが一般的かなと思います)
- TZ:時間設定(Time Zone)
※ひょっとするとLaravel側でタイムゾーンを設定するのでここには不要かもしれませんが一応つけておきました。
あと、構築したファイルをGitHubに上げる場合はここの環境変数は変えてください。
7-5-5.volumes
volumes
は先ほどまでと同じ考え方です。
が、データベースの場合はDocker Volume
というDockerのオプションを使用します。volumes: - mysql-data:/var/lib/mysql
Docker Volume
とはデータを永続的に保存できるようにする仕組みのことで、保存場所のことをvolume(ボリューム)
と呼びます。「なぜデータベースの時にボリューム(という場所)を使うのか」というと、コンテナは停止する時に起動していた物を壊すのでデータベースに保存しているデータがコンテナの停止とする度に消えてしまうからです。
なので開発するWebアプリケーションで扱うデータの保存先であるボリュームを用意する必要があるわけです。
(もちろんですが、ボリュームはコンテナの外に作られます)コンテナの動作は簡単にいうと「起動→停止→破壊」です。で、起動し直す時は新たにコンテナを作って立ち上げます。
上の設定コードからローカルの
mysql-volume
というボリュームとMySQLコンテナの/var/lib/mysql
をリンクさせています。
Docker Volume
の定義はdocker-compose.ymlの上部にあります。volumes: mysql-volume:
Docker Volume
はこちらの記事がわかりやすいです↓Docker、ボリューム(Volume)について真面目に調べた
これで3つ全てのコンテナの設定が終了です。
8.ここまでの全体像
ここまでの内容をざっくりまとめると以下の通りです。
- Dockerを用いたLEMP環境構築では
Nginx
、MySQL
、PHP
のコンテナを準備する- versionは3でOK
- DockerHubのイメージを引用(流用)する場合は
image
、Dockerfileからイメージを構築(build)する場合はbuild
オプションports
はローカルとコンテナ内のポート番号を対応づけるオプションdepends_on
はコンテナ間の依存関係を設定するオプションvolumes
はファイル共有を設定するオプションenvironment
は環境変数を設定するオプションDocker Volume
はデータベースのコンテナを設定する時に用いる仕組みでデータを永続的に保存することができるボリューム(というデータ保存場所)をコンテナの外に作る後編へ続く
環境構築を1つの記事にまとめようと思ったのですが、まだまだ執筆ボリュームもありかなり長くなるので後編で残りの以下をまとめようと思います。
- Dockerfileを作成する(PHPコンテナのイメージの設計書)
- Nginxの設定ファイルを作成する
- イメージを構築(buid)する コンテナを起動(up)する
- Laravelをインストールする
- Vue.jsをインストール
ここまでで間違っていることや不明点があればお気軽にコメントいただければと思います。
後編はこちら
絶対に失敗しないDockerでLaravel6.8+Vueの実行環境(LEMP環境)を構築する方法〜後編〜
- 投稿日:2020-08-09T15:29:47+09:00
テクトロジーによる実践的組織構造学
今回の記事では、ソ連の革命家、医師、哲学者、小説作家であったアレクサンダーボグダノフが提唱したテクトロジーと呼ばれる実践的組織構造学について紹介する。
テクトロジーでは組織が安定、成長、破綻する環境、条件について詳細に解説し、安定した組織を生成する手法について解説している。
テクトロジーの概念を拝借し、創造的な組織創造の手法を紹介したいと思う。テクトロジーにおける組織の定義
テクトロジーでは、組織をオープンクローズ型の成長する有機体システムと定義している。
組織とは以下の要素で構成されている。
ビジョン・・・組織の目指すべき方向性。
経済・・・組織のボディ。巨大であるほど収容できる人の人数が増加する
金融・・・組織を循環する血液。
生産・・・もの、サービスを生産し、組織の経済を巨大化する手段。これらの有機的な要素が相互作用し、成長することで組織という有機体が構成されていると考える。
テクトロジーにおける成長する有機体システムとは
テクトロジーでは、組織をオープンクローズ型の成長する有機体システムと定義している。
テクトロジーにおける組織の定義を中国の陰陽論によって説明することができる。
陰陽論とは、原初は混沌(カオス)の状態であると考え、この混沌の中から光に満ちた明るい澄んだ気、すなわち陽の気が上昇して天となり、重く濁った暗黒の気、すなわち陰の気が下降して地となった。この二気の働きによって万物の事象を理解し、また将来までも予測しようというのが陰陽思想である。
組織が外部からエネルギーを取り入れ、出力するインプット、アウトプットの運動を陰陽論における陽の気と捉えることができる。
逆に組織内部に沈殿し、成長し、ヒエラルキーを形成する秩序生成を担う運動を陰陽論における陰の気と捉えることができる。テクトロジーにおける生産の定義
テクトロジーでは、組織における生産活動は以下の3つに分類されている。
人の生産・・・人に教育を施し、組織活動に従事する生産者を作成する
モノ、サービスの生産・・・外部から取得した資材を用いて、モノ、サービスの生産を行う。
アイデア・・モノ、サービスを生成するための知識、アイディアを作成する。
組織における生産活動を高めることで、組織の経済を成長させることができる。テクトロジーにおける組織が不安定化する条件
テクトロジーにおける組織が不安定化する条件として以下の2点が挙げられる。
・外部からのエネルギー取得の減少・・外部から人、モノ、金の循環が減少することで組織のサイズ、経済を維持することできなくなる。
・ヒエラルキーシステムの固定化・・・ヒエラルキーシステムが巨大化し、組織が硬直化してしまう。
組織不安定化を回避する手法として以下の手段が有効とされている。
生産手段を研究、開発、更新を行い、組織の経済成長のスピードを増加させる。
組織が硬直化の原因になっているヒエラルキーシステムを解体し、適切なサイズに組み替える。まとめ
アレクサンダーボグダノフがテクトロジーに関するアイディアを発表した時期は1920年代である。
独学で組織が破綻する条件、環境を発見し、持続可能な成長のコンセプトを提唱したアレクサンダーボグダノフの先見性は恐るべきものである。
ソ連は軍事、IT、経済においてアメリカと張り合うことができた超大国だった。
ソ連時代に考えられたアイディア、思想などは現代においても見直されるべきものだと思われる。
- 投稿日:2020-08-09T13:33:43+09:00
laravel-cors v2 の HandleCors ミドルウェアは CSRF 対策用途には使えない
はじめに
Web サービスの開発で Laravel × Vue.js という構成を聞くことが多くなってきたのではないでしょうか?
この記事は、私が個人サービスを開発している際にハマった、あるライブラリについてのお話です。この記事を書くにあたり、私の師匠(自称)であるまっぴー(@mpyw)さんに助言を頂きました。
ありがとうございます!!!!!!承知しました師匠 https://t.co/ePE7ha5pfC
— 虚無 ふじしゃん (@fujiwaraizuho) August 4, 2020また、ここでは CSRF 対策や同一オリジンポリシーの基礎知識について詳しく掘り下げません。
私の師匠がとても良い記事を書かれているので、そちらを読んでいただき CSRF 対策と同一オリジンポリシーを完全に理解 した上でこの記事を読むとわかりやすいと思います。これで完璧!今さら振り返る CSRF 対策と同一オリジンポリシーの基礎
laravel-cors って?
ご紹介しましょう、これこそが私がドハマりしたライブラリです。
Laravel において CORS(Cross-Origin Resource Sharing) の導入を行う際に非常に便利なもので、許可するオリジンの設定に正規表現を用いることができたり、様々な拡張に対応しています。
Laravel7 からデフォルトでインストールされるようになっています。ちょっと整理してみよう
Web サービスを Laravel × Vue.js という構成で開発する場合、大抵以下のふたつの方法があります。
- Laravel 自体に Vue.js のコンポネートを流し込む
- 別々のアプリケーションとして開発を行う
Laravel 自体に Vue.js のコンポネートを流し込む場合は、Laravel に標準で用意されている
resource/js/bootstrap.js
を用いることでLaravel 単体で開発を行うときと同じように、CSRF トークンを使って CSRF 対策を行うことができます。別々のアプリケーションとして開発を行う場合も、フロントエンドがバックエンドから送られてくる
XSRF-TOKEN
を用いて CSRF 対策を行うことは可能ですが、XSRF-TOKEN
は Cookie でサーバ側から配信されるためステートフルなWebサービスの場合にしか使えません。また、別々のアプリケーションとして開発を行う場合では
- example.com (フロントエンド)
- api.example.com (バックエンド)
のようにドメインを分けて運用されることが多々あります。
このような構成で、フロントエンドがバックエンドに対してリソースを要求すると、セキュリティ上の理由によりブラウザ自身が 同一オリジンポリシー に従ってリクエストの結果の読み取りをブロックします。
つまり、リクエストは送れてもレスポンスは読み取れないよってことです。同一オリジンポリシーに対して、このドメインに対するリソースの要求は安全なものであることを示し、レスポンスを読み取れるようにするのが CORS (Cross-Origin Resource Sharing) にある
Access-Control-Allow-Origin
などです。では、ステートレスなアプリケーションの場合やドメインがフロントエンドとバックエンドで別れている場合はどのような CSRF 対策を施したらよいのでしょうか?
Origin
をサーバーサイドで検証しよう師匠の記事をよく読み、理解されている方はお察しだと思いますが、上記のような場合はサーバーサイド側で
Origin
ヘッダを検証することで CSRF 対策を行うことができます。これは、現在閲覧しているサイトのURLを示す
Origin
ヘッダが特殊な方法を用いなければ偽装することができず、意図しているオリジンからのリクエストであることをサーバーサイド側で検証することができるからです。本題
私がハマったのは、ズバリ laravel-cors v1.x では
Origin
ヘッダをしっかりとライブラリで検証していたが、laravel-cors v2.x ではOrigin
ヘッダを検証するのをやめていた という点です。以下の画像を御覧ください
これは、laravel-cors のベースとなっているライブラリ stack-cors をOrigin
ヘッダの検証を削除したもの(v2.x)へバージョンアップするためのPRです。
https://github.com/fruitcake/laravel-cors/pull/443ここには、「厳密なオリジンの検証はブラウザ側に任せ、キャッシュ性を向上させる」とあります。
? CORS ≠ CSRF 対策 ?
よく、CORS を導入しているから CSRF 対策ができているという話を聞きますが、これは間違いです。
CORS はあくまで、サーバーに対して別ドメインからリソースを要求し、その結果の読み取りをブロックするものであり、サーバーへのリクエストを制限するものではないからです。よく考えればそれはそう
上記で説明したように、CORS はあくまで返ってきた結果が不正なコードに参照されることを防ぐためのもので、CSRF 対策にはなんら関係がありません。
ライブラリとして持つ責任の範囲を明確にして、厳密なオリジンの検証が必要であればユーザーの実装に任せるというもので、とてもよい変更だったと思います。解決策
laravel-cors v2.x で CSRF 対策ができないことはわかりました。
では、自分でやるしかないでしょう!!!!!
CSRF 対策を自分でするにあたって、要件を書き出しでみましょう。
- メインリクエストでオリジンを検証すること
- リクエストに
Origin
ヘッダが含まれていない場合は通すリクエストに
Origin
ヘッダが含まれていない場合に通すのは、同一オリジンの場合Origin
ヘッダーを付与しない という挙動をするブラウザがあるためです。これを踏まえて、ミドルウェアを書いてみましょう!
ここでは師匠が書いてくださっていたコードを引用させていただきます。VerifyOrigin.php<?php namespace App\Http\Middleware; use Asm89\Stack\CorsService; use Closure; use Symfony\Component\Finder\Exception\AccessDeniedException; class VerifyOrigin { protected CorsService $cors; public function __construct(CorsService $cors) { $this->cors = $cors; } public function handle($request, Closure $next) { // Origin ヘッダがリクエストに含まれていて、かつそのオリジンが許可対象である if ($request->hasHeader('Origin') && !$this->cors->isOriginAllowed($request)) { throw new AccessDeniedException('The request from your origin is not allowed.'); } return $next($request); } }このミドルウェアを使うことで、CSRF 対策もしっかりと行うことができます!
おわりに
おわりに、といってもあんまり書くことないんですが…w
今回の記事は、自分の復習のために書いてみました。
CORS や CSRF 対策に関して再確認ができてよかったです!
- 投稿日:2020-08-09T07:08:14+09:00
Laravel で Access-Control-Allow-Origin ヘッダーを付与しても CORS エラーが解消しない
よくよく考えれば当たり前のことだったんですが、若干ハマってしまったので・・・
同様にハマった人の助けになれば幸いです。普通に CORS 対応をすすめる
Access-Control-Allow-Origin などをレスポンスヘッダーに含ませる Middleware の作成
いろいろな人が記事をまとめてくれているので、ググればすぐ見つかると思います。
各ヘッダーの意味はこちらを参照。
Access-Control-Allow-Origin
Access-Control-Allow-Methods
Access-Control-Allow-HeadersApp\Http\Middleware\Cors<?php namespace App\Http\Middleware; use Closure; class Cors { public function handle($request, Closure $next) { return $next($request) ->header('Access-Control-Allow-Origin', '*') ->header('Access-Control-Allow-Methods', 'GET, POST') ->header('Access-Control-Allow-Headers', 'Accept, X-Requested-With, Origin, Content-Type'); } }api Middleware グループに追加します。
これで api 全体に適用されるようになります。(もちろんルーティング定義の際に api Middleware グループを指定している場合に限ります)App\Http\Kernel<?php namespace App\Http; use Illuminate\Foundation\Http\Kernel as HttpKernel; class Kernel extends HttpKernel { : /** * The application's route middleware groups. * * @var array */ protected $middlewareGroups = [ 'web' => [ \App\Http\Middleware\EncryptCookies::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, // \Illuminate\Session\Middleware\AuthenticateSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class, \App\Http\Middleware\VerifyCsrfToken::class, \Illuminate\Routing\Middleware\SubstituteBindings::class, ], 'api' => [ 'throttle:60,1', \Illuminate\Routing\Middleware\SubstituteBindings::class, \App\Http\Middleware\Cors::class, // ★追加 ], ]; : }大抵はこれで十分なんですが、 プリフライトリクエストが発生する場面ではこれだけでは不十分でした。
プリフライトリクエストについてはこちら
https://developer.mozilla.org/ja/docs/Web/HTTP/CORS#Simple_requests
https://developer.mozilla.org/ja/docs/Web/HTTP/CORS#Preflighted_requestsプリフライトリクエストの場合は api Middleware が使用されない
どうやらプリフライトリクエストについてのルーティング定義は自動的に Laravel が作成するようです。
その場合は、Middleware の適用などが行われません。つまり
こんなルーティング定義を用意しておきます。
Route::get('sample', function () { echo 'sample api'; });URL や Middleware の適用はこんな状態です。
http://domain/api/sample にアクセスすると api Middleware グループが適用されます。$ php artisan route:list | grep 'sample' | | GET|HEAD | api/sample | front.api. | Closure | api |この状態で CORS となるようにブラウザの Console 上でこの API を実行してみます。
fetch('https://test.smartkidsacademy.jp/api/sample', {method: 'GET', headers: {'X-Requested-With': 'XMLHttpRequest'}}) .then(response => console.log(response)) .catch(response => console.error(response)) // --> // Access to fetch at 'https://dummy.jp/api/sample' from origin 'https://developer.mozilla.org' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.先程追加した Cors Middleware で設定しているはずの Access-Control-Allow-Origin が効いていません。
ブラウザの開発者ツールからこのときにリクエストの情報を見てみると
- プリフライトリクエストとして OPTIONS のリクエストが最初に飛ぶ
- その時のレスポンスヘッダーに Access-Control-Allow-Origin は含まれていない
である事がわかります。
OPTIONS に対応するルーティング定義は用意していない
php artisan route:list の結果からわかるように OPTIONS に対するルーティング定義は用意していません。
Laravel は対応していない HTTP リクエストメソッドに対しては 405 エラーを返しますが、そのエラーは発生していません。
このことから OPTIONS の場合は Laravel がプリフライトリクエストだからいい感じにレスポンスしてくれてると思われます。
ソースコードを grep してみたんですが、 OPTIONS ではいろいろな箇所がヒットして特定しきれなかったので諦めました。Laravel がいい感じにレスポンスしてくれるときは Middleware が効かない
URL 自体はルーティング定義にある api/sample なので、 api Middleware グループを適用してほしいところですが、そこまではやってくれないようです。
試しに App\Http\Middleware\Cors に全然関係ない echo や exit を埋め込んでも動作に変化はありませんでした。なので、レスポンスヘッダーに Access-Control-Allow-Origin が含まれることはありません。
対応方法
もうちょっとスマートな方法もあるきもしますが、ひとまず以下の方法で問題は解消できました。
- すべてのルーティングに Cors Middleware を適用する
- Cors Middleware 内で API Middleware グループを適用しようとしている URL であれば Access-Control-Allow-Origin をレスポンスヘッダーに含める
としました。
すべてのルーティングに Cors Middleware を適用する
App\Http\Kernel<?php namespace App\Http; use Illuminate\Foundation\Http\Kernel as HttpKernel; class Kernel extends HttpKernel { : protected $middleware = [ \App\Http\Middleware\TrustProxies::class, \App\Http\Middleware\CheckForMaintenanceMode::class, \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, \App\Http\Middleware\TrimStrings::class, \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, \App\Http\Middleware\Cors::class, // ★追加 ]; : }Cors Middleware 内で API Middleware グループを適用しようとしている URL であれば Access-Control-Allow-Origin をレスポンスヘッダーに含める
適用されている Middleware グループを取得できれば一番良かったんですが、どうにもうまく取れなかったので URL の一部から API であるかを判定するようにしています。
判定方法は実際の実装に合わせて柔軟に変更してください。App\Http\Middleware\Cors<?php namespace App\Http\Middleware; use Closure; class Cors { public function handle($request, Closure $next) { // すべてのレスポンスに CORS 用のヘッダーを追加する必要はないので URL から判断する $paths = explode('/', \Request::getPathInfo()); if ($paths[1] === 'api') { return $next($request) ->header('Access-Control-Allow-Origin', '*') ->header('Access-Control-Allow-Methods', 'GET, POST') ->header('Access-Control-Allow-Headers', 'Accept, X-Requested-With, Origin, Content-Type'); } return $next($request); } }再度 CORS となるようにブラウザの Console 上でこの API を実行してみる
今度はエラーが発生せず、正常に通信できるようになります。