あけましておめでとうございます
(´・ω・`)ハッ 年末年始多忙過ぎてブログのこと忘れてた…!
というのは冗談ですが忙しかったのは本当です。ところでブログというものは見られてなんぼが半分、知識の整理が半分だと思っているのですが、
Qiitaで記事を書くとLGTMがつかない記事でも500くらいの閲覧数がつくんですよね。どちらも無名なのですが、こちらは1記事10閲覧くらいです。
導線がTwitterくらいしかないのである程度は仕方ないと思いますが、やっぱりQiitaはすごいですね!
本題
就活のためアウトプットとインプットの再整理のためにこのブログを書いていましたが、 - Qiitaで記事を書きたくなったこと - 知識の再整理だけならQiitaの下書き機能で十分
ということから、暫くQiitaで記事を書いてみようと思います。
それでは!みなさん、また会う日まで!
【Docker】Dockerネットワークの落とし穴に(勝手に)嵌まった話
最近の活動
スタートアップのプロジェクトのミーティングやら資料やらの準備をしていたらブログを書く時間が...ない!
このブログは更新頻度はぼちぼちでいいから1年間は続けようと考えているので張り切って書いていきますよー!
axiosを使ってAPI通信できない問題
以前の記事で作った環境にて、NginxからLaravelのコンテナにcurlを飛ばすことができました。その際のコマンドは以下のような形、
$ curl http://laravel.test
じゃあaxios
を使ってVueからAPI通信できるな!ヨシッ(某猫並感)
そんなうまい話はありませんでした。
ポート番号を変えてみてもダメ...一体どうして...?となったので調べてみました!
コンテナ同士の見え方
どうやらコンテナ同士の見え方の差が問題だとわかりました!
この場合の見え方の差というのは、Dockerから見たコンテナとブラウザから見たコンテナの見え方の差です。
現在のDockerの構成を図解するとこんな感じ、緑の枠内全体が同じネットワークに設定されています。laravel.test
というコンテナ名でNginxからLaravelにアクセスできたことからも同一ネットワークに配置できていることがわかります。
一方で、ブラウザからDockerのコンテナ名であるlaravel.test
というアドレスはどう解釈されるのでしょうか?
繋がらないんですね。要するにDockerからコンテナ名でアクセスできても、それはDocker内だけの話であってホストのブラウザからは何も見えないわけです。
ここまで来たらaxios
で通信できなかった理由がわかるのではないでしょうか。そう、JavaScriptはブラウザに読み込まれてから実行されます。ブラウザから見れないものがJavaScriptからはアクセスできるはずがないというわけです。
解決法
簡単です。ブラウザから見てアクセスできるアドレスでリクエストを飛ばしてやればいいわけです。今回のLaravelサーバはDockerのlocalhost:80
でリッスンしているポートを3000ポートに転送しています。
つまり、localhost:3000
にリクエストを飛ばせばいいわけですね!とは言ってもポートが違うのでクロスオリジンアクセスを許可しないといけません。まずはその設定から。
プロジェクト名/config/cors.php
'paths' => ['api/*', 'sanctum/csrf-cookie'], 'allowed_methods' => ['*'], 'allowed_origins' => ['*'], 'allowed_origins_patterns' => [], 'allowed_headers' => ['*'], 'exposed_headers' => [], 'max_age' => 0, 'supports_credentials' => true, # 初期false -> trueに
ルートとコントローラの作成
HelloController
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; /** * API用サンプルコントローラ */ class HelloController extends Controller { public function index(){ return response()->json(['message' => 'Hello API!']); } }
/** * APIのサンプルプログラム */ Route::get('/HelloAPI', [HelloController::class, 'index']);
VueのAboutページを編集、Vueのサーバを立ち上げて/aboutにアクセス(※Aboutがない方は vue add router
を実行すると生成されます。)
<template> <div class="about"> <h1 id="message">{{ message }}</h1> </div> </template> <script> import axios from 'axios'; export default { data() { return { message: null } }, // ちゃんとlocalhost:3000にアクセス mounted () { axios .get('http://localhost:3000/api/HelloAPI') .then(response => (this.message = response.data.message)) } } </script>
ふー、これでAPIにアクセスできますね。次はログイン、行ってみますか!
【PHP】LaravelでささっとAPIを実装してみる
こんばんは、けこです。
今日はタイトル通り、LaravelでAPIを作ってみまーす。
特定のアドレスにリクエスト -> jsonが帰ってくるっていう流れですね。今日はとりあえずGETだけ実装して後々PUTやUPDATEも作っていきます。
環境は以前の記事の環境になります。
ルーティング
LaravelでAPIを作るには api.php
にルーティング情報を書く必要があります。
use App\Http\Controllers\HelloController; # ~~~略~~~ /** * APIのサンプルプログラム */ Route::get('/HelloAPI', [HelloController::class, 'index']);
併せて HelloController
を作成.
php artisan make:controller HelloController
中身を修正.
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; /** * API用サンプルコントローラ */ class HelloController extends Controller { public function index(){ return response()->json(['message' => 'Hello API!']); } }
いざ実行!
結構簡単にできました!Laravelはプログラムをシンプルに記述できるのが嬉しいところです。
WebだけでなくAPIもシンプルに記述することができました。
次はAPIを使った認証にチャレンジしてみます😉 それでは!
【Nginx】CSSが読み込まれない問題の解消
......Dockerで立てたNginxでCSSが反映されてない!何故だ!
以前の記事で立てたNginxのサーバにアクセスしたところ...
ビルドする前のvueのlocalでは動いているのでビルドのオプションが悪い説を提唱.
とりあえずキャッシュの削除
CSSが反映されない場合は大体キャッシュが悪い。Chromeの履歴からキャッシュの削除.
-> 変わらず
google先生で検索
見つかった解決策
1のこれは...本番環境だとoffにできないので却下.
2はnginx.confのhttp内に include /etc/nginx/mime.types;
を追記する方法、mime.typesの中身を見てみると...
# cat /etc/nginx/mime.types types { text/html html htm shtml; text/css css; text/xml xml; image/gif gif; image/jpeg jpeg jpg; application/javascript js; application/atom+xml atom; application/rss+xml rss; text/mathml mml; text/plain txt; text/vnd.sun.j2me.app-descriptor jad; text/vnd.wap.wml wml; text/x-component htc; image/avif avif; image/png png; image/svg+xml svg svgz; image/tiff tif tiff; ......................................................
どうやらmimeTypeと拡張子を相互に変換してくれる設定っぽい、これが読み込まれていなかったので.cssファイルを渡す方法がわからなかったと...どうして最初から設定されていないんだ???
command + Shift + R でスーパーリロード.
nginxの設定次第ではcssが読み込めないことがあるんですね...!また賢くなりました。
参考
【Docker】Vue + Nginxで作ったフロントエンド、Laravel + MySQLでバックエンドのコンテナ同士の連携
こんばんは、けこです。
今日はdocker composeを使った2つの環境の構築、そしてそれらの環境のネットワーク連携について調べました!
LaravelならフロントもDB接続もできるのにわざわざ環境を分ける必要があるのか?というところから解説していきたいと思います。
何故環境を分けるのか?
Gitでのコード管理が容易
スマホアプリを追加で作る際に転用できる
問題が起きた際に原因を特定しやすくなる
フロントエンドとバックエンドの環境を分けるメリットとして真っ先に上がるのはこれらの利点でしょうか、特に3の利点に関しては実運用で役立ちそうな予感がします。
Gitでのコード管理が容易
Laravelでフロントエンドとバックエンドを担当する場合、1つのリポジトリにフロントエンドとバックエンドが混在することになりどのコードを弄ったらいいかわからない...という状況が生まれることがあります。
もっとも、LaravelはMVCフレームワークなので他のフレームワークや言語を利用するという手もあります。APIだけの利用目的でもViewを返す代わりにJsonを返すプログラムを書くだけなのでとても簡単なのが嬉しいですね。
スマホアプリを追加で作る際に転用できる
最初にWebサービスを作ってから、軌道に乗ったらスマホアプリを作るというケースは少なからず存在します。
初めからAPIとしてバックエンドを独立させてSPAでフロントエンドを作っておけば、スマホアプリへの移行が簡単になります。
compose同士のネットワーク連携
本題に行きましょう、今回はVue+NginxのフロントエンドとLaravel+MySQLのバックエンドの連携にチャレンジしてみます。
2つのコンテナアプリケーションをdocker composeで立てて、それらを同じネットワークに配置できればいいわけですね。
composeを2つ用意
フロントエンド(参考:https://takake-blog.com/wsl-docker-vue-nginx/#Docker_compose)
version: "3.8" services: nginx: build: ./containers/nginx container_name: nginx ports: - '80:80' volumes: - ./vue_project:/var/www/html - ./containers/nginx/nginx.conf:/etc/nginx/nginx.conf vue-app: build: ./containers/vue_app container_name: vue-app ports: - '8080:8080' volumes: - ./vue_project:/app tty: true
バックエンド(参考:Laravel8公式)
# For more information: https://laravel.com/docs/sail version: '3' services: laravel.test: build: context: ./vendor/laravel/sail/runtimes/8.1 dockerfile: Dockerfile args: WWWGROUP: '${WWWGROUP}' image: sail-8.1/app extra_hosts: - 'host.docker.internal:host-gateway' ports: - '3000:80' environment: WWWUSER: '${WWWUSER}' LARAVEL_SAIL: 1 XDEBUG_MODE: '${SAIL_XDEBUG_MODE:-off}' XDEBUG_CONFIG: '${SAIL_XDEBUG_CONFIG:-client_host=host.docker.internal}' volumes: - '.:/var/www/html' networks: - sail depends_on: - mysql mysql: image: 'mysql/mysql-server:8.0' ports: - '${FORWARD_DB_PORT:-3306}:3306' environment: MYSQL_ROOT_PASSWORD: '${DB_PASSWORD}' MYSQL_ROOT_HOST: "%" MYSQL_DATABASE: '${DB_DATABASE}' MYSQL_USER: '${DB_USERNAME}' MYSQL_PASSWORD: '${DB_PASSWORD}' MYSQL_ALLOW_EMPTY_PASSWORD: 1 volumes: - 'sailmysql:/var/lib/mysql' networks: - sail healthcheck: test: ["CMD", "mysqladmin", "ping", "-p${DB_PASSWORD}"] retries: 3 timeout: 5s networks: sail: driver: bridge volumes: sailmysql: driver: local
よく見てみると、バックエンドのcomposeファイルにnetworksとの記述があります。同じようにフロントエンドにも記述してみましょう。
そしてnginxのコンテナにCLIで入ってcurl localhost:8080
networksを調べて再挑戦!
fmfm...ネットワークを合わせる必要があって、コンテナ名でアクセスできると。
そういえばdocker compose up -d
した際にネットワークが作られているような...?
composeファイルで指定したネットワークどおりにネットワークが生成されているとは限らない
docker network ls
コマンドで調べたところ、フォルダ名_ + ネットワーク名でネットワークが生成されるみたいです!
つまりフロントエンドの方をバックエンドのネットワーク名に合わせてやれば...
今日の学び
networks を使う際は目的のネットワーク名を先に調べておくこと
networksで同じ名前を指定しても目的のネットワーク名で生成されるとは限らないということ
コンテナと通信する際はホスト名にコンテナ名を使えるということ
以上!やはり基本的な情報を得るためには公式情報を見に行くに限る...!これでAPIを作った時にも通信できますね!
【PHP】Laravelにおけるテスト手順、勉強メモ
こんばんは、けこです。
今日は先日作ったsailによるLaravel環境のテストを試してみました!
php artisan
互換のコマンドがsailで使えるのはありがたい!せっかくなので今回はsailコマンドで進めていきます。
前提
docker基本知識、下記リンクのOS別Laravel導入を終えていること。
~/.zshrc にエイリアスを記載済み
alias sail="./vendor/bin/sail"
テスト実行
sail test
でプロジェクトのtestsフォルダ内のFeature, Unitフォルダにあるテストメソッドを実行可能。php artisan test
でも可。
testファイルの作り方
{プロジェクト名}/tests/Feature/UserTest.php
を作る場合、削除する場合は手動で対応しましょう。
sail artisan make:test UserTest
このようなコードが生成されるので、getメソッドの引数/
を/user
に変更します。
<?php namespace Tests\Feature; use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\WithFaker; use Tests\TestCase; class UserTest extends TestCase { /** * A basic feature test example. * * @return void */ public function test_example() { #$response = $this->get('/'); 削除 $response = $this->get('/user'); $response->assertStatus(200); } }
/userというルーティングは作られていないので失敗してしまいます。
ルーティングを加えて成功させる
/routes/web.php
に/userへのルーティングを追記、今回はルーティングのみの検証ということでviewは省略。
<?php use Illuminate\Support\Facades\Route; /* コメント略 */ Route::get('/', function () { return view('welcome'); }); Route::get('/user', function () { return 'user page'; });
再実行
sail test
無事成功、テストを作る時に必要なコーディングのほとんどを自動生成してくれるのでとても楽ですね!
最後
本日は以上となります、APIの値の検証やViewのテストなどもっと深掘りできると思うのでおいおい勉強してまとめていきます!
【PHP】Sailに出会いました
What is Sail?
~~~sailに出会うまでの経緯~~~
うーん、スタートアップ支援のためでLaravelを使うことになったけど環境どうしよう?Dockerで開発したいけどcomposerを入れてローカルに作るのが定石っぽい...うん、公式を見よう!
curl -s "https://laravel.build/example-app" | bash cd example-app ./vendor/bin/sail up
docker環境があればこのコマンドを使うだけで開発環境ができると…fmfm.
docker環境はあるのでサクッと実行!
なにやら沢山出てきましたがほとんどconfigファイルとLaravelのファイルの様子。docker-composeを実行してmysqlやらradisの環境をLaravelと一緒に作ってくれる感じ、とても便利。
もう少し調べてみる
mailhogは使わないし要らないやって場合は docker-compose.yml
の該当範囲をコメントアウト.
mysql等の初期パスワードや初期ユーザは環境変数を格納している .env
ファイルを触る.
と、これは開発環境だけでなくstg環境や本番環境を想定した作り!素晴らしい!
もうちょっと便利に
sailを ./vendor/bin/sail
と書き続けるのは面倒臭い...
alias sail="./vendor/bin/sail"
ということで、~/.zshrc
にエイリアスを追記。これでsailと打つだけで良くなった!
終わり
sail build
sail up
みたいな感じでdocker composeと同じコマンドを使えることがわかった。
とても便利だけどこれだとcomposeとあまり変わらないような...?と思っていたんですが、WWWGroup, WWWUserあたりの環境変数を補完してくれるっぽい。docker compose build --no-cache
で出ていたWWWGroupが無いというエラーがsail build --no-cache
では解消されていました。
もっと便利機能がある予感...また調べてみようとおもいます!では!