Dockerコンテナ内Node.jsアプリのソースマップデバッグが効かない問題の解決法

Dockerコンテナ内でソースマップが機能しない原因
Dockerコンテナ内でNode.jsアプリケーションを実行すると、ソースマップが正しく機能せずデバッグが困難になる状況がよく発生します。この問題はTypeScriptやBabelなどのトランスパイラを使用している開発環境でとくに顕著です。
主な原因として以下の問題が考えられます:
ファイルパスの不一致:
- ホストマシンとコンテナ内でのファイルパスが異なる
- ソースマップが参照するパスがコンテナ内の実際のパスと一致しない
ボリュームマウント関連の問題:
- 不適切なボリュームマウント設定によりソースファイルがコンテナから見えない
- パーミッション問題でファイルにアクセスできない
Node.js設定の問題:
- ソースマップサポートが適切に有効化されていない
node --inspect
フラグの不適切な使用
デバッガー連携の問題:
- VSCodeのデバッグ設定が正しく構成されていない
- リモートデバッグ接続が適切に設定されていない
これらの問題が複合的に絡み合うことで、コンテナ内のNode.jsアプリケーションでエラーが発生した際に、変換後のJavaScriptコードしか表示されず、元のTypeScriptコードでデバッグができないという状況が発生します。
典型的な例として、以下のようなTypeScriptコードがあるとします:
// src/app.ts
function calculateTotal(items: number[]): number {
return items.reduce((total, item) => total + item, 0);
}
const result = calculateTotal([1, 2, "3" as any]);
console.log(`Total: ${result}`);
このコードはトランスパイルされて以下のようなJavaScriptになります:
// dist/app.js
"use strict";
function calculateTotal(items) {
return items.reduce((total, item) => total + item, 0);
}
const result = calculateTotal([1, 2, "3"]);
console.log(`Total: ${result}`);
//# sourceMappingURL=app.js.map
Dockerコンテナ内でこのアプリケーションを実行した際にエラーが発生すると、デバッガーは dist/app.js
ファイルの行番号を指し示し、元の src/app.ts
ファイルにマッピングされません。この状態では、開発効率が著しく低下します。
次のセクションでは、この問題を解決するためのNode.jsにおけるソースマップの基本設定方法について詳しく説明します。
Node.jsにおけるソースマップの基本設定方法
Node.jsでソースマップを正しく機能させるには、以下の基本設定が重要です。特にDockerコンテナ内で動作させる場合、これらの設定を正確に行う必要があります。
TypeScriptプロジェクトでのソースマップ設定
TypeScriptプロジェクトでソースマップを有効にするには、tsconfig.json
ファイルに以下の設定を追加します:
{
"compilerOptions": {
"sourceMap": true,
"inlineSources": true,
"sourceRoot": "/",
"outDir": "./dist",
// 他の設定...
}
}
これらの設定の役割は以下のとおりです:
sourceMap
: ソースマップファイルの生成を有効にしますinlineSources
: ソースマップにソースコードを含めますsourceRoot
: ソースファイルのルートディレクトリを指定しますoutDir
: コンパイル後のファイルの出力先を指定します
Babelを使用している場合の設定
Babelを使用している場合は、.babelrc
またはbabel.config.js
ファイルに以下の設定を追加します:
{
"presets": [
["@babel/preset-env", {
"targets": {
"node": "current"
}
}]
],
"plugins": [],
"sourceMaps": true,
"sourceRoot": "/"
}
webpack設定の例
webpackを使用している場合は、webpack.config.js
ファイルでdevtoolオプションを設定します:
module.exports = {
// 他の設定...
devtool: 'source-map',
// または開発環境向けに
// devtool: 'eval-source-map',
};
Node.jsでのソースマップサポートの有効化
Node.jsでソースマップを使用するには、source-map-support
パッケージをインストールします:
npm install --save-dev source-map-support
そして、アプリケーションのエントリーポイントで以下のコードを追加します:
// アプリケーションの先頭で追加
import 'source-map-support/register';
// または CommonJS の場合
require('source-map-support').install();
Docker環境向けの特別な設定
Docker環境では、パスのマッピング問題に対処するために、追加の設定が必要になることがあります:
// Docker環境用のカスタムソースマップサポート
require('source-map-support').install({
retrieveSourceMap: function(source) {
// コンテナ内パスとホストマシンパスの変換
const containerPath = source;
const hostPath = containerPath.replace('/app/', '/host/actual/path/');
try {
// ソースマップファイルを探す
const sourceMapPath = hostPath + '.map';
const sourceMap = require('fs').readFileSync(sourceMapPath, 'utf8');
return {
url: null,
map: sourceMap
};
} catch (e) {
return null;
}
}
});
上記の例は、コンテナとホスト間のパス変換を行うカスタム実装の例です。実際のプロジェクトでは、パス構造に合わせて調整が必要です。
NODE_OPTIONSによるソースマップ有効化
環境変数を使ってNode.jsにソースマップサポートを有効にする方法もあります:
# Node.js 12以降
NODE_OPTIONS="--enable-source-maps" node dist/app.js
これをDockerfileまたはdocker-compose.ymlに設定することで、コンテナ内での実行時にソースマップが有効になります:
# Dockerfile例
ENV NODE_OPTIONS="--enable-source-maps"
nodemonを使った開発環境での設定
開発中はnodemon
を使用することが多いですが、ソースマップサポートを有効にするには以下の設定を行います:
// nodemon.json
{
"execMap": {
"ts": "node --enable-source-maps -r ts-node/register"
},
"watch": ["src"],
"ext": "ts,json"
}
これらの基本設定を正しく行った上で、次のセクションで説明するVSCodeとの連携設定を適用することで、Dockerコンテナ内のNode.jsアプリケーションでもソースマップを使用したデバッグが可能になります。
デバッグ設定とVSCodeの連携設定
VSCodeとDockerコンテナ内のNode.jsアプリケーションを連携させ、ソースマップを使用したデバッグを行うには、適切な設定が必要です。ここでは、VSCodeでDockerコンテナ内のアプリケーションをデバッグするための詳細な設定方法を解説します。
launch.jsonの設定
VSCodeでは、.vscode/launch.json
ファイルにデバッグ設定を記述します。Dockerコンテナ内のNode.jsアプリケーションをデバッグするための基本的な設定は以下のとおりです:
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "attach",
"name": "Docker: Attach to Node",
"remoteRoot": "/app",
"localRoot": "${workspaceFolder}",
"port": 9229,
"address": "localhost",
"skipFiles": ["<node_internals>/**"],
"sourceMapPathOverrides": {
"/app/*": "${workspaceFolder}/*"
}
}
]
}
この設定の主要なポイントは:
remoteRoot
: コンテナ内のアプリケーションルートディレクトリ(通常は/app
や/usr/src/app
など)localRoot
: ホストマシン上のプロジェクトディレクトリ(${workspaceFolder}
変数で指定)sourceMapPathOverrides
: ソースマップのパスをホストマシンのパスに変換するためのマッピング
sourceMapPathOverridesの詳細設定
sourceMapPathOverrides
はソースマップが参照するパスを、VSCodeが理解できるローカルファイルシステムのパスに変換するための設定です。より複雑なプロジェクト構造の場合は、以下のように詳細なマッピングを設定することもできます:
"sourceMapPathOverrides": {
"/app/src/*": "${workspaceFolder}/src/*",
"/app/dist/*": "${workspaceFolder}/dist/*",
"webpack:///./~/*": "${workspaceFolder}/node_modules/*",
"webpack:///src/*": "${workspaceFolder}/src/*"
}
複数コンテナ環境での設定
マイクロサービスアーキテクチャなど、複数のDockerコンテナを使用する環境では、サービスごとに異なるデバッグ構成を用意することができます:
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "attach",
"name": "Docker: API Service",
"remoteRoot": "/app",
"localRoot": "${workspaceFolder}/services/api",
"port": 9229,
"address": "localhost",
"sourceMapPathOverrides": {
"/app/*": "${workspaceFolder}/services/api/*"
}
},
{
"type": "node",
"request": "attach",
"name": "Docker: Auth Service",
"remoteRoot": "/app",
"localRoot": "${workspaceFolder}/services/auth",
"port": 9230,
"address": "localhost",
"sourceMapPathOverrides": {
"/app/*": "${workspaceFolder}/services/auth/*"
}
}
]
}
VSCodeのRemote Containers拡張機能の活用
VSCodeのRemote Containers拡張機能を使うと、コンテナ内の開発環境とより密接に統合できます:
- VSCodeにRemote Containers拡張機能をインストール
.devcontainer/devcontainer.json
ファイルを作成:
{
"name": "Node.js App",
"dockerComposeFile": "../docker-compose.yml",
"service": "app",
"workspaceFolder": "/app",
"settings": {
"terminal.integrated.shell.linux": "/bin/bash",
"typescript.tsdk": "node_modules/typescript/lib"
},
"extensions": [
"dbaeumer.vscode-eslint",
"ms-vscode.vscode-typescript-tslint-plugin"
],
"forwardPorts": [3000, 9229],
"remoteUser": "node"
}
- コマンドパレットから「Remote-Containers: Reopen in Container」を選択
これにより、VSCodeはDockerコンテナの内部で直接実行され、パスのマッピング問題を回避できます。
デバッグに関する重要なTips
ブレークポイントが機能しない場合の確認事項:
- ソースファイルがコンテナ内にマウントされているか
- ソースマップファイル(.map)が生成されているか
sourceMapPathOverrides
の設定が正しいか
ホットリロードとデバッグの共存: nodemonやts-node-devでホットリロードを使用する場合は、以下のように起動オプションを調整します:
nodemon --inspect=0.0.0.0:9229 --exec "node -r ts-node/register" src/index.ts
デバッグセッション開始のタイミング: アプリケーションの起動タイミングとデバッガーの接続タイミングに注意してください。以下のような方法が有効です:
--inspect-brk
フラグを使用して、デバッガーが接続するまで実行を一時停止- スクリプトの先頭に小さな遅延を入れる:
setTimeout(() => { console.log('デバッガー接続のための遅延'); }, 2000);
エラーメッセージの確認: デバッグセッションで何か問題が発生した場合は、VSCodeのデバッグコンソールとターミナル出力を確認して、エラーメッセージを調査してください。
これらの設定を正しく行うことで、Dockerコンテナ内のNode.jsアプリケーションでもVSCodeを使用して効率的にデバッグできるようになります。次のセクションでは、より効率的なデバッグのためのDockerfileとdocker-compose.ymlの最適化方法について説明します。
Dockerfileとdocker-compose.ymlの最適化方法
Dockerコンテナ内でのNode.jsアプリケーションのデバッグ体験を向上させるには、Dockerfileとdocker-compose.ymlファイルの適切な設定が不可欠です。ここでは、ソースマップデバッグを効率的に行うための最適化方法を説明します。
デバッグ用Dockerfile
デバッグに最適化されたDockerfileの例を紹介します:
FROM node:18-alpine
# デバッグ用の作業ディレクトリを設定
WORKDIR /app
# 依存関係のファイルをコピー
COPY package.json package-lock.json ./
# 開発用依存関係を含めてすべてインストール
RUN npm ci
# TypeScriptやnodemonなどのグローバルツールをインストール(オプション)
RUN npm install -g typescript ts-node nodemon
# ソースコードはボリューム・マウントで提供するため、
# この時点ではコピーしない(開発用)
# デバッグポートを公開
EXPOSE 3000 9229
# デバッグモードでアプリを起動
CMD ["node", "--inspect=0.0.0.0:9229", "-r", "ts-node/register", "src/index.ts"]
このDockerfileのポイント:
--inspect=0.0.0.0:9229
フラグを使って、コンテナ外からのデバッガー接続を許可-r ts-node/register
を使って、TypeScriptファイルを直接実行可能に- ソースコードをイメージ内にコピーせず、ボリューム・マウントを前提とした設計
開発用docker-compose.yml
デバッグ用に最適化されたdocker-compose.ymlファイルの例:
version: '3.8'
services:
node-app:
build:
context: .
dockerfile: Dockerfile.dev
volumes:
# ソースコードを直接マウント(ホットリロード対応)
- ./:/app
# node_modulesは除外(パフォーマンス改善)
- /app/node_modules
ports:
# アプリケーションポート
- "3000:3000"
# デバッグポート
- "9229:9229"
environment:
- NODE_ENV=development
# ソースマップサポートを有効化
- NODE_OPTIONS=--enable-source-maps
# コンテナ内のファイル変更検知を有効化(ホットリロード向け)
environment:
- CHOKIDAR_USEPOLLING=true
# デバッガー接続を待機するフラグを追加可能(必要に応じて)
command: node --inspect-brk=0.0.0.0:9229 -r ts-node/register src/index.ts
このdocker-compose.ymlのポイント:
- ホストのソースコードを直接コンテナにマウント(リアルタイム編集対応)
node_modules
ディレクトリは除外(パフォーマンス向上)- デバッグポート(9229)を公開
- 環境変数による設定(NODE_OPTIONS, CHOKIDAR_USEPOLLINGなど)
ボリュームマウントの最適化
ボリュームマウントに関する一般的な問題と解決方法:
node_modulesのマウント問題:
volumes: - ./:/app # node_modulesを除外して、コンテナ内のものを使用 - /app/node_modules
これにより、ホストとコンテナのnode_modulesの衝突を防ぎます。
パーミッション問題:
# Dockerfile内でユーザー設定 RUN addgroup -g 1000 node_user && \ adduser -u 1000 -G node_user -s /bin/sh -D node_user # 適切なパーミッション設定 RUN chown -R node_user:node_user /app # 非rootユーザーに切り替え USER node_user
SELinuxの問題(主にRedHat系のシステム):
# ホストでの実行 docker run --volume=$(pwd):/app:z ...
:z
オプションでSELinuxコンテキストを適切に設定できます。
マルチステージビルド用Dockerfile
本番環境用のマルチステージビルドDockerfileの例:
# ビルドステージ
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
# TypeScriptをコンパイル(ソースマップを生成)
RUN npm run build
# 実行ステージ
FROM node:18-alpine
WORKDIR /app
# 本番用依存関係のみインストール
COPY package*.json ./
RUN npm ci --omit=dev
# ビルドステージからビルド済みファイルとソースマップをコピー
COPY --from=builder /app/dist /app/dist
# ソースファイルもコピー(ソースマップが参照するため)
COPY --from=builder /app/src /app/src
# ソースマップサポートを有効化
ENV NODE_OPTIONS=--enable-source-maps
EXPOSE 3000
CMD ["node", "dist/index.js"]
このマルチステージビルドのポイント:
- ビルドステージでTypeScriptコンパイルとソースマップ生成
- 実行ステージでは必要なファイルのみを含む軽量イメージ
- ソースマップのために元のソースファイルもコピー
環境別設定の分離
開発環境と本番環境で設定を分離する方法:
# docker-compose.yml(共通設定)
version: '3.8'
services:
node-app:
build:
context: .
ports:
- "3000:3000"
# docker-compose.dev.yml(開発環境用)
version: '3.8'
services:
node-app:
build:
dockerfile: Dockerfile.dev
volumes:
- ./:/app
- /app/node_modules
ports:
- "9229:9229"
environment:
- NODE_ENV=development
- NODE_OPTIONS=--enable-source-maps
command: nodemon --inspect=0.0.0.0:9229 src/index.ts
# docker-compose.prod.yml(本番環境用)
version: '3.8'
services:
node-app:
build:
dockerfile: Dockerfile.prod
environment:
- NODE_ENV=production
使用例:
# 開発環境
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up
# 本番環境
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up
デバッグ環境の自動検出
package.jsonスクリプトを使用して環境を自動的に検出・起動する例:
{
"scripts": {
"start": "node dist/index.js",
"start:dev": "nodemon --inspect=0.0.0.0:9229 src/index.ts",
"docker:dev": "docker-compose -f docker-compose.yml -f docker-compose.dev.yml up",
"docker:debug": "docker-compose -f docker-compose.yml -f docker-compose.debug.yml up",
"docker:prod": "docker-compose -f docker-compose.yml -f docker-compose.prod.yml up"
}
}
このように、Dockerfileとdocker-compose.ymlを適切に設定することで、Dockerコンテナ内でのNode.jsアプリケーションのデバッグ環境を大幅に改善できます。次のセクションでは、ソースマップデバッグに関する一般的な問題のトラブルシューティング方法について説明します。
トラブルシューティングと実践的なデバッグ手法
Dockerコンテナ内でNode.jsアプリケーションをデバッグする際に遭遇する一般的な問題とその解決方法について解説します。実践的なデバッグ手法を身につけることで、トラブルシューティングを効率的に行えるようになります。
ソースマップが正しく読み込まれない問題
症状: ブレークポイントが効かない、またはコンパイル後のJavaScriptコードでのみデバッグできる
解決策:
ソースマップファイルの存在を確認:
# コンテナ内で実行 docker exec -it <container_id> find /app -name "*.map" | grep app.js.map
ソースマップファイルの内容を確認:
# コンテナ内で実行 docker exec -it <container_id> cat /app/dist/app.js.map
ソースマップファイルには以下のような内容が含まれているはずです:
{ "version": 3, "file": "app.js", "sourceRoot": "", "sources": ["../src/app.ts"], "names": [], "mappings": "..." }
sources
の値がコンテナ内の正しい相対パスを指しているか確認してください。NODE_OPTIONSの設定を確認:
# コンテナ内で実行 docker exec -it <container_id> printenv | grep NODE_OPTIONS
--enable-source-maps
フラグが含まれていることを確認します。
パスのマッピング問題
症状: ブレークポイントが認識されるが、デバッガが別のファイルにジャンプする
解決策:
VSCodeの
sourceMapPathOverrides
設定を調整:"sourceMapPathOverrides": { "../src/*": "${workspaceFolder}/src/*", "/absolute/path/in/container/*": "${workspaceFolder}/*" }
コンテナ内のソースパスを確認:
// デバッグ中に実行 console.log(__dirname); console.log(__filename);
VSCodeとコンテナ内のパスの相違を確認し、マッピングを調整します。
ソースマップの
sourceRoot
を修正:// tsconfig.json { "compilerOptions": { "sourceRoot": "/app/src" } }
デバッガー接続の問題
症状: VSCodeのデバッガーがコンテナに接続できない
解決策:
ポートの公開状況を確認:
# ホストマシンで実行 docker ps | grep 9229
出力例:
0.0.0.0:9229->9229/tcp
のように、ポートが正しくマッピングされているか確認します。インスペクタが正しく起動しているか確認:
# コンテナログを確認 docker logs <container_id> | grep "Debugger listening"
インスペクタが起動していれば、
Debugger listening on ws://127.0.0.1:9229/...
のようなメッセージが表示されます。--inspect-brk
フラグを使用:node --inspect-brk=0.0.0.0:9229 -r ts-node/register src/index.ts
これにより、デバッガー接続まで実行が一時停止します。
ホットリロードとデバッグの連携問題
症状: ファイルを変更するとデバッガ接続が切れる、または変更が反映されない
解決策:
nodemonの設定を最適化:
// nodemon.json { "watch": ["src"], "ext": "ts,json", "exec": "node --inspect=0.0.0.0:9229 -r ts-node/register src/index.ts", "delay": "1000", "signal": "SIGTERM" }
delay
オプションにより、ファイル変更後の再起動前に短い遅延が発生します。これにより、デバッガが適切に再接続できる可能性が高まります。auto-attach設定を使用:
VSCodeの設定で自動再接続を有効にします:
// .vscode/settings.json { "debug.javascript.autoAttachFilter": "smart", "debug.javascript.terminalOptions": { "skipFiles": ["<node_internals>/**"] } }
TypeScript / Babel特有の問題
症状: TypeScriptやBabelでトランスパイルされたコードでデバッグ時に変数の値が正しく表示されない
解決策:
inlineSourcesオプションを有効にする:
// tsconfig.json { "compilerOptions": { "sourceMap": true, "inlineSources": true } }
sourcesContentを含める:
// webpack.config.js module.exports = { devtool: 'source-map', module: { rules: [ { test: /\.ts$/, use: { loader: 'ts-loader', options: { compilerOptions: { sourceMap: true, inlineSources: true } } } } ] } };
実践的なデバッグテクニック
条件付きブレークポイント:
VSCodeでブレークポイントを設定した後、右クリックして「条件の編集」を選択し、特定の条件でのみ停止するようにします:
user.id === '12345' // 特定のユーザーIDの場合のみ停止
ロギングブレークポイント:
実行を停止せずにログを出力するブレークポイントを設定できます:
// 右クリック → 「ログメッセージを編集」を選択 "User ID: {user.id}, Name: {user.name}" // 変数の値を出力
変数ウォッチの活用:
デバッグビューの「ウォッチ」パネルで変数の値を継続的に監視します:
// 例えば以下のような式を監視 user.orders.length user.orders.filter(o => o.total > 100)
堆積デバッグ(Postmortem Debugging):
クラッシュ時のメモリダンプを分析することができます:
# クラッシュ時にダンプファイルを生成 node --inspect-brk --heapsnapshot-signal=SIGUSR2 app.js
別のターミナルからSIGUSR2シグナルを送信してヒープスナップショットを作成:
kill -USR2 <pid>
デバッグ用のdockerコマンド:
# コンテナ内でシェルを起動してデバッグ docker exec -it <container_id> sh # コンテナ内の特定のプロセスを確認 docker exec -it <container_id> ps aux | grep node # コンテナのログをリアルタイムで監視 docker logs -f <container_id>
これらのトラブルシューティング手法と実践的なデバッグテクニックを活用することで、Dockerコンテナ内のNode.jsアプリケーションでも効率的なデバッグが可能になります。次のセクションでは、CI/CD環境でのデバッグについて説明します。
CI/CD環境での効率的なデバッグ方法
継続的インテグレーション・継続的デリバリー(CI/CD)環境でのデバッグは、開発環境とは異なる課題があります。このセクションでは、CI/CD環境でのNode.jsアプリケーションのデバッグを効率的に行うための方法について説明します。
CI/CD環境でのソースマップ設定
CI/CD環境でのソースマップ設定には、以下のポイントを考慮する必要があります:
本番ビルドでのソースマップの扱い:
// webpack.config.js module.exports = { mode: process.env.NODE_ENV, devtool: process.env.NODE_ENV === 'production' ? 'hidden-source-map' // 外部からアクセスできないがエラーレポートには使用可能 : 'source-map' // 開発環境では完全なソースマップ };
hidden-source-map
は、ソースマップファイルを生成しますが、JavaScriptファイルからの参照を含めないため、外部からアクセスできなくなります。環境変数を使った条件分岐:
// app.ts if (process.env.NODE_ENV !== 'production') { // 開発環境のみでソースマップサポートを有効にする require('source-map-support').install(); }
CI環境での自動テスト実行
CI環境でのテスト実行時にもソースマップを活用することで、失敗したテストのデバッグが容易になります:
# .github/workflows/test.yml (GitHub Actions例)
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
- run: npm ci
- name: Run tests with source map support
run: |
NODE_OPTIONS="--enable-source-maps" npm test
- name: Upload source maps as artifacts if tests fail
if: failure()
uses: actions/upload-artifact@v3
with:
name: sourcemaps
path: |
dist/**/*.js.map
src/
このワークフローでは、テストが失敗した場合にソースマップとソースファイルをアーティファクトとしてアップロードし、後からデバッグに使用できるようにします。
エラーモニタリングツールの活用
本番環境でのエラーをより効果的にデバッグするために、エラーモニタリングツールとソースマップを連携させる方法:
Sentryとの連携:
// sentry.js const Sentry = require('@sentry/node'); Sentry.init({ dsn: process.env.SENTRY_DSN, environment: process.env.NODE_ENV, release: process.env.GIT_COMMIT_SHA, integrations: [ // エラー発生時に自動的にトランザクションを終了 new Sentry.Integrations.OnUncaughtException(), new Sentry.Integrations.OnUnhandledRejection(), ], });
ソースマップをSentryにアップロードするスクリプト:
#!/bin/bash # upload-sourcemaps.sh sentry-cli releases new $GIT_COMMIT_SHA sentry-cli releases files $GIT_COMMIT_SHA upload-sourcemaps ./dist --url-prefix '~/dist' sentry-cli releases finalize $GIT_COMMIT_SHA
CI/CDパイプラインでのソースマップのアップロード:
# GitLab CI/CD設定例 deploy: stage: deploy script: - npm ci - npm run build - ./upload-sourcemaps.sh - npm start only: - main
デバッグビルド用のCI/CDジョブ
デバッグ用のビルドを自動的に生成する専用のCI/CDジョブを設定することも有効です:
# CircleCI設定例
version: 2.1
jobs:
build-debug:
docker:
- image: node:18
steps:
- checkout
- run:
name: Install dependencies
command: npm ci
- run:
name: Build with full source maps
command: |
NODE_ENV=development npm run build
- persist_to_workspace:
root: .
paths:
- dist
- src
- node_modules
deploy-debug:
docker:
- image: node:18
steps:
- checkout
- attach_workspace:
at: .
- run:
name: Deploy debug version
command: |
# デバッグビルドを特別な環境(ステージングなど)にデプロイ
NODE_OPTIONS="--enable-source-maps" npm run deploy:debug
Dockerfileの条件分岐
CI/CD環境で使用するDockerfileに条件分岐を導入し、環境に応じた設定を適用します:
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# 環境変数ARGを使用して条件分岐
ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}
# 開発/テスト環境の場合はソースマップサポートを有効にする
RUN if [ "$NODE_ENV" != "production" ]; then \
echo "Enabling source maps for debugging" && \
npm install --no-save source-map-support && \
echo "require('source-map-support').install();" > src/source-map-install.js; \
fi
# デバッグ用の起動コマンド
CMD if [ "$NODE_ENV" != "production" ]; then \
node --enable-source-maps -r ./src/source-map-install.js dist/index.js; \
else \
node dist/index.js; \
fi
このDockerfileを使用してイメージをビルドする際に、必要に応じてNODE_ENV引数を指定します:
# デバッグ用ビルド
docker build --build-arg NODE_ENV=development -t my-app:debug .
# 本番用ビルド
docker build -t my-app:production .
CI/CDでのリモートデバッグの設定
CI/CDパイプラインでのリモートデバッグを可能にする設定例:
# GitHub Actions例
jobs:
debug-session:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Start debug container
run: |
docker run -d --name debug-container -p 9229:9229 -e NODE_OPTIONS="--inspect=0.0.0.0:9229" my-app:debug
- name: Setup tmate session (for debugging)
uses: mxschmitt/action-tmate@v3
with:
limit-access-to-actor: true
このアクションは、失敗したワークフローでtmate
セッションを開始し、リモートからSSHでアクセスしてデバッグを行うことができます。
デバッグログの強化
CI/CD環境でのデバッグを容易にするためのログ設定:
// logger.js
const winston = require('winston');
const logger = winston.createLogger({
level: process.env.LOG_LEVEL || 'info',
format: winston.format.combine(
winston.format.timestamp(),
process.env.NODE_ENV === 'production'
? winston.format.json()
: winston.format.prettyPrint()
),
defaultMeta: { service: 'user-service' },
transports: [
new winston.transports.Console(),
// CI/CDでのデバッグ用に特別なログファイルを追加
...(process.env.CI
? [new winston.transports.File({ filename: '/var/log/app-debug.log', level: 'debug' })]
: [])
]
});
// エラー発生時にスタックトレースとソースの位置情報を詳細にログ
logger.exceptions.handle(
new winston.transports.Console({
format: winston.format.combine(
winston.format.colorize(),
winston.format.prettyPrint()
)
})
);
module.exports = logger;
これらの方法を組み合わせることで、CI/CD環境でもDockerコンテナ内のNode.jsアプリケーションを効率的にデバッグすることができます。本番環境での問題が発生した場合でも、ソースマップを活用して迅速に根本原因を特定し、解決することができるようになります。
このトピックはこちらの書籍で勉強するのがおすすめ!
この記事の内容をさらに深く理解したい方におすすめの一冊です。実践的な知識を身につけたい方は、ぜひチェックしてみてください!
おすすめコンテンツ
おすすめDocker2025/5/20Dockerコンテナ内Node.jsアプリの環境変数トラブル解決法
Dockerコンテナ内でNode.jsアプリケーションを実行すると、環境変数が正しく読み込まれない問題に遭遇することがあります。この記事では、具体的な原因と解決策を実用的なコード例で解説します。
続きを読む Docker2025/5/20Docker環境でNode.jsのホットリロードが効かない問題の解決法
Docker環境でNode.jsアプリケーションを開発中にホットリロードが効かない問題に悩んでいませんか?この記事では、この特定の問題を解決するための具体的な対処法をシンプルに解説します。
続きを読む Docker2025/5/20Dockerコンテナ内Node.jsアプリをChromeDevToolsでリモートデバッグする方法
Dockerコンテナ内で動作するNode.jsアプリケーションをChromeDevToolsでリモートデバッグする具体的な手順と設定例を紹介します。コードの実行を一時停止して変数を調査したい開発者に役...
続きを読む Docker2025/5/20Docker環境でNodeモジュールが同期されない問題の解決法
Docker開発環境でのNode.jsプロジェクトでnode_modulesが正しく同期されない問題に悩んでいませんか?このよくある問題の具体的な解決策と実践的なコード例を紹介します。
続きを読む Docker2025/5/20Docker環境でViteのHMR(ホットリロード)が効かない問題の解決法
DockerコンテナでViteを使用した開発環境を構築した際に発生するホットモジュールリプレイスメント(HMR)の問題を解決する方法を詳しく解説します。具体的な設定例とトラブルシューティングのステップ...
続きを読む Docker2025/5/20Dockerコンテナ内TypeScriptプロジェクトのデバッグ技法
Dockerコンテナ内でTypeScriptプロジェクトを効率的にデバッグする方法を解説します。VSCodeの設定からコンテナ内部のツールを活用したトラブルシューティングまで、具体的なコード例と共に詳...
続きを読む Docker2025/5/20Docker環境でTypeScriptのホットリロードが効かない時の解決策
Docker環境でTypeScriptアプリケーションを開発しているとホットリロードが動作しない問題に遭遇することがあります。この記事では、その原因と具体的な解決方法を実践的なコード例とともに解説しま...
続きを読む Node.js2025/5/20Node.jsアプリケーションのCORSエラー解決法:5分で実装できる完全ガイド
フロントエンドとバックエンドの連携で頻繁に遭遇するCORSエラーの原因と解決策を具体的なコード例とともに解説します。Node.js環境でのCORSポリシーの正しい設定方法から、開発環境と本番環境での違...
続きを読む