開発環境構築メモ
Windows11+WSL2環境でDockerを使用して開発環境を構築した際のメモ
※なお、躓いたりわからなくなったところはCopilotやCgatGPTの力を借りた
必要な技術
PHP
Typescript
Sass(SCSS)
タスクランナー(Gulp)
SCSSとTypescriptの自動コンパイルに使用
コンテナ構成
Webサーバー(Nginx):web
htmlなどのソースコードはpublic/以下に配置するものとし、publicディレクトリをマウント
設定ファイルをマウント
PHP:php
phpのソースコードはsrc以下に配置するものとし、srcディレクトリをマウント
Node.js:node
Typescript
Sass
Gulp
最終的な手順まとめ
途中躓いたところなどが多く複雑化したので、とりあえず最終的な手順をざっくりとまとめる。(躓いた箇所は別途メモする)
プロジェクト用のディレクトリを作成
WSL2のファイルシステムに作成する
はじめはローカルの適当な位置に作成していたが、後に問題になるのでプロジェクトのルートディレクトリの位置はWSL2のファイルシステム上に移動した
package.json と package-lock.jsonの用意
ローカル環境の任意の場所でpackage.json と package-lock.jsonを作成する
npmプロジェクトの初期化:npm init -y
-yオプションをつけることですべてをデフォルト値で初期化できる
必要なパッケージをローカルインストール:npm install --save-dev typescript sass gulp gulp-typescript gulp-sass
作成されたpackage.json と package-lock.jsonファイルをプロジェクトのルートディレクトリにコピーする
Dockerfileを作成
ベースイメージはNode.jsを使用
Node.jsコンテナにTypeScript、SCSS、GulpをインストールするためのDockerfileを作成する
code:Dockerfile
# ベースイメージとしてNode.jsを使用
FROM node:14
# 作業ディレクトリを設定
WORKDIR /app
# package.jsonとpackage-lock.jsonをコピー
COPY package*.json ./
# 依存関係をインストール
RUN npm install
# Gulp CLIをグローバルにインストール
RUN npm install -g gulp-cli
# アプリケーションのソースコードをコピー
COPY . .
# デフォルトのコマンドを設定
CMD "gulp"
DockerComposeファイルの作成
構成はコンテナ構成の通り
nodeのuser: "1000:1000"はGulpデコンパイル時にデフォルトだとrootユーザー権限でコンパイルが行われるため、Gulpの実行ユーザーを明示的に指定している
※id -u [ユーザー名]でユーザーID、id -g [ユーザー名]でユーザーグループが確認できる
code:compose.yaml
services:
web:
image: nginx:1.21.1
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./fastcgi-php.conf:/etc/nginx/fastcgi-php.conf
- ./public:/var/www/html
php:
image: php:8.0.8-fpm
volumes:
- ./src:/var/www/src
node:
build: .
volumes:
- .:/app
working_dir: /app
user: "1000:1000"
command: sh -c "npm install && gulp"
Nginxの設定ファイルの追加
Nginxに関しては知識が殆どなかったのでとりあえず最小限の設定ファイルをCopilotのアドバイスをもとに作成
code:nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
server {
listen 80;
server_name localhost;
root /var/www/html;
index index.html index.htm index.php;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include /etc/nginx/fastcgi-php.conf;
fastcgi_pass php:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www/src$fastcgi_script_name;
include fastcgi_params;
}
}
}
code:fastcgi-php.conf
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
include fastcgi_params;
起動、確認
動作確認用にダミーのファイルpublic/index.htmlとsrc/test.phpを作成
docker compose up -dで起動を確認
及びにアクセスして問題なく表示できることを確認
gulpfile追加
gulpfile.jsを作成
内容としては、watchでtypescript用のディレクトリ(/ts)と、SCSS用のディレクトリ(/scss)以下のファイルを監視し、変更があればコンパイルを行うというもの
code:gulpfile.js
const gulp = require("gulp");
const ts = require("gulp-typescript");
const sass = require("gulp-sass")(require("sass"));
// ソースファイル
const tsSrc = "ts/**/*.ts";
const scssSrc = "scss/**/*.scss";
// TypeScriptのコンパイル
gulp.task("typescript", function () {
console.log("Compiling TypeScript...");
return gulp
.src(tsSrc)
.pipe(
ts({
noImplicitAny: true, // 暗黙の any を禁止する
outFile: "script.js", // 出力するJSファイル名
target: "es2023",
module: "amd",
})
)
.pipe(gulp.dest("public/js")); // 出力先
});
// SCSSのコンパイル
gulp.task("scss", function () {
console.log("Compiling SCSS...");
return gulp
.src(scssSrc)
.pipe(sass().on("error", sass.logError))
.pipe(gulp.dest("public/css")); // 出力先
});
// ファイルの変更を監視
gulp.task("watch", function () {
// TypeScriptファイルの監視
gulp.watch(
tsSrc,
{ usePolling: true, interval: 500 },
gulp.series("typescript")
);
// SCSSファイルの監視
gulp.watch(scssSrc, { usePolling: true, interval: 500 }, gulp.series("scss"));
});
// デフォルトタスク("typescript", "scss", "watch"タスクを順番に実行する)
gulp.task("default", gulp.series("typescript", "scss", "watch"));
プロジェクトのルートディレクトリにTypescript用のディレクトリ、tsとSCSS用のディレクトリscssを作成、それぞれダミーのファイルを作成し、自動でコンパイルされることを確認
html、phpが動作すること、typescript、SCSSが自動でコンパイルできることが確認できればひとまず開発環境の構築が完了。
📌開発を開始してから起きた問題
MIME タイプ
SVGを表示しようとしたところ、表示ができないという問題が起きた
ブラウザの開発者ツールから対象のSVGファイルのヘッダーを確認するとContent-Typeがなかった。。。⇒SVGファイルとして正しく認識されていない
サーバー(Nginx)で MIME タイプを正しく設定する必要があったので設定を追加した
nginx.conf のhttpにinclude /etc/nginx/mime.types;を追加
デフォルトのMIMEタイプ設定が記述されているmime.typesというのがあるので、ひとまずそちらを読みこむように設定
複数ファイルのTypeScript
TypesScriptを複数ファイルで運用する場合、コンパイル時にscript.jsに集約して出力するようにしていたが、実際に集約したファイルをHTMLで読み込んで表示しようとした時に上手く動かなかった
詳細はTypeScriptのmoduleをAMDにしてハマったのでやめたメモ
結局1ファイルに集約することは諦め、moduleをesnextで運用するように変更した。
→出力されるファイルはtsファイルと同じ数だけ出力されるようになった。1つに集約するにはWebpackなどのバンドラーを使う必要がある
また、tsconfig.jsonを用いずに、gulpfile.jsに直接TypeScriptの設定を記述していたのでtsconfig.jsonを読み込んで使用するように変更した
code:tsconfig.json
{
"compilerOptions": {
"target": "es2023",
"module": "esnext",
"moduleResolution": "node", // ES モジュールの解決を適切に行うため必要
"noImplicitAny": true,
"outDir": "public/js" // 出力ディレクトリ
}
}
code:gulpfile.js
...
// TypeScriptプロジェクトを作成
const tsProject = ts.createProject("tsconfig.json");
// TypeScriptのコンパイル
gulp.task("typescript", function () {
console.log("Compiling TypeScript...");
return tsProject.src().pipe(tsProject()).pipe(gulp.dest("public/js"));
});
...
😫Gulpでwatchが効かない問題
Gulpでファイルに変更があればコンパイルするようにしようとしていたが、watchが効かずめちゃくちゃに躓いたのでメモ
(なお、上記の手順は諸々が解決したうえでの手順)
問題の概要
コンテナの起動時や手動でgulpコマンドを実行した際には問題なくコンパイルされるが、その後ファイルに変更があってもStarting 'watch'...のままで何も反応がない→Gulpのwatchが効いていない
結論
ひとまず結論としてはソースコードはWindowsのホスト側ではなく、WSL2のファイルシステム上に置かなければいけなかった
(関係性がある記事:WindowsでDockerを使う時、正しくファイル配置しないと激重になるので注意)
最初は開発環境を作ろうとプロジェクトのルートディレクトリを作成する際、Windowsのホスト側に作成していたが、WSL2環境のDockerにはファイルシステムの通知に関する既知の問題はあるらしく、そのせいでwatchが機能していなかった
解決方法
最終的に以下の手順で解決した。(ほぼ内容は結論の通り)
(WSL2の整備)
WSL2はインストールし、Dockerの設定もWSL2ベースになってはいたが、UbuntuディストリビューションはインストールしていなかったのでまずはUbuntuのインストールを行った。
wsl -l -vで確認するとに、「docker-desktop」しかない状態だった
なお、「docker-desktop」のファイルシステムはDocker内部の管理用ディレクトリであり、プロジェクトファイルを配置する場所ではないとのこと
wsl --install -d UbuntuでUbuntuディストリビューションをインストール
途中でユーザー名とパスワードを設定する
インストールが完了すると、Ubuntuのターミナルが起動する
プロジェクトのルートディレクトリをUbuntuのファイルシステムに移動
\\wsl$\Ubuntu\home\{ユーザ名}\以下の任意の場所にプロジェクトのルートディレクトリを移動する
Ubuntuのファイルシステムにはエクスプローラーからはアドレスバーに\\wsl$\Ubuntu入力でアクセス可能
その後、Ubuntuのターミナルで、ソースコードを配置したディレクトリに移動して通常通りdocker compose upでコンテナを起動する
以降、コマンドの実行はUbuntuのターミナルで実行する
watchが正しく機能することを確認
試したこと
解決につながらなかったものも、今後何かの役に立つ可能性もある(?)ので一応記録に残っているものをざっくりと残しておく
まずはローカルとコンテナ間のファイル同期がちゃんとできていることを確認
コンテナ内に直接ファイルを追加したら、ローカルにも反映されることを確認。逆も同様。ここは問題なし
Copilot曰くDockerのボリュームマウントでは、ファイルシステムの変更通知が正しく伝わらないことがあるとのことで、chokidarというファイル監視ライブラリを使うことで解決する可能性があるとのこと
Copilotのアドバイスに従いchokidarを使用するように変更するも、変化なし
ファイルとディレクトリの権限を確認したがこれも問題なし
chokidarのusePollingオプションを有効にしたり、intervalの値を変更してみたが効果なし
WSL2+Dockerということが問題なのでは?と思いCopilotに尋ねるとファイルシステムの通知やパフォーマンスに影響を与えることがあることがわかる
ここで提案されたのは、WSL2統合の確認とWSL2のパフォーマンス調整のためにホームディレクトリに.wslconfigファイルを作成するというものだが、これでは解決せず
nodemonを使って、ファイルの変更を監視し、変更があった場合に自動的にGulpタスクを再実行する方法を試すが解決せず
Gulp以外のWebpackやViteを使用する方法も試してみるが解決には至らなかった
#開発環境構築 #Docker #Gulp #WSL2 #プロフィールサイト作成メモ