20211125のdockerに関する記事は7件です。

Docker Desktop + WSL2 + Laravel が遅いので高速化したい

はじめに 元々は Vagrant + Homestead 環境にて開発を行っていましたが Docker を使ってみたくなり環境を乗り換える事に Docker Desktop を導入し環境を構築するところまでは良かったのだが Homestead の時と比べて明らかに遅かった為、高速化するまでのお話 環境 Docker Desktop WSL 2 Laravel Vue3 想定読者 docker 導入したけど、なんか遅くない?と思っているピンポイントの人向け docker 導入については、私自身参考にさせて頂いた記事を残しておきます どんなシステム構成なのか フロントが Vue3 でバックエンドに Laravel を使用している、何の変哲もない構成 フロント及びバックエンドは、同一サーバ上に配置 Vagrant から Docker への乗り換え Windows10 Home でも Docker が使える事を知り、ノリで乗り換えを決意 詳しい手順等については以下を参考にさせて頂きました ありがとうございます 高速化に向けて ブラウザの開発者ツールにて確認したところ、画面表示完了まで 3 ~ 4 秒掛かっており明らかに遅くなっている 元々は 0.2 秒ほどだったため、10 倍以上遅くなっている なぜ遅いのか? 色々調べているうちに似たような悩みを抱えている人がおり、解決している様に見える そこでの原因として Windows(ホスト) と Linux の OS ファイルシステム間でのファイルの読み込みが遅い どういう事なのか Windows と Linux では HDD のフォーマット形式が違い、その違う環境同士でファイルのやり取りを行うと時間が掛かる という事からくりでした なんでそんなことになるのか Windows(ホスト)の C ドライブのファイルは WSL 上の「/mnt/c/」等にマウントされます なので、特に意識せずに C:\work この様な Path にて docker を起動すると /mnt/c/work のファイルを WSL が読みに行ってしまい、時間が掛かってしまいます どう解決するのか 色々な記事に記載されいる解決策として /mnt/以外に置く ¥¥wsl$Ubuntu¥home¥ に置く という解決策があるのですが、知識が浅い私は で、どうしたらいいの? と結局解決に至らずもやもや 高速化しよう ベストプラクティスなのかは分からないが早くはなりました Ubuntu 導入 Microsoft Store から「Ubuntu 20.04 LTS」をインストール ※多分 Ubuntu じゃなくても良いと思います コマンドでも導入する事が出来そうですが、今回は Store からインストールしました \\wsl$ エクスプローラーで表示すると、Ubuntu が追加されているかと思います ※私の場合は、「Ubuntu-20.04」でした プロジェクト配置場所の変更 今回は以下ディレクトリへ配置することにします \wsl$\Ubuntu-20.04\home 先ほど追加された、Ubuntu を開きプロジェクトを配置 いざ docker 起動 Ubuntu のターミナルを起動し docker compose build docker compose up -d ブラウザからアクセスし起動確認 ・・・早くなってるはず! docker コマンドがエラー ① The command 'docker' could not be found in this WSL 1 distro. We recommend to convert this distro to WSL 2 and activate the WSL integration in Docker Desktop setting WSL バージョンが 1 の為、バージョンアップしましょう $ wsl -l -v NAME STATE VERSION * Ubuntu-20.04 Running 1 $ wsl --set-version Ubuntu-20.04 2 docker コマンドがエラー ② The command 'docker' could not be found in this WSL 2 distro. We recommend to activate the WSL integration in Docker Desktop settings. Docker Desktop > 設定 > Resources > WSL INTEGRATION にて「Ubuntu-20.04」のトグルを有効化する 早くなったのはいいけど、別の問題が 編集、ビルド出来ない? 私は VSCode にて作業をしているのですが、wsl 上にプロジェクトを配置したため 何やら、ファイルの編集やビルドが出来ない。。。 VSCode の Extention を導入にて解消しました VSCode を起動する際は、ubuntu のターミナルにて開きたいディレクトリへ移動後 code . にて起動 ※VSCode 上からも起動可能な為、どちらでも良いです VSCode の拡張が消えた? 消えたわけではなく、Local と WSL 上では別管理の様です VSCode の Extentions タブを開くと WSL UBUNTU - INSTALLED が空っぽの為、Local と同じ Extention で良ければ、Install Local Extensions in 'Remote'... (雲のアイコン)にて、適用出来ました ビルドについて 以前までは、VSCode の terminal にて「npm run watch」でビルドしていましたが、コマンドが通りません ubuntu のターミナルにて「npm run watch」を実行しておき VSCode 上での更新を検知して build が走る事を確認 ブラウザを更新し、変更内容が適用されている事を確認して完了 おわりに もうちょっといいやり方あるんじゃないかと思っているが、現状方法が分からない為一旦これで進めようと思う 違うやり方や効率的な方法があれば教えてもらえると嬉しいです お世話になった記事 ありがとうございます! Docker 導入編 高速化編 ubuntu 開発環境
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

dockerネットワークについて調べる〜bridgeの仕組み編

今回のお題 今回はdockerネットワークの一つであるbridgeの仕組みについてまとめます。 前回の記事でdockerのネットワークには3種類あるという話をしました。 本記事ではその中でも最も使用頻度の高いbridgeというネットワークの仕組みについて話します。 以下で説明する内容については、コンテナ作成時に自動で設定されるものになります。 手動で実行する方法についても別途取り上げる予定ですが、実際に使用する機会は少ないかもしれません。 目次 ネットワーク内のコンテナ同士での通信の仕組み コンテナとホストOSの通信の仕組み コンテナと外部インターネットとの通信の仕組み ネットワーク内のコンテナ同士での通信の仕組み ネットワーク内のコンテナ同士での通信は、仮想スイッチと呼ばれる中継地点によって実現している。 すなわち、コンテナ同士で通信する場合には両者の間を直接情報が行き来するのではなく、一度仮想スイッチを経由して情報がやりとりされることになる。 このような通信方式は、内部的には仮想NICと呼ばれる存在によって実現している。 具体的にいうと、コンテナと仮想スイッチはそれぞれ仮想NICと呼ばれる窓口を持ち、これらを出入り口として情報のやり取りが行われている。 コンテナとホストOSの通信の仕組み コンテナとホストOSの間での通信も基本的な仕組みは変わらない。 ホストOSは仮想NICの代わりに物理NICと呼ばれるNICを持っているのでそれを仮想スイッチと接続することで通信を成立させている。 コンテナと外部インターネットとの通信の仕組み コンテナから外部インターネットに対してリクエストを送信する場合、発信元IPアドレスおよび宛先IPアドレスは以下のようになる。 宛先 = リクエスト先のグローバルIPアドレス 発信元 = コンテナのプライベートIPアドレス このような場合には、以下の2つの問題を抱えることになる。 上記の情報だけでは、仮想スイッチが転送先を判断することができない 上記の宛先IPアドレスは仮想スイッチの属するサブネット内のものではないので、IPアドレスを解釈することができない リクエストの受け手が宛先を解釈できない リクエストの受取手はグローバルIPアドレスなら理解できるが、上記の情報では発信元IPがプライベートアドレスになっており解釈できない つまり、プライベートIPとグローバルIPが混在していることによって、仮想スイッチでもリクエスト先でも解釈できない状態になってしまっている。 bridgeではこの状況をデフォルトゲートウェイとNATによって解決している。 デフォルトゲートウェイとは仮想スイッチが受け取った送信先が同一サブネット内ではない(=仮想スイッチが解釈できない)IPアドレスであった場合のデフォルトの送信先である。 これをホストOSの物理NICのIPアドレスにすることによって、グローバルIPへのリクエストをホストOSへ転送することが可能になる。 NATとはNetwork Address Transferの略であり、プライベートIPとグローバルIPを変換する技術を指す。 コンテナから外部へリクエストが送られる場合には、ホストOSの物理NICをまたぐ際に送信元のアドレスがプライベートIPからグローバルIPに変換されることで、リクエストの受け手が発信元を解釈できるようにしている。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Docker上でのStreamlitの使用方法【Windows 10】

はじめに Windows環境で、数値計算の環境の事情(例えばcvxpyとか環境構築がめんどっちいとかの事情があります)からLinuxを使用したいことがあります。そのような場合、Dockerを用いるかと思います。しかしながら、streamlitをDockerのコンテナで実行した際、Webブラウザの見方があまり記事としてなかったので拙いながらもまとめてみます。 環境 Windows 10 Docker for Windows Python streamlit コンテナの作成 下記のコマンドを実行しコンテナを作成する。 $ docker run -it -p 8501:8501 -v <パス>:/home/jovyan/work --name unko jupyter/datascience-notebook /bin/bash Streamlitの実行 試しに下記のPythonファイルを実行することを考えます。 import streamlit as st st.title("Hello World !") ターミナルでPythonファイルを実行してみます。 $ pip install streamlit $ python -m streamlit run hello.py すると下記の結果が得られるかと思います。 それではブラウザで結果を表示してみましょう。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

dockerネットワークについて調べる〜ネットワークの種類

今回のお題 前回はdocker-composeを用いて複数のコンテナを同時に作成しましたが、その結果それらの間でも通信ができるようになりました。 これはコンテナ同士がdockerネットワークという同一の入れ物に入っているからであり、docker-composeを用いることでコンテナの作成だけでなくネットワークの整備までもが自動で進むのがdocker-composeのメリットだと言われています。 と、偉そうに言いましたが、docker-composeが自動でやってくれたおかげで私自身dockerネットワークについてはほとんどわかっていません。 ですので、それらについて自分なりに調べた内容をここにメモしておこうと思います。 復習〜Dockerネットワークとは 複数のコンテナを連携させるための箱のようなもの。 ほとんどのサービスは複数のコンテナを利用することで成り立っているため、コンテナ同士での通信が必要になる。 コンテナ同士を同一のネットワークに所属させることでそれらの間での通信が容易になり、結果的にサービスの構築が簡単になる。 Dockerネットワークの種類 Dockerネットワークには大きく分けて3つのタイプがあり、それぞれbridge, host, null(none)と呼ばれる。 この分類は、ネットワーク内のコンテナがホストOSの外部とどのようにして通信するのかによって行われている。 ネットワークの種類がnull(none)の場合、コンテナは外部と通信できない。 hostにおいては、ネットワークに所属するコンテナはホストOSのプライベートIPアドレスを使って通信することになる。 bridgeにおいてはコンテナごとにホストOSとは別のIPアドレスが割り当てられ、ホストOSとコンテナのIPアドレスを仮想スイッチと呼ばれる装置が中継(bridge)することで通信が成立している。 作成されたコンテナのネットワーク設定 Dockerはデフォルトで3つのネットワークを保有しており、それぞれのネットワーク名やネットワークタイプについては以下のようになっている。 # 作成済みのネットワークを一覧表示 % docker network ls NETWORK ID NAME DRIVER SCOPE 59c6a0c60086 bridge bridge local efba6f694b6f host host local a0d4f5e885f9 none null local docker runコマンドで作成されたコンテナについては基本的には上記のbridgeに所属するが、--netオプションを付けることで所属するコンテナの指定が可能。 # これだとbridgeに所属 % docker run -it -d centos:centos7 # hostを指定 % docker run -it -d --net=host centos:centos7 # noneを指定 % docker run -it -d --net=none centos:centos7 また、docker-compose upコマンドを用いてコンテナを作成した場合にはxxxx_defaultという名前のネットワークが新しく作られるが、この際も特に指定がなければdriverはbridgeになる。 また、デフォルトのbridgeであっても新規作成されたbridgeネットワークであっても、コンテナ作成時に自動的にIPアドレスが付与される。 終わりに 長くなってしまったので一旦ここまでにします。 次回はbridgeの仕組みについてまとめる予定です。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

モダンフロントとLaravelでCRUD処理をやってみる

はじめに 【マイスター・ギルド】本物の Advent Calendar 2021の4日目の記事です。 他にもROCKな記事ばっかりなので要チェック!!! 本記事は筆者が以下の2つの記事を自身の学習用にまとめたものです。 大変参考にさせていただきました。ありがとうございます。 『Laravel CRUD』 『LaravelでCRUD』 モダンフロントとLaravelの組み合わせを想定しているので、bladeは使いません。 フロント部分についてはコードは載せますが、詳細は触れません。 Laravel側へリクエスト投げていれば何でも大丈夫です。今回はReactとaxiosを用います。 執筆の経緯 LaravelでCRUDをやってみたいが、bladeを使っている記事ばかり。 モダンフロントとLaravelの記事が少ない・・・。 なかったら作れ!(ハック精神) 想定読者 前回の記事で環境構築された方。 記事の通りに環境構築された場合はバージョンは以下になっているはず。 PHP : 7.3.32 Composer : 2.0.14 Laravel : 6.20.41 Laravel初心者の方。 LaravelおよびMVCモデルの基礎について簡単に理解している前提で話を進めます。 今回のゴール 簡単なCRUD処理を実装する。 タスク管理アプリを作る。 実行環境 PC : MacBookAir(M1, 2020) OS : macOS Big Sur11.4 チップ : Apple M1 メモリ : 16GB DockerDesktop : 3.5.2 Docker : 20.10.7 目次 何を作るか Laravelの前準備 処理のイメージ Controllerを作成する。 web.phpを編集し、ルーティングを設定する。 .envを編集する Modelおよびmigrationを作成し、テーブルを作成する Seederを作成して実行し、サンプルレコードを作成する フロントエンドの完成形 【要件1の実装】データベースからレコードを読み込む(Read) 【要件2の実装】データベースへレコードを挿入する(Create) 【要件3の実装】データベースの情報を更新する(Update) 【要件4の実装】データベースの情報を削除する(Delete) リポジトリ 何を作るか 簡単なタスク管理アプリを作成します。簡単な要件は以下の通り。 【要件1】ページ遷移時にデータベースから既存のタスクがfetchされている。 【要件2】タスクを追加することができる。 【要件3】「変更する」ボタンを押下すると状況が「作業中」と「完了」のトグルで入れ替わる。 【要件4】「削除する」ボタンを押下するとタスクが削除される。もちろんDBからも消えている。 Laravelの前準備 Laravelの処理の簡単なイメージ とりあえずModel、View、Controller、Route、DBが分かっていればOK。小売店と卸問屋で例えてみましょう。 View ブラウザ株式会社という小売店のスタッフ。お客さんに画面という情報を提供している。 今回はここがbladeじゃなくてReact。 Route サーバー株式会社という卸問屋の電話番。 Controller サーバー株式会社の営業マン。 Model サーバー株式会社の在庫管理の部署。 DB サーバー株式会社の倉庫。 イメージ Viewから商品問い合わせの電話が入った。 Routeが電話を受けて、担当営業マンのControllerに繋ぐ。 ControllerがModelへ在庫を確認。 ModelはDBへ在庫を確認、Viewへ発送する。 ControllerがViewへ納期を伝える。 イメージ違ってたらご指摘いただけると幸いです。 Controllerを作成する。 Controllerを作成する 中身は後ほど実装するので、とりあえず作成だけしておく。 backendコンテナの中 php artisan make:controller TodoController web.phpを編集し、ルーティングを設定する。 以下の通り設定。 これでpublic/fetch_todosにgetメソッドでリクエストが来たら、TodoControllerのfetchTodosメソッドを実行するよう設定ができている。 前述の通りcontrollerの中身は後ほど実装します。 routes/web.php Route::get('fetch_todos', 'TodoController@fetchTodos'); .envファイルを編集する Laravelプロジェクト直下にある.envファイルを以下の通り修正。 dockerは各コンテナ間のネットワークも自動で作成をしてくれている。 そのためLaravel(backendコンテナ)からMySQL(dbコンテナ)へサービス名でアクセスできるようになっている。 つまり「DB_HOST」の値は「db」でOK。 .env(一部抜粋) DB_CONNECTION=mysql // dockerで環境構築した場合は、docker-compose.ymlデータベースのコンテナのサービス名を入力する。 DB_HOST=db DB_PORT=3306 // 任意のデータベース名。先にDBコンテナに入ってデータベースだけは作成しておくこと。 DB_DATABASE=tasuku // rootユーザーは初期設定で存在しているので、このままでOK。 DB_USERNAME=root // docker-compose.ymlで設定したパスワードを入力。 DB_PASSWORD=pass Modelおよびmigrationを作成し、テーブルを作成する modelファイルとmigrationファイルを作成する migrationファイルとは簡易に書け、なおかつ複数実行可能なSQL文の集まりのようなものです。 -mオプションをつけることで、modelと一緒にmigrationも作成されます。 今回はタスクを格納するtodosテーブルのみ作成します。 model名は単数形にすること。(migrationファイルは複数形名で自動生成されている) ってことはmodelはきっとテーブルの各レコードってことなんだろうか。 backendコンテナ内 php artisan make:model Models/Todo -m migrationファイルを編集 ->nullable(false)のような書き方をすることで、該当のカラムにオプションを付与します。 私はいつも頭の中でSQLを思い浮かべてからどう書くのか検索したりしてます。 database/migrations/(作成時の日時)_create_todos_table.php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateTodosTable extends Migration { public function up() { Schema::create('todos', function (Blueprint $table) { $table->bigIncrements('id'); $table->string('name', 255)->nullable(false); $table->string('status', 255)->nullable(false); $table->timestamps(); }); } public function down() { Schema::dropIfExists('todos'); } } migrationを実行 事前にdbコンテナ内で.envで指定したデータベースを作成しておかないとエラーになるので注意。 実行したらdbコンテナ内でテーブルができているか確認。 SQLポチポチ叩かなくて良いので便利! backendコンテナ内 php artisan migrate Seederを作成して実行し、サンプルレコードを作成する Seederファイルを作成する Seederファイルとはサンプルのデータを作成できるファイル。 さっきのmigrationがcreate table文の簡易版とすると、seederはinsert文の簡易版。 backendコンテナ内 php artisan make:seeder TodosTableSeeder Seederファイルを編集 適当にファイルを作成する。 id,created_at,updated_atはSeederには入力不要。 初期だとDBがimportされていないので、追記すること。 database/seeds/TodosTableSeeder.php use Illuminate\Support\Facades\DB; use Illuminate\Database\Seeder; class TodosTableSeeder extends Seeder { public function run() { DB::table('todos')->insert( [ [ 'name' => '買い物', 'status' => '作業中' ], [ 'name' => '料理', 'status' => '作業中' ], [ 'name' => '洗濯', 'status' => '作業中' ] ] ); } } DatabaseSeederへの登録 後述のseedコマンドを実行すると、このファイルが実行される。 つまりこのファイルに先ほど作成したSeederを記載しないと意味なし。 database/seeds/DatabaseSeeder.php use Illuminate\Database\Seeder; class DatabaseSeeder extends Seeder { /** * Seed the application's database. * * @return void */ public function run() { $this->call(TodosTableSeeder::class); } } Seederファイルの実行 dbコンテナにデータが入っていることを確認。 backendコンテナ内 php artisan db:seed フロントエンドの完成形 一部抜粋です。完成系は本記事の終わりのgithub参照。何やっているか雰囲気だけ掴んでもらえれば。 Reactで書いてますが、画面表示時にLaravelへgetメソッド投げれたら何でも良いです。 Vue.jsの場合はcreated()にfetchTodosメソッド、それ以外のメソッドはv-onで制御すればOKかと思います。 バニラJSの場合はaddEventListener駆使してください。 Main.tsx import { useState, useEffect, ChangeEvent } from 'react' import { client, postMethod } from './lib/axios' import { createURLSearchParams } from './utils' interface TodoType { id: string name: string status: string } const WORK_IN_PROGRESS = '作業中' const DONE = '完了' export const Main = () => { const [todos, setTodos] = useState<TodoType[]>([]) const [todoName, setTodoName] = useState('') const bindTodoNameValue = (event: ChangeEvent<HTMLInputElement>) => { setTodoName(event.target.value) } // 要件1 const fetchTodos = async () => { const { data } = await client.get<TodoType[]>('/fetch_todos') setTodos(data) } useEffect(() => { fetchTodos() }, []) // 要件2 const pushTodo = () => { const params = createURLSearchParams<TodoType>([ ['name', todoName], ['status', WORK_IN_PROGRESS], ]) postMethod('push_todo', params).then((_response) => fetchTodos()) } // 要件3 const changeStatus = (id: string, status: string) => { const statusParam = status === WORK_IN_PROGRESS ? DONE : WORK_IN_PROGRESS const params = createURLSearchParams<TodoType>([ ['id', id], ['status', statusParam], ]) postMethod('change_status', params).then((_response) => fetchTodos()) } // 要件4 const deleteTodo = (id: string) => { const params = createURLSearchParams<TodoType>([['id', id]]) postMethod('delete_todo', params).then((_response) => fetchTodos()) } return ( <> <p>タスクを追加する</p> <input onChange={bindTodoNameValue} type="text" /> <button onClick={pushTodo}>追加する</button> <ul> {todos.length > 0 && todos.map(({ id, name, status }, index) => { return ( <li key={id}> <p>Index:{index + 1}</p> <p>タスク名:{name}</p> <p>状況:{status}</p> <button onClick={() => changeStatus(id, status)}> 変更する </button> <button onClick={() => deleteTodo(id)}>削除する</button> </li> ) })} </ul> </> ) } 【要件1の実装】データベースからレコードを読み込む(Read) 処理が簡単なので、まずはReadからやります。 TodoControllerを以下の通り実装。 header("Access-Control-Allow-Origin: *")を付けないとCSRFのエラーが出ます。 簡単に言うと「違うドメインから通信来ても受け入れるよ」という設定です。 本来はちゃんとした設定をしないといけないんですが、今回は省略します。 migrationの時と似たような書き方でselect文を書いているイメージです。 json形式に変換してレスポンスを返します。 Todo::select()のようにModelを利用してDBへアクセスしていますが、DBから直接取ってくる実装方法もあります。 役割を考えると、Modelを利用するべきではと考えています。 TodoController.php namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; class TodoController extends Controller { public function fetchTodos() { header("Access-Control-Allow-Origin: *"); $todos = Todo::select('id' ,'name', 'status')->get(); return json_decode($todos); } } 画面をリロードしてみて、きちんとfetchできているか確認。 Chromeのdeveloperツールでも確認。200番返ってきてますね。 【要件2の実装】データベースへレコードを挿入する(Create) web.phpを編集してルーティングを追加 クライアント側から情報を受け取る時は大事な情報が入っている場合もあるでしょうから、post通信にします。 ちなみにそのままaxiosでLaravelにPOSTすると、エラーコード419が返ってきます。 これはCSRFトークンが埋め込まれていないためのエラーです。 app/Http/Kernel.phpの$middlewareGroupsの\App\Http\Middleware\VerifyCsrfToken::classをコメントアウトすれば一旦解決。 根本解決するにはリクエスト内にCSRFトークンを埋め込む必要がある。(勉強中) bladeを使用する場合はとても簡単に解決可能ですが、Laravelでフロント作る気になれなかったので今回は割愛。 routes/web.php <?php Route::get('fetch_todos', 'TodoController@fetchTodos'); // 追加 Route::post('push_todo', 'TodoController@pushTodos'); TodoControllerを以下の通り実装 フロント側から受け取った情報は$request内に格納されている。 $todo = new Todo()でModelの新しい営業担当を呼び出したイメージ。 $requst->input('name')はバニラPHPで言えば、$_POST['name']というところ。 $todo->save()でDBに格納できる。 TodoController.php <?php namespace App\Http\Controllers; // 追加 use App\Models\Todo; use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; class TodoController extends Controller { public function fetchTodos() { header("Access-Control-Allow-Origin: *"); $todos = Todo::select('id' ,'name', 'status')->get(); return json_decode($todos); }   //追加 public function pushTodo(Request $request) { header("Access-Control-Allow-Origin: *"); $todo = new Todo(); $todo->name = $request->input('name'); $todo->status = $request->input('status'); $todo->save(); } } フロント側から適当にタスクを追加する。 200番が返ってきていることを確認。Laravel側で何も返していないので、dataは空でOK。 リロードしても今追加したタスクが消えないことを確認。 【要件3の実装】データベースの情報を更新する(Update) web.phpを編集してルーティングを追加 routes/web.php <?php Route::get('fetch_todos', 'TodoController@fetchTodos'); Route::post('push_todo', 'TodoController@pushTodo'); // 追加 Route::post('change_status', 'TodoController@changeStatus'); TodoControllerを以下の通り実装 $id = (int) $request->input('id')でフロント側からきているidはstring型なので、int型へ型キャスト。 $todo = Todo::find($id)でTodoModelへ「$idを満たすレコードを頂戴」と言っている。 今回はstatusだけを変更したいので、上書きして保存。 TodoController.php <?php namespace App\Http\Controllers; use App\Models\Todo; use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; class TodoController extends Controller { public function fetchTodos() { header("Access-Control-Allow-Origin: *"); $todos = Todo::select('id' ,'name', 'status')->get(); return json_decode($todos); } public function pushTodo(Request $request) { header("Access-Control-Allow-Origin: *"); $todo = new Todo(); $todo->name = $request->input('name'); $todo->status = $request->input('status'); $todo->save(); } // 追加 public function changeStatus(Request $request) { header("Access-Control-Allow-Origin: *"); $id = (int) $request->input('id'); $todo = Todo::find($id); $todo->status = $request->input('status'); $todo->save(); } } フロント側で「変更ボタン」を押下して、「状況」が変わることを確認。 200番が出ていることも確認。 リロードしても「状況」が「完了」のままだと確認。 【要件4の実装】データベースの情報を削除する(Delete) web.phpを編集してルーティングを追加 routes/web.php <?php Route::get('fetch_todos', 'TodoController@fetchTodos'); Route::post('push_todo', 'TodoController@pushTodo'); Route::post('change_status', 'TodoController@changeStatus'); // 追加 Route::post('delete_todo', 'TodoController@deleteTodo'); TodoControllerを以下の通り実装 delete()でレコード削除。 TodoController.php <?php namespace App\Http\Controllers; use App\Models\Todo; use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; class TodoController extends Controller { public function fetchTodos() { header("Access-Control-Allow-Origin: *"); $todos = Todo::select('id' ,'name', 'status')->get(); return json_decode($todos); } public function pushTodo(Request $request) { header("Access-Control-Allow-Origin: *"); $todo = new Todo(); $todo->name = $request->input('name'); $todo->status = $request->input('status'); $todo->save(); } public function changeStatus(Request $request) { header("Access-Control-Allow-Origin: *"); $id = (int) $request->input('id'); $todo = Todo::find($id); $todo->status = $request->input('status'); $todo->save(); } // 追加 public function deleteTodo(Request $request) { header("Access-Control-Allow-Origin: *"); $id = (int) $request->input('id'); $todo = Todo::find($id); $todo->delete(); } } フロント側から適当にタスクを削除。 今回は「買い物」を削除してみた。 200番が返ってくることを確認。 リポジトリ https://github.com/chillout2san/laravel_crud パイセンがガッツリレビューしてくれてプルリクまで出してくれました。ギザ優しす。 そんなパイセンのアドカレ記事はこちらです→FastAPI + Reactでフルスタックアプリを作成する 終わりに 今までfirebaseしか触ったことがなかったので、バックエンド触るのは新鮮だった。 API組むの楽しすぎてハマりそう。 だがやっぱりbladeは好きになれなかった。 Laravelはドキュメントが非常に充実していてありがたい。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

NuxtとRailsで構築したアプリにローカルでスマホからアクセスする

はじめに NuxtとRails APIで開発してる時にスマホで動作確認したい時ありますよね。 わざわざステージング環境にデプロイして動作確認するのは一手間。 そこでローカルでスマホからアクセスして動作確認する方法をメモしておきます。 Dockerを使って環境構築しており、PCとスマホを同じWiFiに接続していることが前提です。 僕はMacとiPhoneを利用するので端末がこれらと異なる場合はご自身で対応してください。 注意事項 同じネットワークを利用している端末だったらアクセスできてしまうため、カフェなどFree Wi-Fiなどでは避けること。 設定していく 1.IPアドレスを確認する システム環境設定→ネットワークを開きます。 すると以下の画像の青線のようにプライベートIPアドレスがわかるのでコピーしておきましょう。 この例では192.168.11.9です。 2.Nuxtの設定 package.jsonの"dev": "nuxt"以下に変更します。 僕は8080番ポートを使っているのでご自身のポート番号に置き換えてください。 IPアドレスも先ほどメモしたご自身のものに置き換えましょう。 package.json "scripts": { "dev": "NUXT_HOST=192.168.11.9 NUXT_PORT=8080 nuxt" } 続いてaxiosの設定です。 僕の場合はbaseURLがlocalhostになっています。 このままだとスマホでアクセスしてRails側にリクエストを投げる際、スマホ自身の3000番ポートを参照してしまいます。 なので先ほどメモしたIPアドレスとRails側のポート番号に変更します。 僕はRailsのデフォルトである3000番ポートを使っていますが、ご自身のものに置き換えてください。 front/plugins/axios.js //削除 config.baseURL = 'http://localhost:3000' //追加 config.baseURL = 'http://192.168.11.9:3000' 3.Railsの設定 corsでhttp://192.168.11.9:8080を許可します。 corsの設定は他にもやり方もあるので下記通りではうまくいかないかもしれませんが、許可するオリジンにhttp://192.168.11.9:8080を追加すればOKです。 development.rb # 削除 config.allow_origins = ['http://localhost:8080'] # 追加 config.allow_origins = ['http://localhost:8080', 'http://192.168.11.9:8080'] これでhttp://192.168.11.9:8080(自分のIPアドレスとポート番号に変更する)にスマホでアクセスできると思います。 動作確認が終わったらファイルの変更を元に戻しましょう。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

DockerfileにおけるCMDとRUNの挙動

はじめに Dockerfileを書く際に、CMDとRUNの挙動について調べたので、そのことについてまとめていく。 CMD CMD の主な目的は、コンテナ実行時のデフォルト(初期設定)を指定するためですと公式ドキュメントにあるように、CMDはコンテナが作成されるときに実行される。 ということは、イメージを作成するビルド時に実行されないと思われるので試してみた。 試してみた Dockerfileの最後にCMDでWebサーバーを起動するコマンドを書いた際の挙動をみてみる。 以下、Dockerfileのみ抜粋。 他の構成ファイルはGithubを参照。 FROM node:12.22.1-alpine WORKDIR /app COPY ./src/package.json ./src/yarn.lock ./src/server.js ./ RUN yarn install # コンテナ作成後にコマンド実行 CMD [ "node", "server.js" ] 1.Dockerfileをビルド ビルドしただけなので、CMDのコマンドは実行されず、何も表示されない。 2.コンテナを起動 画面が表示される。 結果 Webサーバーが起動していることから、コンテナ作成時にCMDで書いたコマンド[ "node", "server.js" ]が実行されたことが分かる。 RUN RUN 命令は、現在のイメージよりも上にある新しいレイヤでコマンドを実行し、その結果を コミット(確定)commit しますと公式ドキュメントにあるように、RUNはビルド時に実行される。 ということは、ビルド時に実行されると思われるので試してみた。 試してみた Dockerfileの最後にRUNでWebサーバーを起動するコマンドを書いた際の挙動をみてみる。 以下、Dockerfileのみ抜粋。 他の構成ファイルはGithubを参照。 ※Dockerfileの最後は以下のように変更すること。 FROM node:12.22.1-alpine WORKDIR /app COPY ./src/package.json ./src/yarn.lock ./src/server.js ./ RUN yarn install # ビルド後にコマンド実行 RUN node server.js 1.Dockerfileをビルド node server.jsが実行されているのがみえる。 結果 イメージのビルド時にRUNで書いたコマンドnode server.jsが実行されていることが分かった。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む