スマレジのテックファーム(SES 部門)で Web 系エンジニアとして働いている やまて(@r_yamate) と申します。
2023 年 4 月からは、スマレジの関連アプリの開発業務を担当しています。触ったことのなかった Flutter での開発を担当(React も少々)することになり、日々奮闘中です。開発しているアプリはモニター利用も始まり、開発の醍醐味を味わえていて楽しいです。
はじめに
今回は Laravel 10 と React 18 の SPA の開発環境を、ucan-lab/docker-laravel を用いて構築します。
前回は、Laravel Sail を活用して構築する手順について投稿しましたが、自身が何度か利用したことがあって使い慣れている ucan-lab/docker-laravel で React を導入したいと思い、その方法も試してみます。
目次
環境
- macOS Monterey v12.6.5 (MacBook Pro 2016)
$ git --version git version 2.33.0 $ docker --version Docker version 20.10.22, build 3a2c30b $ docker compose version Docker Compose version v2.15.1
バックエンド
- Laravel 10(Vite)
- MySQL 8
フロントエンド
- React 18
- Sass
- TypeScript
ucan-lab/docker-laravel
ucan-lab/docker-laravel は「Docker, Docker Compose を使って、nginx, php-fpm, MySQLの実行環境(LEMP)を構築して、最強のLaravel開発環境」を用意できるリポジトリです。
2 年前にポートフォリオとしての Web アプリを作ったときも活用させていただきましたが、とても使いやすいのでオススメです。
ただ更新がマメに実施されるため、2年前とも使い方が結構変わっているようです。(その変更を確認することも、参考になってとても良いです)
1. Laravel の開発環境構築
Laravel の開発環境を構築します。
※ Docker Desktop が必要です。
ターミナルを開き、任意のディレクトリに移動し、 git clone
コマンドを実行します。
git clone https://github.com/ucan-lab/docker-laravel.git sample-app
プロジェクトルートに移動します。
cd sample-app
# r_yamate @ mbp in ~/development [9:29:05] $ git clone https://github.com/ucan-lab/docker-laravel.git sample-app Cloning into 'sample-app'... remote: Enumerating objects: 689, done. remote: Counting objects: 100% (232/232), done. remote: Compressing objects: 100% (108/108), done. remote: Total 689 (delta 134), reused 174 (delta 107), pack-reused 457 Receiving objects: 100% (689/689), 460.05 KiB | 5.35 MiB/s, done. Resolving deltas: 100% (345/345), done. # r_yamate @ mbp in ~/development [9:30:34] $ cd sample-app
docker-laravel の README.md のとおり、以下の make
コマンドを実行して、Laravel の開発環境を構築します。
make create-project
コマンド実行時ログ
# r_yamate @ mbp in ~/development/sample-app on git:main o [9:31:39] $ make create-project mkdir -p src docker compose build [+] Building 0.0s (0/0) [+] Building 0.0s (0/0) [+] Building 0.1s (0/1) => [internal] load build definition from Dockerfile 0.1s [+] Building 0.2s (1/2) => [internal] load build definition from Dockerfile 0.2s [+] Building 0.3s (2/2) => [internal] load build definition from Dockerfile 0.2s [+] Building 0.4s (5/5) => [internal] load build definition from Dockerfile 0.2s [+] Building 0.5s (6/6) FINISHED => [internal] load build definition from Dockerfile 0.2s => => transferring dockerfile: 151B 0.0s => [internal] load .dockerignore 0.1s => => transferring context: 561B 0.0s => [internal] load metadata for docker.io/mysql/mysql-server:8.0 0.0s => [1/2] FROM docker.io/mysql/mysql-server:8.0 0.0s [+] Building 0.4s (2/3) [+] Building 5.4s (4/7) => [internal] load build definition from Dockerfile 0.1s => => transferring dockerfile: 138B 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 561B 0.0s => [internal] load metadata for docker.io/library/nginx:1.25 4.7s [+] Building 5.5s (4/7) => [internal] load build definition from Dockerfile 0.1s => => transferring dockerfile: 138B 0.0s [+] Building 7.2s (4/7) [+] Building 8.4s (4/7) [+] Building 9.2s (4/7) => [internal] load build definition from Dockerfile 0.1s [+] Building 9.5s (4/7) [+] Building 13.8s (4/11) [+] Building 22.0s (4/11) [+] Building 26.1s (4/11) => [internal] load metadata for docker.io/library/php:8.3-fpm-bullseye 4.9s => [internal] load metadata for docker.io/library/nginx:1.25 4.7s => [1/3] FROM docker.io/library/nginx:1.25@sha256:10d1f5b58f74683ad34eb29287e07dab 20.9s => => resolve docker.io/library/nginx:1.25@sha256:10d1f5b58f74683ad34eb29287e07dab1 0.0s => => sha256:10d1f5b58f74683ad34eb29287e07dab1e90f10af243f151bb50aa 1.86kB / 1.86kB 0.0s => => sha256:3c4c1f42a89e343c7b050c5e5d6f670a0e0b82e70e0e7d023f1009 1.78kB / 1.78kB 0.0s => => sha256:1f7ce2fa46ab3942feabee654933948821303a5a821789dddab2 29.15MB / 29.15MB 3.3s => => sha256:9b16c94bb68628753a94b89ddf26abc0974cd35a96f785895ab0 41.38MB / 41.38MB 3.8s => => sha256:a6bd71f48f6839d9faae1f29d3babef831e76bc213107682c5cc80 8.15kB / 8.15kB 0.0s => => sha256:9a59d19f9c5bb1ebdfef2255496b1bb5d658fdccc300c4c1f0d18c73f1 625B / 625B 0.5s => => sha256:9ea27b074f71d5766a59cdbfaa15f4cd3d17bffb83fed066373eb28732 959B / 959B 0.9s => => sha256:c6edf33e2524b241a0b191d0a0d2ca3d8d4ae7470333b059dd97ba30e6 371B / 371B 1.3s => => sha256:84b1ff10387b26e2952f006c0a4fe4c6f3c0743cb08ee448bb7157 1.21kB / 1.21kB 1.7s => => sha256:51735783196785d1f604dc7711ea70fb3fab3cd9d99eaeff991c5a 1.40kB / 1.40kB 2.0s => => extracting sha256:1f7ce2fa46ab3942feabee654933948821303a5a821789dddab2d8c3df5 7.6s => => extracting sha256:9b16c94bb68628753a94b89ddf26abc0974cd35a96f785895ab011d9b50 4.1s [+] Building 28.3s (4/11) [+] Building 28.4s (4/11) [+] Building 28.8s (4/11) [+] Building 28.9s (4/11) [+] Building 29.0s (4/11) [+] Building 30.3s (4/11) [+] Building 31.4s (4/11) [+] Building 31.6s (4/11) => [base 1/4] FROM docker.io/library/php:8.3-fpm-bullseye@sha256:2d5f4befa91070594 26.3s [+] Building 32.2s (4/11) => [base 1/4] FROM docker.io/library/php:8.3-fpm-bullseye@sha256:2d5f4befa91070594 26.8s [+] Building 164.1s (12/12) FINISHED => [internal] load build definition from Dockerfile 0.1s => => transferring dockerfile: 1.55kB 0.0s => [internal] load .dockerignore 0.1s => => transferring context: 561B 0.0s => [internal] load metadata for docker.io/library/php:8.3-fpm-bullseye 4.9s => [internal] load build context 0.1s => => transferring context: 613B 0.0s => [base 1/4] FROM docker.io/library/php:8.3-fpm-bullseye@sha256:2d5f4befa91070594 31.3s => => resolve docker.io/library/php:8.3-fpm-bullseye@sha256:2d5f4befa91070594565fdc 0.1s => => sha256:2d5f4befa91070594565fdc5ea82d195afbc7ab58f751ffa3f15a1 1.86kB / 1.86kB 0.0s => => sha256:847b1caa324dbe80aa89aa9c0bab82b4f35f28ac7ade8fdb00cc68 2.41kB / 2.41kB 0.0s => => sha256:a5167fbbfff9b6ff9064d01373065a0257e93c7bb02ec3c0e1e1 11.87kB / 11.87kB 0.0s => => sha256:b7f91549542cca4b35a34cdee5364339f17468971ea730bb0728 31.42MB / 31.42MB 4.0s => => sha256:0754b57b9b7d3a089ca18ba98121861a56ce2624c2875a8e7bf8b21a79 225B / 225B 3.6s => => sha256:71e5060f3937930b5fa3d39f56adf3c2acfea72741014d1969f3 91.64MB / 91.64MB 8.2s => => sha256:f25a6e74b7f558f50a59c2efa94a62c44a6323861b0c76e6d2144078ab 271B / 271B 4.1s => => sha256:cfe33a1c9e51d04803112f71e930c4269107031efc4492cc8c5c 12.75MB / 12.75MB 6.6s => => sha256:d58c6c3d379db9c036fab15df68bd59cd5c41b64cff7c04b1273c9d677 494B / 494B 4.5s => => sha256:cf1390e81c475fb5d364ad488163d4b7f30014dc41029f88be5b 26.78MB / 26.78MB 7.5s => => sha256:f79e7693b86d830f0e80c0cf8a0b5cdeeac23d4b6f34288dcb8bd3 2.45kB / 2.45kB 6.9s => => sha256:9d907b627720968665b5d5d86ca0cbe3216a59fd11482c0a2ecd5177a0 246B / 246B 7.3s => => extracting sha256:b7f91549542cca4b35a34cdee5364339f17468971ea730bb072864d3e78 8.3s => => sha256:3aae34d45ac145909b5032380784641470d1f0b6e98814b113fc81 9.18kB / 9.18kB 8.7s => => extracting sha256:0754b57b9b7d3a089ca18ba98121861a56ce2624c2875a8e7bf8b21a795 0.0s => => extracting sha256:71e5060f3937930b5fa3d39f56adf3c2acfea72741014d1969f3f437e5 11.3s => => extracting sha256:f25a6e74b7f558f50a59c2efa94a62c44a6323861b0c76e6d2144078ab6 0.0s => => extracting sha256:cfe33a1c9e51d04803112f71e930c4269107031efc4492cc8c5c0bc4bf3 0.2s => => extracting sha256:d58c6c3d379db9c036fab15df68bd59cd5c41b64cff7c04b1273c9d677d 0.0s => => extracting sha256:cf1390e81c475fb5d364ad488163d4b7f30014dc41029f88be5b98f2167 1.4s => => extracting sha256:f79e7693b86d830f0e80c0cf8a0b5cdeeac23d4b6f34288dcb8bd3b9df0 0.0s => => extracting sha256:9d907b627720968665b5d5d86ca0cbe3216a59fd11482c0a2ecd5177a0b 0.0s => => extracting sha256:3aae34d45ac145909b5032380784641470d1f0b6e98814b113fc81730d9 0.0s => FROM docker.io/library/composer:2.6 27.3s => => resolve docker.io/library/composer:2.6 4.3s => => sha256:67f1bec07666f688791bff2c13b34b9c35042cc4c1e42fbb5bd4db 1.65kB / 1.65kB 0.0s => => sha256:20f5108974c63c7f1053b3a1e45215aeee2a83ee2c3e6fa0d011a9 3.25kB / 3.25kB 0.0s => => sha256:a367d1cb680d822e1cfff066254fd1db8392a47a1b7c31c38d62 11.34kB / 11.34kB 0.0s => => sha256:c926b61bad3b94ae7351bafd0c184c159ebf0643b085f7ef1d47ec 3.40MB / 3.40MB 4.0s => => extracting sha256:c926b61bad3b94ae7351bafd0c184c159ebf0643b085f7ef1d47ecdc731 0.8s => => sha256:e8e26b626c27026d1938a0b6bd77e36b4113da4b7a1134df8d1aa9 2.68MB / 2.68MB 5.2s => => sha256:23427f6f19cc27aa3496173559d7fc30c2501d1d179a15b52ac175 1.26kB / 1.26kB 4.7s => => sha256:938ee652f0dd66c081c31e773163d4c3d8ec979f9ced384ed270cdc5fb 269B / 269B 4.9s => => sha256:8abe2aaf4047e9984223c8d63be88c09b7d447f8c9f77851aa06 12.45MB / 12.45MB 7.5s => => sha256:e06ec6f102433dfe7410990547f8d059d4c3e56455e35d7b4dfbfb9678 492B / 492B 5.2s => => sha256:9ea984f05cf27a91a07a0b1f63adb1e6f9c4cb631325b5a07343 17.07MB / 17.07MB 7.3s => => extracting sha256:e8e26b626c27026d1938a0b6bd77e36b4113da4b7a1134df8d1aa9f4965 0.8s => => sha256:2e6c3ecb64ca025834e2eba225bd5d603742000e1d67407ba50cf0 2.45kB / 2.45kB 5.7s => => sha256:d3b07fe920dd6973a44ea83074fd9125fe7d4774492d00c0ffef 18.95kB / 18.95kB 6.3s => => extracting sha256:23427f6f19cc27aa3496173559d7fc30c2501d1d179a15b52ac1758cc16 0.0s => => sha256:db476e3c025b598a275cc72e45c12e45db55e1df982d1e90e45f 32.53MB / 32.53MB 8.6s => => extracting sha256:938ee652f0dd66c081c31e773163d4c3d8ec979f9ced384ed270cdc5fbc 0.0s => => sha256:00b605206545e71c8d6637e233d08e5cae279512b88f4eedbb3dd94449 257B / 257B 7.7s => => sha256:a3f172b6c24514834b464f5a515ea799ff120009dbb5e8be3574b7 1.32MB / 1.32MB 8.2s => => sha256:f4200807651477364bc9a9c65461e6606f9fd636a2bc8f3bb3b22b6c84 419B / 419B 8.0s => => extracting sha256:8abe2aaf4047e9984223c8d63be88c09b7d447f8c9f77851aa06771c52b 0.9s => => sha256:3ae5dfbba469e3be92262cca5c2241876dc072ecaaff4285c202d0c0c3e3 93B / 93B 8.3s => => extracting sha256:e06ec6f102433dfe7410990547f8d059d4c3e56455e35d7b4dfbfb96784 0.0s => => extracting sha256:9ea984f05cf27a91a07a0b1f63adb1e6f9c4cb631325b5a07343b8faf75 3.0s => => extracting sha256:2e6c3ecb64ca025834e2eba225bd5d603742000e1d67407ba50cf0f60ea 0.0s => => extracting sha256:d3b07fe920dd6973a44ea83074fd9125fe7d4774492d00c0ffefb9a04a8 0.0s => => extracting sha256:db476e3c025b598a275cc72e45c12e45db55e1df982d1e90e45f76b630e 6.3s => => extracting sha256:00b605206545e71c8d6637e233d08e5cae279512b88f4eedbb3dd944494 0.0s => => extracting sha256:a3f172b6c24514834b464f5a515ea799ff120009dbb5e8be3574b779c4f 0.3s => => extracting sha256:f4200807651477364bc9a9c65461e6606f9fd636a2bc8f3bb3b22b6c847 0.0s => => extracting sha256:3ae5dfbba469e3be92262cca5c2241876dc072ecaaff4285c202d0c0c3e 0.0s => [base 2/4] WORKDIR /workspace 0.5s => [base 3/4] COPY --from=composer:2.6 /usr/bin/composer /usr/bin/composer 0.1s => [base 4/4] RUN apt-get update && apt-get -y install --no-install-recommends 121.2s => [development 1/2] RUN apt-get -y install --no-install-recommends default-mys 4.3s => [development 2/2] COPY ./infra/docker/php/php.development.ini /usr/local/etc/php 0.0s => exporting to image 1.2s => => exporting layers 1.2s => => writing image sha256:fed5decbff1787633896f6ad5c2c62e4d368f83d36ede7181f8b6288 0.0s => => naming to docker.io/library/sample-app-app 0.0s docker compose up -d [+] Running 7/7 ⠿ Network sample-app_default Created 0.1s ⠿ Volume "sample-app_db-store" Created 0.0s ⠿ Volume "sample-app_psysh-store" Created 0.0s ⠿ Container sample-app-app-1 Started 1.4s ⠿ Container sample-app-db-1 Started 1.3s ⠿ Container sample-app-mailpit-1 Started 1.3s ⠿ Container sample-app-web-1 Started 1.4s docker compose exec app composer create-project --prefer-dist laravel/laravel . Creating a "laravel/laravel" project at "./" Installing laravel/laravel (v10.2.9) - Downloading laravel/laravel (v10.2.9) - Installing laravel/laravel (v10.2.9): Extracting archive Created project in /workspace/. > @php -r "file_exists('.env') || copy('.env.example', '.env');" Loading composer repositories with package information Updating dependencies Lock file operations: 111 installs, 0 updates, 0 removals - Locking brick/math (0.11.0) - Locking carbonphp/carbon-doctrine-types (3.0.0) - Locking dflydev/dot-access-data (v3.0.2) - Locking doctrine/inflector (2.0.8) - Locking doctrine/lexer (3.0.0) - Locking dragonmantank/cron-expression (v3.3.3) - Locking egulias/email-validator (4.0.2) - Locking fakerphp/faker (v1.23.0) - Locking filp/whoops (2.15.4) - Locking fruitcake/php-cors (v1.3.0) - Locking graham-campbell/result-type (v1.1.2) - Locking guzzlehttp/guzzle (7.8.0) - Locking guzzlehttp/promises (2.0.1) - Locking guzzlehttp/psr7 (2.6.1) - Locking guzzlehttp/uri-template (v1.0.2) - Locking hamcrest/hamcrest-php (v2.0.1) - Locking laravel/framework (v10.34.2) - Locking laravel/pint (v1.13.6) - Locking laravel/prompts (v0.1.13) - Locking laravel/sail (v1.26.2) - Locking laravel/sanctum (v3.3.2) - Locking laravel/serializable-closure (v1.3.3) - Locking laravel/tinker (v2.8.2) - Locking league/commonmark (2.4.1) - Locking league/config (v1.2.0) - Locking league/flysystem (3.21.0) - Locking league/flysystem-local (3.21.0) - Locking league/mime-type-detection (1.14.0) - Locking mockery/mockery (1.6.6) - Locking monolog/monolog (3.5.0) - Locking myclabs/deep-copy (1.11.1) - Locking nesbot/carbon (2.72.0) - Locking nette/schema (v1.2.5) - Locking nette/utils (v4.0.3) - Locking nikic/php-parser (v4.17.1) - Locking nunomaduro/collision (v7.10.0) - Locking nunomaduro/termwind (v1.15.1) - Locking phar-io/manifest (2.0.3) - Locking phar-io/version (3.2.1) - Locking phpoption/phpoption (1.9.2) - Locking phpunit/php-code-coverage (10.1.9) - Locking phpunit/php-file-iterator (4.1.0) - Locking phpunit/php-invoker (4.0.0) - Locking phpunit/php-text-template (3.0.1) - Locking phpunit/php-timer (6.0.0) - Locking phpunit/phpunit (10.5.1) - Locking psr/clock (1.0.0) - Locking psr/container (2.0.2) - Locking psr/event-dispatcher (1.0.0) - Locking psr/http-client (1.0.3) - Locking psr/http-factory (1.0.2) - Locking psr/http-message (2.0) - Locking psr/log (3.0.0) - Locking psr/simple-cache (3.0.0) - Locking psy/psysh (v0.11.22) - Locking ralouphie/getallheaders (3.0.3) - Locking ramsey/collection (2.0.0) - Locking ramsey/uuid (4.7.5) - Locking sebastian/cli-parser (2.0.0) - Locking sebastian/code-unit (2.0.0) - Locking sebastian/code-unit-reverse-lookup (3.0.0) - Locking sebastian/comparator (5.0.1) - Locking sebastian/complexity (3.1.0) - Locking sebastian/diff (5.0.3) - Locking sebastian/environment (6.0.1) - Locking sebastian/exporter (5.1.1) - Locking sebastian/global-state (6.0.1) - Locking sebastian/lines-of-code (2.0.1) - Locking sebastian/object-enumerator (5.0.0) - Locking sebastian/object-reflector (3.0.0) - Locking sebastian/recursion-context (5.0.0) - Locking sebastian/type (4.0.0) - Locking sebastian/version (4.0.1) - Locking spatie/backtrace (1.5.3) - Locking spatie/flare-client-php (1.4.3) - Locking spatie/ignition (1.11.3) - Locking spatie/laravel-ignition (2.3.1) - Locking symfony/console (v6.4.1) - Locking symfony/css-selector (v6.4.0) - Locking symfony/deprecation-contracts (v3.4.0) - Locking symfony/error-handler (v6.4.0) - Locking symfony/event-dispatcher (v7.0.0) - Locking symfony/event-dispatcher-contracts (v3.4.0) - Locking symfony/finder (v6.4.0) - Locking symfony/http-foundation (v6.4.0) - Locking symfony/http-kernel (v6.4.1) - Locking symfony/mailer (v6.4.0) - Locking symfony/mime (v6.4.0) - Locking symfony/polyfill-ctype (v1.28.0) - Locking symfony/polyfill-intl-grapheme (v1.28.0) - Locking symfony/polyfill-intl-idn (v1.28.0) - Locking symfony/polyfill-intl-normalizer (v1.28.0) - Locking symfony/polyfill-mbstring (v1.28.0) - Locking symfony/polyfill-php72 (v1.28.0) - Locking symfony/polyfill-php80 (v1.28.0) - Locking symfony/polyfill-php83 (v1.28.0) - Locking symfony/polyfill-uuid (v1.28.0) - Locking symfony/process (v6.4.0) - Locking symfony/routing (v6.4.1) - Locking symfony/service-contracts (v3.4.0) - Locking symfony/string (v7.0.0) - Locking symfony/translation (v6.4.0) - Locking symfony/translation-contracts (v3.4.0) - Locking symfony/uid (v6.4.0) - Locking symfony/var-dumper (v6.4.0) - Locking symfony/yaml (v7.0.0) - Locking theseer/tokenizer (1.2.2) - Locking tijsverkoyen/css-to-inline-styles (2.2.6) - Locking vlucas/phpdotenv (v5.6.0) - Locking voku/portable-ascii (2.0.1) - Locking webmozart/assert (1.11.0) Writing lock file Installing dependencies from lock file (including require-dev) Package operations: 111 installs, 0 updates, 0 removals - Downloading doctrine/inflector (2.0.8) - Downloading doctrine/lexer (3.0.0) - Downloading symfony/polyfill-ctype (v1.28.0) - Downloading webmozart/assert (1.11.0) - Downloading dragonmantank/cron-expression (v3.3.3) - Downloading symfony/deprecation-contracts (v3.4.0) - Downloading psr/container (2.0.2) - Downloading fakerphp/faker (v1.23.0) - Downloading symfony/polyfill-php80 (v1.28.0) - Downloading symfony/polyfill-php83 (v1.28.0) - Downloading symfony/polyfill-mbstring (v1.28.0) - Downloading symfony/http-foundation (v6.4.0) - Downloading fruitcake/php-cors (v1.3.0) - Downloading psr/http-message (2.0) - Downloading psr/http-client (1.0.3) - Downloading ralouphie/getallheaders (3.0.3) - Downloading psr/http-factory (1.0.2) - Downloading guzzlehttp/psr7 (2.6.1) - Downloading guzzlehttp/promises (2.0.1) - Downloading guzzlehttp/guzzle (7.8.0) - Downloading guzzlehttp/uri-template (v1.0.2) - Downloading laravel/pint (v1.13.6) - Downloading symfony/polyfill-intl-normalizer (v1.28.0) - Downloading symfony/polyfill-intl-grapheme (v1.28.0) - Downloading symfony/string (v7.0.0) - Downloading symfony/service-contracts (v3.4.0) - Downloading symfony/console (v6.4.1) - Downloading voku/portable-ascii (2.0.1) - Downloading phpoption/phpoption (1.9.2) - Downloading graham-campbell/result-type (v1.1.2) - Downloading vlucas/phpdotenv (v5.6.0) - Downloading symfony/css-selector (v6.4.0) - Downloading tijsverkoyen/css-to-inline-styles (2.2.6) - Downloading symfony/var-dumper (v6.4.0) - Downloading symfony/polyfill-uuid (v1.28.0) - Downloading symfony/uid (v6.4.0) - Downloading symfony/routing (v6.4.1) - Downloading symfony/process (v6.4.0) - Downloading symfony/polyfill-php72 (v1.28.0) - Downloading symfony/polyfill-intl-idn (v1.28.0) - Downloading symfony/mime (v6.4.0) - Downloading psr/event-dispatcher (1.0.0) - Downloading symfony/event-dispatcher-contracts (v3.4.0) - Downloading symfony/event-dispatcher (v7.0.0) - Downloading psr/log (3.0.0) - Downloading egulias/email-validator (4.0.2) - Downloading symfony/mailer (v6.4.0) - Downloading symfony/error-handler (v6.4.0) - Downloading symfony/http-kernel (v6.4.1) - Downloading symfony/finder (v6.4.0) - Downloading ramsey/collection (2.0.0) - Downloading brick/math (0.11.0) - Downloading ramsey/uuid (4.7.5) - Downloading psr/simple-cache (3.0.0) - Downloading nunomaduro/termwind (v1.15.1) - Downloading symfony/translation-contracts (v3.4.0) - Downloading symfony/translation (v6.4.0) - Downloading psr/clock (1.0.0) - Downloading carbonphp/carbon-doctrine-types (3.0.0) - Downloading nesbot/carbon (2.72.0) - Downloading monolog/monolog (3.5.0) - Downloading league/mime-type-detection (1.14.0) - Downloading league/flysystem (3.21.0) - Downloading league/flysystem-local (3.21.0) - Downloading nette/utils (v4.0.3) - Downloading nette/schema (v1.2.5) - Downloading dflydev/dot-access-data (v3.0.2) - Downloading league/config (v1.2.0) - Downloading league/commonmark (2.4.1) - Downloading laravel/serializable-closure (v1.3.3) - Downloading laravel/prompts (v0.1.13) - Downloading laravel/framework (v10.34.2) - Downloading symfony/yaml (v7.0.0) - Downloading laravel/sail (v1.26.2) - Downloading laravel/sanctum (v3.3.2) - Downloading nikic/php-parser (v4.17.1) - Downloading psy/psysh (v0.11.22) - Downloading laravel/tinker (v2.8.2) - Downloading hamcrest/hamcrest-php (v2.0.1) - Downloading mockery/mockery (1.6.6) - Downloading filp/whoops (2.15.4) - Downloading nunomaduro/collision (v7.10.0) - Downloading sebastian/version (4.0.1) - Downloading sebastian/type (4.0.0) - Downloading sebastian/recursion-context (5.0.0) - Downloading sebastian/object-reflector (3.0.0) - Downloading sebastian/object-enumerator (5.0.0) - Downloading sebastian/global-state (6.0.1) - Downloading sebastian/exporter (5.1.1) - Downloading sebastian/environment (6.0.1) - Downloading sebastian/diff (5.0.3) - Downloading sebastian/comparator (5.0.1) - Downloading sebastian/code-unit (2.0.0) - Downloading sebastian/cli-parser (2.0.0) - Downloading phpunit/php-timer (6.0.0) - Downloading phpunit/php-text-template (3.0.1) - Downloading phpunit/php-invoker (4.0.0) - Downloading phpunit/php-file-iterator (4.1.0) - Downloading theseer/tokenizer (1.2.2) - Downloading sebastian/lines-of-code (2.0.1) - Downloading sebastian/complexity (3.1.0) - Downloading sebastian/code-unit-reverse-lookup (3.0.0) - Downloading phpunit/php-code-coverage (10.1.9) - Downloading phar-io/version (3.2.1) - Downloading phar-io/manifest (2.0.3) - Downloading myclabs/deep-copy (1.11.1) - Downloading phpunit/phpunit (10.5.1) - Downloading spatie/backtrace (1.5.3) - Downloading spatie/flare-client-php (1.4.3) - Downloading spatie/ignition (1.11.3) - Downloading spatie/laravel-ignition (2.3.1) - Installing doctrine/inflector (2.0.8): Extracting archive - Installing doctrine/lexer (3.0.0): Extracting archive - Installing symfony/polyfill-ctype (v1.28.0): Extracting archive - Installing webmozart/assert (1.11.0): Extracting archive - Installing dragonmantank/cron-expression (v3.3.3): Extracting archive - Installing symfony/deprecation-contracts (v3.4.0): Extracting archive - Installing psr/container (2.0.2): Extracting archive - Installing fakerphp/faker (v1.23.0): Extracting archive - Installing symfony/polyfill-php80 (v1.28.0): Extracting archive - Installing symfony/polyfill-php83 (v1.28.0): Extracting archive - Installing symfony/polyfill-mbstring (v1.28.0): Extracting archive - Installing symfony/http-foundation (v6.4.0): Extracting archive - Installing fruitcake/php-cors (v1.3.0): Extracting archive - Installing psr/http-message (2.0): Extracting archive - Installing psr/http-client (1.0.3): Extracting archive - Installing ralouphie/getallheaders (3.0.3): Extracting archive - Installing psr/http-factory (1.0.2): Extracting archive - Installing guzzlehttp/psr7 (2.6.1): Extracting archive - Installing guzzlehttp/promises (2.0.1): Extracting archive - Installing guzzlehttp/guzzle (7.8.0): Extracting archive - Installing guzzlehttp/uri-template (v1.0.2): Extracting archive - Installing laravel/pint (v1.13.6): Extracting archive - Installing symfony/polyfill-intl-normalizer (v1.28.0): Extracting archive - Installing symfony/polyfill-intl-grapheme (v1.28.0): Extracting archive - Installing symfony/string (v7.0.0): Extracting archive - Installing symfony/service-contracts (v3.4.0): Extracting archive - Installing symfony/console (v6.4.1): Extracting archive - Installing voku/portable-ascii (2.0.1): Extracting archive - Installing phpoption/phpoption (1.9.2): Extracting archive - Installing graham-campbell/result-type (v1.1.2): Extracting archive - Installing vlucas/phpdotenv (v5.6.0): Extracting archive - Installing symfony/css-selector (v6.4.0): Extracting archive - Installing tijsverkoyen/css-to-inline-styles (2.2.6): Extracting archive - Installing symfony/var-dumper (v6.4.0): Extracting archive - Installing symfony/polyfill-uuid (v1.28.0): Extracting archive - Installing symfony/uid (v6.4.0): Extracting archive - Installing symfony/routing (v6.4.1): Extracting archive - Installing symfony/process (v6.4.0): Extracting archive - Installing symfony/polyfill-php72 (v1.28.0): Extracting archive - Installing symfony/polyfill-intl-idn (v1.28.0): Extracting archive - Installing symfony/mime (v6.4.0): Extracting archive - Installing psr/event-dispatcher (1.0.0): Extracting archive - Installing symfony/event-dispatcher-contracts (v3.4.0): Extracting archive - Installing symfony/event-dispatcher (v7.0.0): Extracting archive - Installing psr/log (3.0.0): Extracting archive - Installing egulias/email-validator (4.0.2): Extracting archive - Installing symfony/mailer (v6.4.0): Extracting archive - Installing symfony/error-handler (v6.4.0): Extracting archive - Installing symfony/http-kernel (v6.4.1): Extracting archive - Installing symfony/finder (v6.4.0): Extracting archive - Installing ramsey/collection (2.0.0): Extracting archive - Installing brick/math (0.11.0): Extracting archive - Installing ramsey/uuid (4.7.5): Extracting archive - Installing psr/simple-cache (3.0.0): Extracting archive - Installing nunomaduro/termwind (v1.15.1): Extracting archive - Installing symfony/translation-contracts (v3.4.0): Extracting archive - Installing symfony/translation (v6.4.0): Extracting archive - Installing psr/clock (1.0.0): Extracting archive - Installing carbonphp/carbon-doctrine-types (3.0.0): Extracting archive - Installing nesbot/carbon (2.72.0): Extracting archive - Installing monolog/monolog (3.5.0): Extracting archive - Installing league/mime-type-detection (1.14.0): Extracting archive - Installing league/flysystem (3.21.0): Extracting archive - Installing league/flysystem-local (3.21.0): Extracting archive - Installing nette/utils (v4.0.3): Extracting archive - Installing nette/schema (v1.2.5): Extracting archive - Installing dflydev/dot-access-data (v3.0.2): Extracting archive - Installing league/config (v1.2.0): Extracting archive - Installing league/commonmark (2.4.1): Extracting archive - Installing laravel/serializable-closure (v1.3.3): Extracting archive - Installing laravel/prompts (v0.1.13): Extracting archive - Installing laravel/framework (v10.34.2): Extracting archive - Installing symfony/yaml (v7.0.0): Extracting archive - Installing laravel/sail (v1.26.2): Extracting archive - Installing laravel/sanctum (v3.3.2): Extracting archive - Installing nikic/php-parser (v4.17.1): Extracting archive - Installing psy/psysh (v0.11.22): Extracting archive - Installing laravel/tinker (v2.8.2): Extracting archive - Installing hamcrest/hamcrest-php (v2.0.1): Extracting archive - Installing mockery/mockery (1.6.6): Extracting archive - Installing filp/whoops (2.15.4): Extracting archive - Installing nunomaduro/collision (v7.10.0): Extracting archive - Installing sebastian/version (4.0.1): Extracting archive - Installing sebastian/type (4.0.0): Extracting archive - Installing sebastian/recursion-context (5.0.0): Extracting archive - Installing sebastian/object-reflector (3.0.0): Extracting archive - Installing sebastian/object-enumerator (5.0.0): Extracting archive - Installing sebastian/global-state (6.0.1): Extracting archive - Installing sebastian/exporter (5.1.1): Extracting archive - Installing sebastian/environment (6.0.1): Extracting archive - Installing sebastian/diff (5.0.3): Extracting archive - Installing sebastian/comparator (5.0.1): Extracting archive - Installing sebastian/code-unit (2.0.0): Extracting archive - Installing sebastian/cli-parser (2.0.0): Extracting archive - Installing phpunit/php-timer (6.0.0): Extracting archive - Installing phpunit/php-text-template (3.0.1): Extracting archive - Installing phpunit/php-invoker (4.0.0): Extracting archive - Installing phpunit/php-file-iterator (4.1.0): Extracting archive - Installing theseer/tokenizer (1.2.2): Extracting archive - Installing sebastian/lines-of-code (2.0.1): Extracting archive - Installing sebastian/complexity (3.1.0): Extracting archive - Installing sebastian/code-unit-reverse-lookup (3.0.0): Extracting archive - Installing phpunit/php-code-coverage (10.1.9): Extracting archive - Installing phar-io/version (3.2.1): Extracting archive - Installing phar-io/manifest (2.0.3): Extracting archive - Installing myclabs/deep-copy (1.11.1): Extracting archive - Installing phpunit/phpunit (10.5.1): Extracting archive - Installing spatie/backtrace (1.5.3): Extracting archive - Installing spatie/flare-client-php (1.4.3): Extracting archive - Installing spatie/ignition (1.11.3): Extracting archive - Installing spatie/laravel-ignition (2.3.1): Extracting archive 52 package suggestions were added by new dependencies, use `composer suggest` to see details. Generating optimized autoload files > Illuminate\Foundation\ComposerScripts::postAutoloadDump > @php artisan package:discover --ansi INFO Discovering packages. laravel/sail ..................................................................... DONE laravel/sanctum .................................................................. DONE laravel/tinker ................................................................... DONE nesbot/carbon .................................................................... DONE nunomaduro/collision ............................................................. DONE nunomaduro/termwind .............................................................. DONE spatie/laravel-ignition .......................................................... DONE 83 packages you are using are looking for funding. Use the `composer fund` command to find out more! > @php artisan vendor:publish --tag=laravel-assets --ansi --force INFO No publishable resources for tag [laravel-assets]. No security vulnerability advisories found. > @php artisan key:generate --ansi INFO Application key set successfully. docker compose exec app php artisan key:generate INFO Application key set successfully. docker compose exec app php artisan storage:link INFO The [public/storage] link has been connected to [storage/app/public]. docker compose exec app chmod -R 777 storage bootstrap/cache docker compose exec app php artisan migrate:fresh --seed Dropping all tables ........................................................ 232ms DONE INFO Preparing database. Creating migration table .................................................... 88ms DONE INFO Running migrations. 2014_10_12_000000_create_users_table ....................................... 113ms DONE 2014_10_12_100000_create_password_reset_tokens_table ....................... 106ms DONE 2019_08_19_000000_create_failed_jobs_table .................................. 87ms DONE 2019_12_14_000001_create_personal_access_tokens_table ...................... 115ms DONE INFO Seeding database.
create-project
で実行されるのは、以下の内容です。
# srcディレクトリを作成 $ mkdir -p src # イメージをビルド $ docker compose build # コンテナをバックグラウンドで起動 $ docker compose up -d # appサービスのコンテナ内でComposerコマンドを実行し、Laravelプロジェクトを現在のディレクトリに作成 $ docker compose exec app composer create-project --prefer-dist laravel/laravel . # アプリケーションの暗号化キーを生成 $ docker compose exec app php artisan key:generate # public/storageからstorage/app/publicへのシンボリックリンクを作成 $ docker compose exec app php artisan storage:link # 指定のstorageディレクトリ、bootstrap/cacheディレクトリに対して書き込み権限付与 $ docker compose exec app chmod -R 777 storage bootstrap/cache # データベースのマイグレーションを実行 $ docker compose exec app php artisan migrate
Web ブラウザで http:// localhost
にアクセスし、Laravel と書かれたページが表示されるか確認します。
app サービスのコンテナの Dockerfile を編集します。追加した内容の確認のために、ステップを踏んで追加します。
2. Node.js のバージョンを指定してインストール
デフォルトの状態では以下のとおり、Node.js は導入されていないため、インストールします。
# r_yamate @ mbp in ~/development/sample-app on git:main x [9:38:20] $ make app docker compose exec app bash root@87b34a2bdd9a:/workspace# node --version bash: node: command not found root@87b34a2bdd9a:/workspace# npm --version bash: npm: command not found root@87b34a2bdd9a:/workspace# npx --version bash: npx: command not found
構築した Laravel の開発環境に node, npm, npx がインストールされるように app サービスのコンテナの Dockerfile を編集します。
- 編集:infra/docker/php/Dockerfile
FROM php:8.3-fpm-bullseye AS base WORKDIR /workspace # timezone environment ENV TZ=UTC \ # locale LANG=en_US.UTF-8 \ LANGUAGE=en_US:en \ LC_ALL=en_US.UTF-8 \ # composer environment COMPOSER_ALLOW_SUPERUSER=1 \ COMPOSER_HOME=/composer COPY --from=composer:2.6 /usr/bin/composer /usr/bin/composer # 必要なパッケージのインストールと設定 RUN apt-get update \ && apt-get -y install --no-install-recommends \ locales \ git \ unzip \ libzip-dev \ libicu-dev \ libonig-dev \ && locale-gen en_US.UTF-8 \ && localedef -f UTF-8 -i en_US en_US.UTF-8 \ && docker-php-ext-install \ intl \ pdo_mysql \ zip \ bcmath \ && composer config -g process-timeout 3600 \ && composer config -g repos.packagist composer https://packagist.org # === ここから追加 === # Node.jsのバージョンを指定してインストール ARG NODE_VERSION=20.x RUN curl -sL https://deb.nodesource.com/setup_$NODE_VERSION | bash - \ && apt-get update \ && apt-get install -y nodejs \ && apt-get clean \ && npm install -g npm@10.2.4 # === ここまで追加 === # 開発用設定 FROM base AS development RUN apt-get -y install --no-install-recommends \ default-mysql-client \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* COPY ./infra/docker/php/php.development.ini /usr/local/etc/php/php.ini # Xdebug設定 FROM development AS development-xdebug RUN pecl install xdebug && \ docker-php-ext-enable xdebug COPY ./infra/docker/php/xdebug.ini /usr/local/etc/php/conf.d/xdebug.ini # デプロイ用設定 FROM base AS deploy COPY ./infra/docker/php/php.deploy.ini /usr/local/etc/php/php.ini COPY ./src /workspace RUN composer install -q -n --no-ansi --no-dev --no-scripts --no-progress --prefer-dist \ && chmod -R 777 storage bootstrap/cache \ && php artisan optimize:clear \ && php artisan optimize \ && apt-get clean \ && rm -rf /var/lib/apt/lists/*
Docker イメージ内に Node.js をセットアップし、npm を指定のバージョンにアップグレードしています。
環境を再構築します。
make remake
コマンド実行時ログ
# r_yamate @ mbp in ~/development/sample-app on git:main x [9:56:36] C:2 $ make remake docker compose down --rmi all --volumes --remove-orphans [+] Running 4/4 ⠿ Image sample-app-db:latest Removed 0.3s ⠿ Image sample-app-web:latest Removed 0.3s ⠿ Volume sample-app_db-store Removed 0.0s ⠿ Volume sample-app_psysh-store Removed 0.0s docker compose build [+] Building 0.0s (0/0) [+] Building 0.0s (0/0) [+] Building 0.3s (1/1) => [internal] load build definition from Dockerfile 0.0s [+] Building 0.0s (1/1) => [internal] load build definition from Dockerfile 0.0s [+] Building 0.5s (6/6) FINISHED => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 31B 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 35B 0.0s => [internal] load metadata for docker.io/mysql/mysql-server:8.0 0.0s => [1/2] FROM docker.io/mysql/mysql-server:8.0 0.0s => CACHED [2/2] RUN mkdir /var/log/mysql && chown mysql:mysql $_ && chmod 777 $ 0.0s => exporting to image 0.0s [+] Building 0.3s (2/3) => => transferring context: 35B 0.0s => [internal] load metadata for docker.io/library/php:8.3-fpm-bullseye 0.9s [+] Building 3.0s (8/8) FINISHED => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 31B 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 35B 0.0s => [internal] load metadata for docker.io/library/nginx:1.25 2.6s => [internal] load build context 0.0s => => transferring context: 953B 0.0s => [1/3] FROM docker.io/library/nginx:1.25@sha256:10d1f5b58f74683ad34eb29287e07dab1 0.0s [+] Building 98.5s (13/13) FINISHED => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 1.83kB 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 35B 0.0s => [internal] load metadata for docker.io/library/php:8.3-fpm-bullseye 2.6s => [base 1/5] FROM docker.io/library/php:8.3-fpm-bullseye@sha256:2d5f4befa910705945 0.0s => [internal] load build context 0.1s => => transferring context: 613B 0.0s => FROM docker.io/library/composer:2.6 1.5s => => resolve docker.io/library/composer:2.6 1.5s => CACHED [base 2/5] WORKDIR /workspace 0.0s => CACHED [base 3/5] COPY --from=composer:2.6 /usr/bin/composer /usr/bin/composer 0.0s => CACHED [base 4/5] RUN apt-get update && apt-get -y install --no-install-recomm 0.0s => [base 5/5] RUN curl -sL https://deb.nodesource.com/setup_20.x | bash - && apt 87.5s => [development 1/2] RUN apt-get -y install --no-install-recommends default-mysql 4.2s => [development 2/2] COPY ./infra/docker/php/php.development.ini /usr/local/etc/php 0.1s => exporting to image 2.4s => => exporting layers 2.3s => => writing image sha256:5443fca82f3999e8d839ab763661ef37983bb62a1032fb36eed64bd5 0.0s => => naming to docker.io/library/sample-app-app 0.0s docker compose up -d [+] Running 4/4 ⠿ mailpit Pulled 5.2s ⠿ c926b61bad3b Already exists 0.0s ⠿ 06402ac516d6 Pull complete 1.4s ⠿ b077324cb2fc Pull complete 1.6s [+] Running 7/7 ⠿ Network sample-app_default Created 0.1s ⠿ Volume "sample-app_psysh-store" Created 0.0s ⠿ Volume "sample-app_db-store" Created 0.0s ⠿ Container sample-app-web-1 Started 4.0s ⠿ Container sample-app-db-1 Started 4.0s ⠿ Container sample-app-mailpit-1 Started 1.4s ⠿ Container sample-app-app-1 Started 3.7s docker compose exec app composer install Installing dependencies from lock file (including require-dev) Verifying lock file contents can be installed on current platform. Nothing to install, update or remove Generating optimized autoload files > Illuminate\Foundation\ComposerScripts::postAutoloadDump > @php artisan package:discover --ansi INFO Discovering packages. laravel/sail ..................................................................... DONE laravel/sanctum .................................................................. DONE laravel/tinker ................................................................... DONE nesbot/carbon .................................................................... DONE nunomaduro/collision ............................................................. DONE nunomaduro/termwind .............................................................. DONE spatie/laravel-ignition .......................................................... DONE 83 packages you are using are looking for funding. Use the `composer fund` command to find out more! docker compose exec app cp .env.example .env docker compose exec app php artisan key:generate INFO Application key set successfully. docker compose exec app php artisan storage:link ERROR The [public/storage] link already exists. docker compose exec app chmod -R 777 storage bootstrap/cache docker compose exec app php artisan migrate:fresh --seed Dropping all tables ...................................................... 1,521ms DONE INFO Preparing database. Creating migration table ................................................... 306ms DONE INFO Running migrations. 2014_10_12_000000_create_users_table ..................................... 1,343ms DONE 2014_10_12_100000_create_password_reset_tokens_table ....................... 422ms DONE 2019_08_19_000000_create_failed_jobs_table ................................. 296ms DONE 2019_12_14_000001_create_personal_access_tokens_table ...................... 502ms DONE INFO Seeding database.
以下のとおり、指定したバージョンの Node.js をインストールできていることが確認できました。
# r_yamate @ mbp in ~/development/sample-app on git:main x [10:07:57] $ make app docker compose exec app bash root@37aa25accac5:/workspace# node --version v20.5.1 root@37aa25accac5:/workspace# npm --version 10.2.4 root@37aa25accac5:/workspace# npx --version 10.2.4
3. React の開発環境構築
React の開発環境を Laravel の開発環境内に構築します。TypeScript, Sass も追加します。
npm install -D react react-dom @types/react @types/react-dom npm install -D @vitejs/plugin-react npm install -D react-router-dom npm install -D @types/react-router-dom npm install -D typescript npx tsc --init --jsx react-jsx npm install -D sass
コマンド実行時ログ
root@5f8dbf46957f:/workspace# npm install -D react react-dom @types/react @types/react-dom npm install -D @vitejs/plugin-react npm install -D react-router-dom npm install -D @types/react-router-dom npm install -D typescript npx tsc --init --jsx react-jsx npm install -D sass up to date, audited 46 packages in 995ms 6 packages are looking for funding run `npm fund` for details found 0 vulnerabilities added 60 packages, and audited 106 packages in 25s 10 packages are looking for funding run `npm fund` for details found 0 vulnerabilities added 3 packages, and audited 109 packages in 5s 10 packages are looking for funding run `npm fund` for details found 0 vulnerabilities added 3 packages, and audited 112 packages in 6s 10 packages are looking for funding run `npm fund` for details found 0 vulnerabilities added 1 package, and audited 113 packages in 17s 10 packages are looking for funding run `npm fund` for details found 0 vulnerabilities Created a new tsconfig.json with: TS target: es2016 module: commonjs jsx: react-jsx strict: true esModuleInterop: true skipLibCheck: true forceConsistentCasingInFileNames: true You can learn more at https://aka.ms/tsconfig up to date, audited 113 packages in 1s 10 packages are looking for funding run `npm fund` for details found 0 vulnerabilities
package.json を確認してみます。
- 確認:src/package.json
{ "private": true, "type": "module", "scripts": { "dev": "vite", "build": "vite build" }, "devDependencies": { "@types/react": "^18.2.41", "@types/react-dom": "^18.2.17", "@types/react-router-dom": "^5.3.3", "@vitejs/plugin-react": "^4.2.0", "axios": "^1.6.1", "laravel-vite-plugin": "^0.8.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-router-dom": "^6.20.1", "sass": "^1.69.5", "typescript": "^5.3.2", "vite": "^4.0.0" } }
先ほど Docker コンテナでインストールしたパッケージが追加されています。
導入ができているかの検証は、前回の記事同様であるため省略させていただきます。
おわりに
今回は Laravel 10 と React 18 の SPA の開発環境を、ucan-lab/docker-laravel を用いて構築しました。
ありがとうございました。
SIerで12年、転職経験なし。「不満はないけどなんか不安」に向き合って気づいたこと【シニアエンジニアの働き方#6】 | Engineer's Voice by スマレジ #転職 #開発 #エンジニア https://t.co/hrvJi0vn7q
— やまて|Web系エンジニア3年目 (@r_yamate) 2023年11月21日
シニアエンジニアの働き方シリーズ、毎回とても参考になる。まだジュニアエンジニアだけど。
社内の方々のエンジニアキャリアがとても気になる今日この頃です。