<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Docker &#8211; エンジニア見習い</title>
	<atom:link href="https://otonan-syusyoku.work/archives/tag/docker/feed" rel="self" type="application/rss+xml" />
	<link>https://otonan-syusyoku.work</link>
	<description>三流プログラマー</description>
	<lastBuildDate>Wed, 25 Feb 2026 08:34:10 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://otonan-syusyoku.work/wp-content/uploads/2023/10/cropped-名称未設定のデザイン-16-32x32.png</url>
	<title>Docker &#8211; エンジニア見習い</title>
	<link>https://otonan-syusyoku.work</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>マルチステージビルドでイメージサイズを劇的に削減できるべ</title>
		<link>https://otonan-syusyoku.work/archives/2165</link>
					<comments>https://otonan-syusyoku.work/archives/2165#respond</comments>
		
		<dc:creator><![CDATA[hrokig2]]></dc:creator>
		<pubDate>Wed, 19 Nov 2025 04:09:20 +0000</pubDate>
				<category><![CDATA[インフラ]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[業務]]></category>
		<guid isPermaLink="false">https://otonan-syusyoku.work/?p=2165</guid>

					<description><![CDATA[PHPアプリケーションのコンテナイメージを作成する際、ビルドに必要なツール（Composer、各種コンパイラなど）をすべて含めてしまうと、イメージが肥大化し、セキュリティリスクも増大します。 この課題を解決するのが、コン [&#8230;]]]></description>
										<content:encoded><![CDATA[<div id="model-response-message-contentr_700d418a97f56345" class="markdown markdown-main-panel stronger enable-updated-hr-color" dir="ltr" aria-live="polite" aria-busy="false">
<p>PHPアプリケーションのコンテナイメージを作成する際、ビルドに必要なツール（Composer、各種コンパイラなど）をすべて含めてしまうと、イメージが肥大化し、セキュリティリスクも増大します。</p>
<p>この課題を解決するのが、コンテナビルドの効率を最大化する技術、<b>マルチステージビルド</b>です。</p>
<h2>マルチステージビルドとは？</h2>
<p>マルチステージビルドとは、<b>一つの<code>Dockerfile</code>内で複数の<code>FROM</code>命令（ステージ）を定義し、最終的なイメージにデプロイに必要なファイルだけをコピーする</b>手法です。</p>
<h3>役割分担</h3>
<ol start="1">
<li><b>ビルドステージ (Build Stage):</b>
<ul>
<li><b>目的:</b> アプリケーションのビルドと依存関係の解決。</li>
<li><b>使用イメージ:</b> <b>大きなイメージ</b>（例: <code>composer:latest</code>、<code>php:8.3-fpm</code>など）。</li>
<li><b>作業:</b> Composerによる依存パッケージのインストール、フロントエンドアセットのコンパイル、テストの実行などを行います。</li>
<li><b>特徴:</b> このステージは最終的なデプロイには使用されません。</li>
</ul>
</li>
<li><b>最終ステージ (Final Stage):</b>
<ul>
<li><b>目的:</b> アプリケーションの実行環境の構築。</li>
<li><b>使用イメージ:</b> <b>軽量なイメージ</b>（例: <code>php:8.3-fpm-alpine</code>、<code>distroless</code>など）。</li>
<li><b>作業:</b> ビルドステージで生成された<b>成果物</b>（例: <code>vendor</code>ディレクトリ、コンパイル済みバイナリ、PHPコード）のみをコピーします。</li>
</ul>
</li>
</ol>
<h3>メリット</h3>
<ul>
<li><b>イメージサイズの劇的な削減:</b> ビルドツールやキャッシュ、開発用の依存関係が最終イメージから完全に除外されます。</li>
<li><b>セキュリティ向上:</b> 最終イメージが最小限の構成になるため、攻撃対象となる領域が縮小します。</li>
<li><b>ビルド時間の短縮:</b> 軽量なイメージを使用することで、プル時間が短くなります。</li>
</ul>
<h2>PHPアプリケーションでのマルチステージビルド</h2>
<p>PHPアプリケーションの典型的なマルチステージビルドは、<b>Composerによる依存関係の解決</b>を分離することに焦点を当てます。</p>
<h3>Dockerfile</h3>
<p>以下の<code>Dockerfile</code>は、Composerで依存関係を解決するステージと、それを使ってアプリケーションを実行する最小限のステージに分離しています。</p>
<pre class="ng-tns-c519592647-2110"><code># =============================================</code>
<code># ステージ1：build_stage（依存関係の解決）</code>
<code># =============================================</code>
<code>FROM composer:latest AS build_stage 
WORKDIR /app 
# 先に依存関係ファイルだけをコピー（キャッシュ効率化のため）
COPY composer.json composer.lock ./ 
# 本番環境用に最適化してインストール 
</code><code># --no-dev: 開発用パッケージを除外</code>
<code># --optimize-autoloader: オートローダーを最適化して高速化 
</code><code>RUN composer install \</code>
<code>--no-dev \</code>
<code>--no-interaction \</code>
<code>--optimize-autoloader 
</code><code># =============================================</code>
<code># ステージ2：final_stage（最小限の実行環境）</code>
<code># =============================================</code>
<code># 軽量なAlpine LinuxベースのPHP-FPMイメージを使用</code>
<code>FROM php:8.3-fpm-alpine AS final_stage 
</code><code># セキュリティ：実行用の非特権ユーザーを作成</code>
<code>RUN adduser -D appuser</code>
<code>USER appuser
</code><code>WORKDIR /var/www/html
</code><code># ステージ1からvendorディレクトリのみをコピー</code>
<code># --chown で所有権を同時に変更するのがポイント</code>
<code>COPY --from=build_stage --chown=appuser:appuser /app/vendor ./vendor
</code><code># アプリケーションのソースコードをコピー</code>
<code>COPY --chown=appuser:appuser . .
 </code>
<code># PHP-FPMを起動 
</code><code>EXPOSE 9000</code><code>
CMD ["php-fpm"]</code><span style="font-size: 14px; background-color: #dddddd;">

</span></pre>
</div>
<h3>実行手順</h3>
<ol start="1">
<li><b>プロジェクトルートに配置:</b> 上記の<code>Dockerfile</code>をプロジェクトのルートディレクトリに配置します。</li>
<li><b><code>docker build</code>を実行:</b> 通常通り<code>docker build</code>コマンドを実行するだけです。Dockerエンジンが自動的にマルチステージビルドを処理します。</li>
</ol>
<pre class="line-numbers"><code class="language-php">docker build -t my-php-app:prod .</code></pre>
<h3>PHPでのポイント</h3>
<ol start="1">
<li><b><code>composer_stage</code>の利用:</b> Composerをインストールする手間を省くため、公式の<code>composer</code>イメージをビルダーとして使うのが最も効率的です。</li>
<li><b><code>--no-dev</code>:</b> 開発時のみ必要なパッケージ（テストフレームワークなど）は最終イメージに含めないようにします。</li>
<li><b><code>USER nonroot</code>:</b> セキュリティのため、最終ステージでは必ず<code>root</code>権限を放棄し、<b>非特権ユーザー</b>でアプリケーションを実行するように設定しましょう。（これにより、低ポート番号の使用には制約が生じますが、セキュリティが大幅に向上します）</li>
<li><b><code>COPY --from</code>の活用:</b> この命令が全てです。Composerの巨大なキャッシュやビルドツール群を最終イメージから排除し、必要な<code>vendor</code>ディレクトリだけをクリーンにコピーします。</li>
</ol>
<p>マルチステージビルドは、軽量で安全なPHPコンテナイメージを作成するための必須技術です。ぜひあなたのプロジェクトに導入してください。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://otonan-syusyoku.work/archives/2165/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>unprivileged かつ distroless なイメージ について理解しようぜ</title>
		<link>https://otonan-syusyoku.work/archives/2156</link>
					<comments>https://otonan-syusyoku.work/archives/2156#respond</comments>
		
		<dc:creator><![CDATA[hrokig2]]></dc:creator>
		<pubDate>Wed, 19 Nov 2025 03:50:41 +0000</pubDate>
				<category><![CDATA[インフラ]]></category>
		<category><![CDATA[生涯独学]]></category>
		<category><![CDATA[ALB]]></category>
		<category><![CDATA[AWS]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[nginx]]></category>
		<guid isPermaLink="false">https://otonan-syusyoku.work/?p=2156</guid>

					<description><![CDATA[コンテナ技術は現代のアプリケーション開発・運用に欠かせないものとなりましたが、コンテナを運用する上で「セキュリティ」と「イメージサイズ」は常に大きな課題として立ちはだかります。 あなたのコンテナイメージは本当に安全で、そ [&#8230;]]]></description>
										<content:encoded><![CDATA[<div _ngcontent-ng-c2987940602="" inline-copy-host="" class="markdown markdown-main-panel stronger enable-updated-hr-color" id="model-response-message-contentr_c303978cc0204370" aria-live="polite" aria-busy="false" dir="ltr">
<p>コンテナ技術は現代のアプリケーション開発・運用に欠かせないものとなりましたが、コンテナを運用する上で「セキュリティ」と「イメージサイズ」は常に大きな課題として立ちはだかります。</p>
<p>あなたのコンテナイメージは本当に安全で、そして最小限に保たれていますか？</p>
<p>&nbsp;</p>
<p>多くの開発者は、手軽さからコンテナを<code>root</code>（管理者）権限で実行し、また開発やデバッグに不要なOSパッケージをそのまま含めてしまいがちです。</p>
<p>これが、<b>セキュリティリスクの増大</b>と、<b>イメージサイズの肥大化</b>を招く原因となります。</p>
<p>この記事では、この課題を解決するための <strong>Unprivileged（非特権ユーザー実行）</strong>と<strong>Distroless（ディストロレス）</strong>イメージについて、その概念から実践的な使い方、そして運用上の注意点までを解説します。</p>
<h2>そもそも「Unprivileged」と「Distroless」とは何か？</h2>
<h3>1. Unprivileged (非特権ユーザー実行) とは？</h3>
<p><b>Unprivileged実行</b>とは、「最小特権の原則」をコンテナで実践することです。</p>
<ul>
<li><b>定義<br />
</b>コンテナ内のメインプロセスを<code>root</code>ユーザー（UID 0）ではなく、一般ユーザー（非特権ユーザー）として実行すること。</li>
<li><b>メリット<br />
</b>コンテナが何らかの理由で侵害されたり、エスケープ（コンテナの外側にあるホストOSへの侵入）が試みられたりした場合でも、プロセスが持つ権限が最小限に抑えられます。<br />
これにより、ホストシステムへの影響範囲を劇的に制限できます。</li>
<li><b>実現方法<br />
</b>Dockerfile内で<code>USER</code>命令を使用して、コンテナの実行ユーザーを切り替えます。</li>
</ul>
<h3>2. Distroless (ディストロレス) イメージとは？</h3>
<p><b>Distrolessイメージ</b>とは、セキュリティとサイズを極限まで追求したベースイメージです。</p>
<ul>
<li><b>定義<br />
</b>OSディストリビューション（Linux）の要素、具体的には<code>bash</code>、<code>apt</code>、<code>ls</code>といった一般的なシェルやパッケージ管理ツール<b>を</b>意図的に含めない、アプリケーション実行に必要な最小限のランタイムとライブラリのみで構成されたコンテナイメージです。</li>
<li><b>「通常のイメージ」との違い<br />
</b>通常のイメージ（例: <code>ubuntu:latest</code>）には多くの汎用ツールが含まれていますが、Distrolessイメージにはそれらが一切含まれていません。デバッグツールさえないため、その名（Distro-less = ディストリビューションがない）が示す通り、極めて軽量です。</li>
</ul>
<p><a href="https://otonan-syusyoku.work/archives/1674/lets-go" rel="attachment wp-att-1680"><img fetchpriority="high" decoding="async" src="https://otonan-syusyoku.work/wp-content/uploads/2024/02/Lets-GO.png" alt="Let&#96;s GO" width="1000" height="500" class="aligncenter size-full wp-image-1680" srcset="https://otonan-syusyoku.work/wp-content/uploads/2024/02/Lets-GO.png 1000w, https://otonan-syusyoku.work/wp-content/uploads/2024/02/Lets-GO-300x150.png 300w, https://otonan-syusyoku.work/wp-content/uploads/2024/02/Lets-GO-768x384.png 768w" sizes="(max-width: 1000px) 100vw, 1000px" /></a></p>
<h2>Unprivileged &amp; Distroless を組み合わせるメリット</h2>
<p>この二つのアプローチを組み合わせることで、コンテナの運用は次のレベルに引き上げられます。</p>
<h3>1. 圧倒的なセキュリティ向上</h3>
<ul>
<li><b>攻撃対象領域の削減<br />
</b>Distroless化により、イメージに含まれるバイナリやライブラリの数が最小限になります。<br />
その結果、<b>既知の脆弱性（CVE）を持つ可能性のあるパッケージが激減</b>し、攻撃対象となる領域を大幅に縮小します。</li>
<li><b>権限昇格リスクの低減<br />
</b>Unprivileged実行により、仮にコンテナに侵入されても、攻撃者がホストシステムで<code>root</code>権限を得るのが極めて困難になります。</li>
</ul>
<h3>2. イメージサイズの劇的な削減</h3>
<ul>
<li>不要なOSレイヤーやツールがないため、イメージサイズは通常のベースイメージに比べて<b>数百MB単位で削減</b>されることがあるらしい</li>
<li>これにより、レジストリへのプッシュ/プル時間が短縮され、デプロイ時間の高速化、そしてストレージコストの削減につながります。</li>
</ul>
<h3>3. ビルド時間の短縮と効率化</h3>
<p>ベースイメージが小さくなることで、CI/CDパイプラインでのダウンロード時間が短縮され、コンテナのビルドプロセス全体が効率化されます。</p>
<h2>Unprivileged &amp; Distroless なコンテナの使い方</h2>
<p>Unprivileged &amp; Distrolessを実現する最も一般的な方法は、<b>マルチステージビルド</b>を利用することです。</p>
<h3>1. Distroless イメージの基本構造</h3>
<ol start="1">
<li><b>Build Stage<br />
</b>開発に必要なコンパイラ、パッケージマネージャなどを含む通常のイメージ（例: <code>golang:latest</code>, <code>node:latest</code>）を使い、アプリケーションのビルドや依存関係のインストールを行います。</li>
<li><b>Final Stage<br />
</b>Distrolessイメージをベースとし、Build Stageで生成された<b>最終的なバイナリ</b>や<b>必要なランタイムファイル</b>だけをコピーします。</li>
</ol>
<h3>2. Unprivileged実行の設定</h3>
<p>Distrolessイメージの多く（例: <code>gcr.io/distroless/...</code>）は、セキュリティのため、デフォルトで<code>非root</code>ユーザー（例: <code>nonroot</code>）が設定されています。</p>
<p>もしご自身でベースイメージから構築する場合、Dockerfileに以下のコマンドを追加してユーザーを切り替えます。</p>
<p><response-element class="" ng-version="0.0.0-PLACEHOLDER"><code-block _nghost-ng-c519592647="" class="ng-tns-c519592647-2060 ng-star-inserted"></code-block></response-element></p>
<div _ngcontent-ng-c519592647="" class="code-block ng-tns-c519592647-2060 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation" jslog="223238;track:impression,attention;BardVeMetadataKey:[[&quot;r_c303978cc0204370&quot;,&quot;c_2e6b4137d5b58b23&quot;,null,&quot;rc_9ed9dae3948441fd&quot;,null,null,&quot;ja&quot;,null,1,null,null,1,0]]">
<div _ngcontent-ng-c519592647="" class="formatted-code-block-internal-container ng-tns-c519592647-2060">
<div _ngcontent-ng-c519592647="" class="animated-opacity ng-tns-c519592647-2060">
<pre _ngcontent-ng-c519592647="" class="ng-tns-c519592647-2060"># ユーザーを作成し、パーミッションを設定
RUN adduser --disabled-password --gecos "" appuser

# 実行ユーザーを一般ユーザーに切り替える
USER appuser</pre>
</div>
</div>
</div>
<p><a href="https://otonan-syusyoku.work/archives/1519/%e3%81%ae" rel="attachment wp-att-1540"><img decoding="async" src="https://otonan-syusyoku.work/wp-content/uploads/2023/12/の.png" alt="title" width="1000" height="500" class="aligncenter size-full wp-image-1540" srcset="https://otonan-syusyoku.work/wp-content/uploads/2023/12/の.png 1000w, https://otonan-syusyoku.work/wp-content/uploads/2023/12/の-300x150.png 300w, https://otonan-syusyoku.work/wp-content/uploads/2023/12/の-768x384.png 768w" sizes="(max-width: 1000px) 100vw, 1000px" /></a></p>
<h2>運用上の注意点：非特権ユーザーとポート番号の壁</h2>
<p>UnprivilegedコンテナをECS（または任意のLinuxホスト）で運用する際、セキュリティの恩恵と引き換えに、ある<b>実用上の課題</b>に直面します。</p>
<h3>1. ポート1024未満のバインドはroot権限が必要</h3>
<p>Linux OSのセキュリティ原則により、Webサーバーなどで一般的に使われる<b>ポート番号1024未満</b>（ウェルノウンポート、例: HTTPの<code>80</code><b>、</b>HTTPSの<code>443</code><b>）にバインドするには、</b><code>root</code>権限（特権）が必要です。</p>
<p>あなたがECSでUnprivilegedかつDistrolessなNginxイメージを使った際、Nginxがデフォルトで<code>80</code>番ポートを使おうとすると、権限がないため「<b>Permission Denied</b>」といった<b>エラーが発生し、コンテナの起動に失敗</b>してしまいます。</p>
<h3>2. ECS/Fargate環境での具体的な解決策</h3>
<p>この問題を解決しつつ、Unprivilegedのセキュリティメリットを維持するには、以下の方法が最も推奨されます。</p>
<ol start="1">
<li>アプリケーション側のポート変更:Webサーバー（Nginxなど）の設定ファイルを変更し、1024番以上のポート（例: 8080、8081）で待ち受けるように設定を変更します。</li>
<li><b>ロードバランサー (ALB) でのポートマッピング:</b>
<ul>
<li>ECS（Fargate）の<b>タスク定義</b>で、コンテナが使用するポートを<code>8080</code>などに設定します。</li>
<li><b>Application Load Balancer (ALB)</b> を利用し、ALBは外部からのアクセスを<code>80</code>番（標準HTTP）で受けます。</li>
<li>ALBは、内部のECSタスクグループに対しては<code>8080</code>番でルーティングします。</li>
</ul>
</li>
</ol>
<p>これにより、コンテナ内部は非特権ユーザーで安全に運用され、外部ユーザーはポート番号を意識することなくWebサイトにアクセスできるようになります。</p>
<h2>次世代コンテナの標準へ</h2>
<p>UnprivilegedとDistrolessの組み合わせは、<b>コンテナのセキュリティ基準</b>と<b>デプロイ効率</b>を大きく引き上げる、次世代コンテナの標準パターンです。</p>
<ul>
<li><b>Distroless:</b> 攻撃対象領域とイメージサイズを最小化。</li>
<li><b>Unprivileged:</b> 権限昇格リスクを最小化。</li>
</ul>
<p>特にECSなどの本番環境で運用する際は、<b>ポート1024未満の制限</b>に注意を払い、<b>ロードバランサー</b>を活用して安全かつ効率的な構成を構築しましょう。</p>
<p>あなたのプロジェクトも、今日からこの強力なセキュリティパターンに移行してみませんか？</p>
</div>
]]></content:encoded>
					
					<wfw:commentRss>https://otonan-syusyoku.work/archives/2156/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Laravel+Inertia+ReactをECSで動かしたい！ NginxとPHP-FPMのコンテナ分離</title>
		<link>https://otonan-syusyoku.work/archives/2153</link>
					<comments>https://otonan-syusyoku.work/archives/2153#respond</comments>
		
		<dc:creator><![CDATA[hrokig2]]></dc:creator>
		<pubDate>Tue, 28 Oct 2025 05:24:52 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[インフラ]]></category>
		<category><![CDATA[AWS]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[LAMP]]></category>
		<category><![CDATA[Laravel]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[React]]></category>
		<category><![CDATA[ネットワーク]]></category>
		<guid isPermaLink="false">https://otonan-syusyoku.work/?p=2153</guid>

					<description><![CDATA[Laravel + Inertia (React/Vue) の組み合わせは、SPA（シングルページアプリケーション）の体験とサーバーサイド（Laravel）の書きやすさを両立できる、非常に強力な構成です。 しかし、ローカ [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Laravel + Inertia (React/Vue) の組み合わせは、SPA（シングルページアプリケーション）の体験とサーバーサイド（Laravel）の書きやすさを両立できる、非常に強力な構成です。</p>
<p>しかし、ローカルのDocker Compose環境では問題なく動作しても、AWSのECS Fargateのような本番環境にデプロイしようとすると、いくつかの疑問に直面します。</p>
<ul>
<li>「NginxとPHP-FPMコンテナはどう連携させるのがベスト？」</li>
<li>「<code>fastcgi_pass</code> ってローカルと設定を変える必要ある？」</li>
<li>「InertiaでビルドしたReactのJS/CSSファイルは、結局どのコンテナに置くのが正解？」</li>
</ul>
<p>この記事では、<code>fastcgi_pass</code> の基本から、ECS Fargateでの最適なコンテナ構成、そしてInertia/Reactプロジェクト特有の「静的ファイルの配置場所」問題までを、順を追って解説します。</p>
<h2>fastcgi_pass とは？</h2>
<h3>NginxとPHP-FPMの「橋渡し」</h3>
<p>まず基本のおさらいです。Nginxは高性能なWebサーバーですが、それ自体はPHPコードを実行できません。<br />
一方、PHP-FPMはPHPコードを実行することに特化したプロセス（サーバー）です。</p>
<p>Nginxがクライアント（ブラウザ）から <code>.php</code> ファイルへのリクエストを受け取ったとき、そのリクエストをPHP-FPMに処理してもらう必要があります。</p>
<p>このとき、Nginxの設定ファイル（<code>nginx.conf</code>）で、<b>「どのPHP-FPMに処理を依頼するか」の宛先を指定する</b>のが <code>fastcgi_pass</code> ディレクティブです。</p>
<div _ngcontent-ng-c535465467="" class="code-block ng-tns-c535465467-470 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation" jslog="223238;track:impression,attention;BardVeMetadataKey:[[&quot;r_4fea32b244968dc8&quot;,&quot;c_103da6cb53c10bc2&quot;,null,&quot;rc_8751fdc7f6beda59&quot;,null,null,&quot;ja&quot;,null,1,null,null,1,0]]">
<div _ngcontent-ng-c535465467="" class="formatted-code-block-internal-container ng-tns-c535465467-470">
<div _ngcontent-ng-c535465467="" class="animated-opacity ng-tns-c535465467-470">
<pre _ngcontent-ng-c535465467="" class="ng-tns-c535465467-470"><code _ngcontent-ng-c535465467="" role="text" data-test-id="code-content" class="code-container formatted ng-tns-c535465467-470"><span class="hljs-attribute">location</span> <span class="hljs-regexp">~ \.php$</span> {
    <span class="hljs-comment"># ...</span>
    <span class="hljs-comment"># ↓ この一行が「橋渡し」の指定</span>
    <span class="hljs-attribute">fastcgi_pass</span> php-fpm-server:<span class="hljs-number">9000</span>; 
}
</code></pre>
</div>
</div>
</div>
<p>&nbsp;</p>
<h2>ローカル開発 (Docker Compose) での構成</h2>
<p>ローカル開発では、「1コンテナ1責務」の原則に従い、NginxとPHP-FPMを別々のコンテナとして <code>docker-compose.yml</code> で定義するのが一般的です。</p>
<div _ngcontent-ng-c535465467="" class="code-block ng-tns-c535465467-471 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation" jslog="223238;track:impression,attention;BardVeMetadataKey:[[&quot;r_4fea32b244968dc8&quot;,&quot;c_103da6cb53c10bc2&quot;,null,&quot;rc_8751fdc7f6beda59&quot;,null,null,&quot;ja&quot;,null,1,null,null,1,0]]">
<div _ngcontent-ng-c535465467="" class="formatted-code-block-internal-container ng-tns-c535465467-471">
<div _ngcontent-ng-c535465467="" class="animated-opacity ng-tns-c535465467-471">
<pre _ngcontent-ng-c535465467="" class="ng-tns-c535465467-471"><code _ngcontent-ng-c535465467="" role="text" data-test-id="code-content" class="code-container formatted ng-tns-c535465467-471"><span class="hljs-comment"># docker-compose.yml (抜粋)</span>
<span class="hljs-attr">version:</span> <span class="hljs-string">'3'</span>
<span class="hljs-attr">services:</span>
  <span class="hljs-comment"># Nginxコンテナ</span>
  <span class="hljs-attr">nginx:</span>
    <span class="hljs-attr">image:</span> <span class="hljs-string">nginx:alpine</span>
    <span class="hljs-attr">ports:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">"80:80"</span>
    <span class="hljs-attr">volumes:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">./nginx.conf:/etc/nginx/conf.d/default.conf</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">./laravel-project:/var/www/html</span>

  <span class="hljs-comment"># PHP-FPMコンテナ</span>
  <span class="hljs-attr">php:</span>
    <span class="hljs-attr">build:</span> <span class="hljs-string">.</span> <span class="hljs-comment"># PHP-FPMとLaravelコードを含むDockerfile</span>
    <span class="hljs-attr">volumes:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">./laravel-project:/var/www/html</span>
</code></pre>
</div>
</div>
</div>
<p>&nbsp;</p>
<p>この構成では、NginxコンテナとPHPコンテナは <b>別々のネットワーク空間</b> に存在します。Docker Composeが提供する内部ネットワークを介して、サービス名で通信します。</p>
<p>したがって、NginxコンテナからPHPコンテナへは、<code>php</code> というサービス名（ホスト名）を使ってアクセスします。</p>
<div _ngcontent-ng-c535465467="" class="code-block ng-tns-c535465467-472 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation" jslog="223238;track:impression,attention;BardVeMetadataKey:[[&quot;r_4fea32b244968dc8&quot;,&quot;c_103da6cb53c10bc2&quot;,null,&quot;rc_8751fdc7f6beda59&quot;,null,null,&quot;ja&quot;,null,1,null,null,1,0]]">
<div _ngcontent-ng-c535465467="" class="formatted-code-block-internal-container ng-tns-c535465467-472">
<div _ngcontent-ng-c535465467="" class="animated-opacity ng-tns-c535465467-472">
<pre _ngcontent-ng-c535465467="" class="ng-tns-c535465467-472"><code _ngcontent-ng-c535465467="" role="text" data-test-id="code-content" class="code-container formatted ng-tns-c535465467-472"><span class="hljs-comment"># nginx.conf (Docker Compose用)</span>
<span class="hljs-attribute">location</span> <span class="hljs-regexp">~ \.php$</span> {
    <span class="hljs-comment"># ...</span>
    <span class="hljs-comment"># 'php' サービス（コンテナ）の 9000番ポートに転送</span>
    <span class="hljs-attribute">fastcgi_pass</span> php:<span class="hljs-number">9000</span>;
}
</code></pre>
</div>
</div>
</div>
<p>&nbsp;</p>
<p>（※ このTCP/IP通信によるパフォーマンスやセキュリティの懸念は、コンテナ間通信がDockerの内部ネットワークに限定されていれば、実用上ほとんど問題になりません。）</p>
<h2>【1タスク2コンテナ】本番 (ECS Fargate) での構成：</h2>
<p>さて、本題のECS Fargateです。<br />
ECSでは、<code>docker-compose.yml</code> に相当するものとして「タスク定義 (Task Definition)」を使います。</p>
<p>ここで重要なキーポイントは、<strong>「1つのタスク定義の中で、NginxコンテナとPHP-FPMコンテナの2つを定義する」</strong>ことです。</p>
<p><strong>これら2つのコンテナは、1セットで「Webアプリケーションサーバー」</strong>として機能します。</p>
<h3>ECS Fargateでのfastcgi_passはどうなる？</h3>
<p>ECSの同一タスク内で実行されるコンテナは、<b>同じネットワーク空間（ネットワークモード <code>awsvpc</code>）を共有します</b>。</p>
<p>これは、Nginxコンテナから見ると、PHP-FPMコンテナが「他人」ではなく、「自分自身（localhost）」として見えることを意味します。</p>
<p>したがって、ECS Fargate用のNginxイメージに含める <code>nginx.conf</code> の設定は、以下のようになります。</p>
<div _ngcontent-ng-c535465467="" class="code-block ng-tns-c535465467-473 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation" jslog="223238;track:impression,attention;BardVeMetadataKey:[[&quot;r_4fea32b244968dc8&quot;,&quot;c_103da6cb53c10bc2&quot;,null,&quot;rc_8751fdc7f6beda59&quot;,null,null,&quot;ja&quot;,null,1,null,null,1,0]]">
<div _ngcontent-ng-c535465467="" class="formatted-code-block-internal-container ng-tns-c535465467-473">
<div _ngcontent-ng-c535465467="" class="animated-opacity ng-tns-c535465467-473">
<pre _ngcontent-ng-c535465467="" class="ng-tns-c535465467-473"><code _ngcontent-ng-c535465467="" role="text" data-test-id="code-content" class="code-container formatted ng-tns-c535465467-473"><span class="hljs-comment"># nginx.conf (ECS Fargate用)</span>
<span class="hljs-attribute">location</span> <span class="hljs-regexp">~ \.php$</span> {
    <span class="hljs-comment"># ...</span>
    <span class="hljs-comment"># サービス名ではなく、localhost (127.0.0.1) を指定する</span>
    <span class="hljs-attribute">fastcgi_pass</span> <span class="hljs-number">127.0.0.1:9000</span>;
}
</code></pre>
</div>
</div>
</div>
<p>&nbsp;</p>
<h3>タスク定義のイメージ</h3>
<p>タスク定義では、以下のように設定します。</p>
<ul>
<li><b>コンテナ-A: <code>php-fpm-container</code></b>
<ul>
<li>イメージ: （Laravelコードを含むPHP-FPMイメージ）</li>
<li>ポートマッピング: <b>なし</b> (外部に公開する必要はないため)</li>
</ul>
</li>
<li><b>コンテナ-B: <code>nginx-container</code></b>
<ul>
<li>イメージ: （設定済みのnginx.confと静的ファイルを含むNginxイメージ）</li>
<li>ポートマッピング: <b><code>80:80</code></b> (ALBからのトラフィックを受け取るため)</li>
</ul>
</li>
</ul>
<p>ALB（ロードバランサー）からのトラフィックはNginxコンテナが受け取り、必要に応じて <code>localhost:9000</code> を介してPHP-FPMコンテナに処理を渡します。</p>
<h2>Inertia/Reactのビルドファイルはどこに置く？</h2>
<p>ここで、Inertia/React構成特有の問題に直面します。</p>
<p>「InertiaはLaravel（PHP）がビューを配信する仕組みだから、<code>npm run build</code> で生成された <code>public/build</code> フォルダは、PHP-FPMコンテナにだけ置けば良いのでは？」</p>
<p>これはよくある誤解ですが、<b>パフォーマンスと責務分離の観点から、ビルドした静的ファイル（JS/CSS）はNginxコンテナに配置するのが正解</b>です。</p>
<p>この理由を理解するために、Inertiaのページが読み込まれる2段階のフローを見てみましょう。</p>
<h3>ステップ1: HTMLシェルのリクエスト (PHP-FPMが処理)</h3>
<ol start="1">
<li>ブラウザが <code>https://example.com/dashboard</code> にアクセスします。</li>
<li>ALB → Nginxコンテナがリクエストを受け取ります。</li>
<li>NginxはこれがPHPのリクエストだと判断し、<code>fastcgi_pass 127.0.0.1:9000</code> を使って<b>PHP-FPMコンテナ</b>に転送します。</li>
<li>PHP (Laravel) が起動し、Inertiaは <code>app.blade.php</code> をレンダリングしようとします。</li>
<li>このとき、PHPは <b><code>public/build/manifest.json</code></b> を読み取り、HTMLに含めるべきJS/CSSのファイル名を特定します。</li>
<li>PHPは以下のようなHTMLの「ガワ」を<b>生成</b>し、Nginx経由でブラウザに返します。
<p><response-element class="" ng-version="0.0.0-PLACEHOLDER"><code-block _nghost-ng-c535465467="" class="ng-tns-c535465467-474 ng-star-inserted"></p>
<div _ngcontent-ng-c535465467="" class="code-block ng-tns-c535465467-474 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation" jslog="223238;track:impression,attention;BardVeMetadataKey:[[&quot;r_4fea32b244968dc8&quot;,&quot;c_103da6cb53c10bc2&quot;,null,&quot;rc_8751fdc7f6beda59&quot;,null,null,&quot;ja&quot;,null,1,null,null,1,0]]">
<div _ngcontent-ng-c535465467="" class="formatted-code-block-internal-container ng-tns-c535465467-474">
<div _ngcontent-ng-c535465467="" class="animated-opacity ng-tns-c535465467-474">
<pre _ngcontent-ng-c535465467="" class="ng-tns-c535465467-474"><code _ngcontent-ng-c535465467="" role="text" data-test-id="code-content" class="code-container formatted ng-tns-c535465467-474"><span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"/build/assets/app.12345.js"</span> <span class="hljs-attr">defer</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/build/assets/app.67890.css"</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"app"</span> <span class="hljs-attr">data-page</span>=<span class="hljs-string">"..."</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
</div>
</div>
</div>
<p></code-block></response-element></li>
</ol>
<h3>ステップ2: 静的アセット(JS/CSS)のリクエスト (Nginxが処理)</h3>
<ol start="1">
<li>ブラウザは、ステップ1で受け取ったHTMLを解析します。</li>
<li>「<code>/build/assets/app.12345.js</code> と <code>/build/assets/app.67890.css</code> が必要だ」と判断し、ブラウザは<b>別途2回のリクエスト</b>をサーバーに送信します。</li>
<li><b>このリクエストは、もはやPHPとは全く関係ありません。</b></li>
<li>ALB → <b>Nginxコンテナ</b>がこの2つのリクエストを受け取ります。</li>
<li>Nginxは「自分の管理下（<code>public</code> フォルダ）にそのファイルがあるか？」を探します。</li>
<li><b>Nginxコンテナに <code>public/build/</code> 以下の実体ファイルが存在するため</b>、NginxはPHP-FPMを起動することなく、それらの静的ファイルを<b>超高速で</b>ブラウザに直接返します。</li>
</ol>
<p>もし、NginxコンテナにJS/CSSファイルがなければ、このリクエストもPHP-FPMに転送されてしまい、「JSファイルを取得するためだけにLaravelを起動する」という深刻なパフォーマンスボトルネックが発生します。</p>
<h3>CI/CDでのベストプラクティス</h3>
<p>上記2ステップから、CI/CDパイプラインでDockerイメージをビルドする際は、以下の構成が最適です。</p>
<ol start="1">
<li><code>npm run build</code> を実行し、<code>public/build</code> ディレクトリを生成します。</li>
<li><b>PHP-FPMイメージのビルド:</b>
<ul>
<li>Laravelのコード（<code>app/</code>, <code>routes/</code> など）をコピーします。</li>
<li>ステップ1のために <b><code>public/build/manifest.json</code></b> をコピーします。（リンク生成に必要）</li>
</ul>
</li>
<li><b>Nginxイメージのビルド:</b>
<ul>
<li><code>nginx.conf</code> をコピーします。</li>
<li>ステップ2のために <b><code>public</code> フォルダ全体</b>（<code>index.php</code> と、<code>public/build</code> 以下の <b>全てのJS/CSSファイル</b> を含む）をコピーします。（静的アセットの配信用）</li>
</ul>
</li>
</ol>
<h3><b>結論</b></h3>
<p><code>manifest.json</code> はPHP-FPMコンテナに、JS/CSSの実体ファイルはNginxコンテナに必要です。</p>
<p>両方のイメージに <code>public</code> フォルダ（または <code>public/build</code>）全体をコピーするのが、最もシンプルで確実な方法です。</p>
<h2>まとめ</h2>
<p>ECS Fargateで Laravel + Inertia + React 構成を動かすための要点をまとめます。</p>
<ol start="1">
<li><b>構成</b>: 「1タスク2コンテナ（Nginx + PHP-FPM）」構成を採用します。</li>
<li><b><code>fastcgi_pass</code></b>: NginxからPHP-FPMへの通信は、同一タスク内のため <code>fastcgi_pass 127.0.0.1:9000;</code> を指定します。</li>
<li><b>静的ファイル</b>: ビルドしたJS/CSSは、パフォーマンス最適化のためNginxコンテナに配置し、Nginxから直接配信させます。</li>
<li><b><code>manifest.json</code></b>: HTMLシェル生成のため、PHP-FPMコンテナにも <code>manifest.json</code> が必要です。</li>
</ol>
<p>この構成により、PHP-FPMは動的処理に専念し、Nginxは静的ファイルの高速配信に専念するという、「1コンテナ1責務」のメリットを最大限に活かした、スケーラブルな本番環境を構築できます。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://otonan-syusyoku.work/archives/2153/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>【Laravel】MinIO にputできない問題が情けなさ過ぎた</title>
		<link>https://otonan-syusyoku.work/archives/1839</link>
					<comments>https://otonan-syusyoku.work/archives/1839#respond</comments>
		
		<dc:creator><![CDATA[hrokig2]]></dc:creator>
		<pubDate>Sat, 17 Aug 2024 08:06:12 +0000</pubDate>
				<category><![CDATA[仕事の独り言]]></category>
		<category><![CDATA[AWS]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[Laravel]]></category>
		<guid isPermaLink="false">https://otonan-syusyoku.work/?p=1839</guid>

					<description><![CDATA[概要 個人開発で使用している以下スタックで画像を保存できない問題がおきた。 Laravel10 MinIO(S3の代わり) Intervention IMage 3 調査 Intervention IMage Inter [&#8230;]]]></description>
										<content:encoded><![CDATA[<h2>概要</h2>
<p>個人開発で使用している以下スタックで画像を保存できない問題がおきた。</p>
<ul>
<li>Laravel10</li>
<li>MinIO(S3の代わり)</li>
<li>Intervention IMage 3</li>
</ul>
<h2>調査</h2>
<h3>Intervention IMage</h3>
<p>Intervention IMage がVersion2 → Version3 で大きく変わったこともあり、使用法を疑ったが、何ら問題はなかった。</p>
<p>debug等の値を見て見たが、問題なし。。。</p>
<pre class="line-numbers"><code class="language-php">    /**
     * 画像をリサイズする.
     *
     * @param \Illuminate\Http\UploadedFile $file
     * @return \Intervention\Image\Interfaces\ImageInterface
     */
    public function resize(UploadedFile $file): ImageInterface
    {
        return $this-&gt;ImageManager
            -&gt;read($file)
            -&gt;resize(Media::BLOG_IMAGE_WIDTH, Media::BLOG_IMAGE_HEIGHT);
    }


    /**
     * 画像をS3にPutする.
     *
     * @param string $path
     * @param \Illuminate\Http\UploadedFile $file
     * @return bool
     */
    public function putForS3(string $path, UploadedFile $file): bool
    {
        $convertFile = $this-&gt;ImageManger-&gt;resize($file)-&gt;toPng();
        return $this-&gt;diskS3-&gt;put($path, $convertFile);
    }</code></pre>
<h3>minio への通信</h3>
<p>ローカル環境をDockerを用いて開発していることもあり、ローカルネットワークが怪しいと何故か閃いた。</p>
<p>以下のコマンドを用いてネットワークを見たところ、同じネットワーク内に存在していたのでコンテナ間の通信は担保されている様子でした。</p>
<pre class="line-numbers"><code class="language-other">docker network ls
docker network inspect</code></pre>
<p>ただし、 minio に向けた <code>curl</code> コマンドが返ってこないことが分かった。</p>
<h2>原因</h2>
<p>調査を進めていくと、サービス名に対してエンドポイントを指定しないといけないことが分かった。</p>
<pre class="line-numbers"><code class="language-other">minio:
    image: quay.io/minio/minio:RELEASE.2023-01-18T04-36-38Z
    container_name: 'discovery-gem_minio'</code></pre>
<p>今回はminioとして登録していたので、 <code>.env</code> のエンドぽいとの指定が以下の様に設定する必要がありました。</p>
<pre class="line-numbers"><code class="language-other">AWS_ENDPOINT=http:{docker-compose.ymlで指定したport}//minio</code></pre>
<p>たったこれだけのために頭を悩ましたのは悔しすぎる。</p>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://otonan-syusyoku.work/archives/1839/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>自分で作ったサービスで売上を上げるのめちゃくちゃ難しいやんけ</title>
		<link>https://otonan-syusyoku.work/archives/1613</link>
					<comments>https://otonan-syusyoku.work/archives/1613#respond</comments>
		
		<dc:creator><![CDATA[hrokig2]]></dc:creator>
		<pubDate>Sat, 27 Jan 2024 01:55:46 +0000</pubDate>
				<category><![CDATA[仕事の独り言]]></category>
		<category><![CDATA[日々の独り言]]></category>
		<category><![CDATA[生涯独学]]></category>
		<category><![CDATA[AWS]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[LAMP]]></category>
		<category><![CDATA[Laravel]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[個人開発]]></category>
		<guid isPermaLink="false">https://otonan-syusyoku.work/?p=1613</guid>

					<description><![CDATA[こんにちは。都内でPHPerとして勤務している三流プログラマーです。 本業とは別に取り組んでいた個人開発でマネタイズができず、サービスを終了させてしまったのでここで供養させてください。 RIP My Service&#8 [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>こんにちは。都内でPHPerとして勤務している三流プログラマーです。</p>
<p>本業とは別に取り組んでいた個人開発でマネタイズができず、サービスを終了させてしまったのでここで供養させてください。</p>
<p>RIP My Service&#8230;</p>
<h2>作ったもの</h2>
<p>HP 兼 予約サイト 兼 ECサイトなるシステムを開発しました。</p>
<p>僕が沖縄県出身ということもあり、沖縄の個人経営を営んでいる小さな企業さんを相手に営業の肩代わりをすることを目的にシステムを開発しました。</p>
<p>というのも沖縄県は観光地として有名でありながらもHPすら持たず、地元の口コミのみで経営を行っているお店が多々ある状態でした。</p>
<p>せっかくの観光地でありながらお客様を呼び込めないのはかなりもったいないという思いから作った次第でございます。</p>
<h2>技術構成</h2>
<table style="border-collapse: collapse; width: 100%;">
<tbody>
<tr>
<td style="width: 50%;">デザイン</td>
<td style="width: 50%;">Tailwind + DaisyUI</td>
</tr>
<tr>
<td style="width: 50%;">フロントエンド</td>
<td style="width: 50%;">React</td>
</tr>
<tr>
<td style="width: 50%;">バックエンド</td>
<td style="width: 50%;">Laravel10</td>
</tr>
<tr>
<td style="width: 50%;">DB</td>
<td style="width: 50%;">RDS(MySQL8.x)</td>
</tr>
<tr>
<td style="width: 50%;">決済</td>
<td style="width: 50%;">Stripe</td>
</tr>
<tr>
<td style="width: 50%;">インフラ</td>
<td style="width: 50%;">サーバー：EC2<br />
DB：RDS<br />
ファイルサーバー：S3</td>
</tr>
<tr>
<td style="width: 50%;">その他</td>
<td style="width: 50%;">Docker</td>
</tr>
</tbody>
</table>
<h2>マネタイズポイント</h2>
<h3>物販購入</h3>
<p>沖縄ならではの商品が展開されるEC機能を開発しました。</p>
<p>1商品当たり個別に x％ の手数料をいただく契約になります。</p>
<h3>予約</h3>
<p>美容院やレジャー施設の予約を受け付ける機能を開発しました。</p>
<p>こちらもEC同様に1予約あたり、x円の手数料 or オプション契約 のどちらかを契約する想定でした。</p>
<h2>売り方</h2>
<p>沖縄出身ではあるものの都内で勤務しているということもあり現地での営業活動ができないという状況でした。<br />
そのため、現地で営業活動を行ってもらうために地元の友だちに「俺はこれから月100万円稼ぐシステムを開発するから営業をしてくれ」と<strong>大きく誇張した言い分</strong>を持って営業活動をしてもらいました。</p>
<p>その友人は面白そうだからという理由で快く引き受けてくれ、以下のマーケティング手法で営業を行ってもらいました。</p>
<ul>
<li>SNS
<ul>
<li>Instagram</li>
<li>Twitter</li>
</ul>
</li>
<li>ブログ</li>
</ul>
<p>先に結論から入るのですが、期間としては6ヶ月間行ってもらい、皆さんの想像通り契約は1件も入らなかったです。</p>
<h2>なぜ売れなかったのか</h2>
<h3>知名度</h3>
<p>これは誰しもが考えることだと思うのですが <span class="sc_marker blue"><strong>認知されていないサービスにお金を払う</strong></span> ことは避けたいはずです。</p>
<p>尚更、登記もしていない<span class="sc_marker blue"><strong>個人が開発したシステムに対して自分の命であるお金を注ぐことはあり得ない</strong></span>です。</p>
<p>考えられる手法としては以下の手法が取れるはずです。</p>
<ul>
<li>正しい営業をする</li>
<li>受託等で知名度を得る</li>
<li>その他のサービスで知名度を得る（知名度が無いことによる無限ループが発生する…）</li>
</ul>
<p>お客様が安心してこのサービスにはお金を投資できると胸を張って言えるようなシステムを構築するのは難しいですね。。。</p>
<h3>効果を得られるか不安</h3>
<p>知名度がないという理由にも近しいですが、当システムを使用することで利益を得られることに対する不安を拭い去る事はできませんでした。</p>
<p>なぜなら<span class="sc_marker blue"><strong>契約が1件もないということは実績が無いということですからお客様からすると不安しかありません</strong></span>。</p>
<p>世の中のスタートアップはどうやって利益を得ているんですか？？</p>
<h3>県民性</h3>
<p>こちらは確固たるデータがある訳ではないんですが、ハードに仕事をしないという県民性を見誤っていた可能性がある事を感じています。</p>
<p>沖縄は「のんかーな性格（のんきな性格）」と呼ばれる人が多い印象です。</p>
<p>事実として僕の知っている<span class="sc_marker blue"><strong>沖縄の経営者では食べていける分を稼げて楽しい毎日を送ることが大切</strong></span>という人が多いです。（4人だけしか知りませんが…）</p>
<p>そういった考えを持っている人に対して業務を効率化して売上を伸ばしましょうなんて言っても「忙しくなるなら現状のままで」といった答えが返ってくるに決まっています。</p>
<p>そのあたりをしっかりと調査する or ターゲットを先に見つける事が大切かなぁという印象です。</p>
<h2>反省</h2>
<p>僕はゴミを作ってしましました。</p>
<p>誰にも使われないシステムなんてゴミです。ただのゴミクズです。</p>
<p>今回は僕一人と頭の悪い友人の時間だけが溶けただけで済んで本当に良かったです。（実際には5万ほど運用費としてお金を使いました。）</p>
<p>仮に起業という形でサービスを開発していた場合は廃業に大きく近づいていたので、個人開発の一環でここまでの勉強ができたのは僕の才能かもしれません。笑</p>
<p>まだまだ作りたいものはあるので引き続き頑張っていきたいですねぇ〜</p>
]]></content:encoded>
					
					<wfw:commentRss>https://otonan-syusyoku.work/archives/1613/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Docker+Laravel+React+Viteで環境構築し、npm run dev で画面真っ白</title>
		<link>https://otonan-syusyoku.work/archives/1377</link>
					<comments>https://otonan-syusyoku.work/archives/1377#respond</comments>
		
		<dc:creator><![CDATA[hrokig2]]></dc:creator>
		<pubDate>Sat, 22 Jul 2023 05:19:52 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[好きではないJS]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[Laravel]]></category>
		<category><![CDATA[React]]></category>
		<guid isPermaLink="false">https://otonan-syusyoku.work/?p=1377</guid>

					<description><![CDATA[画面真っ白に 表題の通り、Docker+Laravel+React+Viteで環境構築後にnpm run dev で画面が真っ白になってしまった。 バージョン Docker docker --version Docker [&#8230;]]]></description>
										<content:encoded><![CDATA[<h2>画面真っ白に</h2>
<p>表題の通り、Docker+Laravel+React+Viteで環境構築後にnpm run dev で画面が真っ白になってしまった。</p>
<table style="border-collapse: collapse; width: 43.7902%;">
<tbody>
<tr>
<td style="width: 18.4791%;" colspan="2">バージョン</td>
</tr>
<tr>
<td style="width: 18.4791%;">Docker</td>
<td style="width: 25.3122%;">
<pre class="line-numbers"><code class="language-php">docker --version
Docker version 20.10.6, build 370c289</code></pre>
</td>
</tr>
<tr>
<td style="width: 18.4791%;">Laravel</td>
<td style="width: 25.3122%;">
<pre class="line-numbers"><code class="language-php">php artisan --version
[22-Jul-2023 14:05:32 Asia/Tokyo] Xdebug: [Step Debug] Could not connect to debugging client. Tried: host.docker.internal:9000 (through xdebug.client_host/xdebug.client_port).
Laravel Framework 10.15.0</code></pre>
</td>
</tr>
<tr>
<td style="width: 18.4791%;">React</td>
<td style="width: 25.3122%;">
<pre class="line-numbers"><code class="language-php">npm list --depth=0
data@ /data
+-- @headlessui/react@1.7.15
+-- @inertiajs/react@1.0.9
+-- @tailwindcss/forms@0.5.4
+-- @vitejs/plugin-react@3.1.0
+-- autoprefixer@10.4.14
+-- axios@1.4.0
+-- laravel-vite-plugin@0.7.8
+-- postcss@8.4.27
+-- react-dom@18.2.0
+-- react@18.2.0
+-- tailwindcss@</code></pre>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<h2>エラー文言</h2>
<p>デベロッパーツール＞Console</p>
<pre class="line-numbers"><code class="language-php">GET http://127.0.0.1:5173/@vite/client net::ERR_CONNECTION_REFUSED
localhost/:25     GET http://127.0.0.1:5173/resources/js/app.jsx net::ERR_CONNECTION_REFUSED
localhost/:25     GET http://127.0.0.1:5173/resources/js/Pages/Welcome.jsx net::ERR_CONNECTION_REFUSED
localhost/:20     GET http://127.0.0.1:5173/@react-refresh net::ERR_CONNECTION_REFUSED</code></pre>
<p>&nbsp;</p>
<h2>portがおかしい</h2>
<p>ConsoleのリクエストURLからportがおかしいことに気づく。</p>
<p>Dockerのnginxで指定していたportは8080:80にしていたのだが、http://<strong>127.0.0.1:5173</strong>となっている。</p>
<p>&nbsp;</p>
<p>うーん。なぜだ。</p>
<h2>解決方法</h2>
<p>Laravel,Reactを導入しているコンテナの設定が漏れている気がしてきた。</p>
<p>Dockerにてアプリケーションコンテナにportをしてみると解決できた。</p>
<p>docker-compose.ymlに以下を追記。</p>
<pre class="line-numbers"><code class="language-php">app:
    build: ./docker/php
    volumes:
      - ./src:/data
    ports:
    - 5173:5173  ←vite用port開通</code></pre>
<p>&nbsp;</p>
<p>そして、viteがホストを参照するようにするため、package.jsonに以下を追記。</p>
<pre class="line-numbers"><code class="language-php">"scripts": {
        "dev": "vite --host",   ←--hostを追記
        "build": "vite build"
    },</code></pre>
<p>&nbsp;</p>
<p>これで解決できた−</p>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://otonan-syusyoku.work/archives/1377/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
