運用スクリプト作成ガイド¶
概要¶
本ガイドは ops/scripts/ 配下に配置する運用スクリプトのネーミングルール、ディレクトリ構成、実装スタイルを定義します。Gulp タスクランナーと連携し、環境構築・デプロイ・プロビジョニング・運用タスクを自動化します。
ディレクトリ構成¶
ops/
├── scripts/
│ ├── shared.js # 共通ユーティリティ
│ ├── ssh.js # SSH/SCP ヘルパー
│ ├── deploy_dev.js # 開発環境デプロイ
│ ├── deploy_stg.js # ステージング環境デプロイ
│ ├── deploy_prd.js # 本番環境デプロイ
│ ├── provision_stg.js # ステージング環境プロビジョニング
│ ├── provision_prd.js # 本番環境プロビジョニング
│ ├── develop.js # アプリケーション開発タスク
│ ├── release.js # リリースワークフロー
│ ├── journal.js # 開発ジャーナル生成
│ ├── mkdocs.js # ドキュメントビルド
│ ├── vault.js # シークレット管理
│ ├── ssh_stg.js # ステージング SSH・踏み台
│ ├── ssh_prd.js # 本番 SSH・踏み台
│ ├── sonar_local.js # SonarQube ローカル環境
│ └── sonar_aws.js # SonarQube AWS 環境
├── terraform/ # IaC(Terraform)
├── docker/ # Docker 関連設定
└── nix/ # Nix 開発環境(任意)
ネーミングルール¶
ファイル名¶
{カテゴリ}_{環境}.js の形式で命名する。
| カテゴリ | 説明 | 例 |
|---|---|---|
deploy |
デプロイスクリプト | deploy_dev.js, deploy_stg.js, deploy_prd.js |
provision |
IaC プロビジョニング | provision_stg.js, provision_prd.js |
ssh |
SSH・踏み台操作 | ssh.js(共通), ssh_stg.js, ssh_prd.js |
develop |
アプリケーション開発タスク | develop.js |
release |
リリースワークフロー | release.js |
journal |
開発ジャーナル | journal.js |
mkdocs |
ドキュメント | mkdocs.js |
sonar |
コード品質分析 | sonar_local.js, sonar_aws.js |
shared |
共通ユーティリティ | shared.js |
vault |
シークレット管理 | vault.js |
環境サフィックス:
| サフィックス | 環境 | 例 |
|---|---|---|
_dev |
開発環境 | deploy_dev.js |
_stg |
ステージング環境 | deploy_stg.js, provision_stg.js |
_prd |
本番環境 | deploy_prd.js, provision_prd.js |
_local |
ローカル環境 | sonar_local.js |
_aws |
AWS 環境 | sonar_aws.js |
| なし | 環境非依存 / 共通 | shared.js, ssh.js, release.js |
Gulp タスク名¶
{カテゴリ}:{環境}:{アクション} の形式で命名する。
deploy:dev:build # 開発環境: ビルド
deploy:dev:push # 開発環境: Registry プッシュ
deploy:dev # 開発環境: デプロイ実行
deploy:dev:status # 開発環境: ステータス確認
deploy:dev:logs # 開発環境: ログ取得
deploy:dev:clean # 開発環境: クリーンアップ
deploy:dev:setup # 開発環境: 初回セットアップ
deploy:dev:help # 開発環境: ヘルプ
provision:stg:plan # ステージング: Terraform plan
provision:stg:vpc # ステージング: VPC プロビジョニング
provision:stg:rds # ステージング: RDS プロビジョニング
provision:stg:ecs # ステージング: ECS プロビジョニング
provision:stg # ステージング: 全リソース一括
provision:stg:destroy # ステージング: 全リソース廃棄
provision:stg:help # ステージング: ヘルプ
ssh:stg:login # ステージング: 踏み台ログイン
ssh:stg:tunnel # ステージング: SSH トンネル
ssh:stg:backup # ステージング: DB バックアップ
ssh:stg:restore # ステージング: DB リストア
dev:sms # SMS 開発サーバー起動
dev:sms:product # SMS product プロファイル起動
tdd:sms # SMS TDD モード
実装スタイル¶
基本構造¶
すべてのスクリプトは以下の構造に従う。
'use strict';
import path from 'path';
import { execSync } from 'child_process';
import { cleanDockerEnv } from './shared.js';
// ============================================
// 設定
// ============================================
const PREFIX = 'DEV'; // 環境変数プレフィックス
/** サービス定義 */
const SERVICES = [
{ name: 'backend', port: 8080, container: 'app-backend', label: 'Backend' },
{ name: 'frontend', port: 3000, container: 'app-frontend', label: 'Frontend' },
];
// ============================================
// ヘルパー関数
// ============================================
/**
* JSDoc コメントで関数の目的・引数・戻り値を記述
* @param {string} param - パラメータの説明
* @returns {string}
*/
function helperFunction(param) {
// 実装
}
// ============================================
// Gulp タスク
// ============================================
export default function(gulp) {
// タスク登録
gulp.task('deploy:dev:build', (done) => {
// タスク実装
done();
});
}
コーディング規約¶
1. strict mode¶
すべてのファイルの先頭に 'use strict'; を記述する。
2. ESM(ES Modules)¶
import / export 構文を使用する。require は使用しない。
// Good
import path from 'path';
import { execSync } from 'child_process';
import { cleanDockerEnv } from './shared.js';
// Bad
const path = require('path');
3. セクション区切り¶
コード内のセクションは以下のコメントで区切る。
// ============================================
// 設定
// ============================================
// ============================================
// ヘルパー関数
// ============================================
// ============================================
// Gulp タスク
// ============================================
4. JSDoc コメント¶
すべての関数に JSDoc コメントを記述する。
/**
* docker build に渡すオプションを組み立てる
* @returns {string} ビルドオプション文字列
*/
function dockerBuildOptions() {
// ...
}
5. 環境変数の管理¶
環境変数は .env ファイルで管理し、環境プレフィックス(DEV_, STG_, PRD_)で名前空間を分離する。
// 環境変数プレフィックスで名前空間を分離
const PREFIX = 'STG';
const awsProfile = () => process.env.STG_AWS_PROFILE || '';
const sshHost = () => process.env[`${PREFIX}_SSH_HOST`];
環境変数の命名規則:
| プレフィックス | 環境 | 例 |
|---|---|---|
DEV_ |
開発環境 | DEV_SSH_HOST, DEV_SSH_USER |
STG_ |
ステージング環境 | STG_AWS_PROFILE, STG_DB_USERNAME |
PRD_ |
本番環境 | PRD_AWS_PROFILE, PRD_DB_USERNAME |
GHCR_ |
GitHub Container Registry | GHCR_USER, GHCR_TOKEN |
DOCKER_ |
Docker 関連 | DOCKER_BUILD_NETWORK, DOCKER_BUILD_DNS |
6. サービス定義¶
複数サービスを扱うスクリプトでは、サービスを配列で定義する。
const SERVICES = [
{ name: 'sms', port: 8080, container: 'app-sms', label: 'SMS(販売管理)' },
{ name: 'fas', port: 8081, container: 'app-fas', label: 'FAS(財務会計)' },
];
サービス定義を基に、個別タスクと一括タスクを動的に生成する。
// 個別タスク: deploy:dev:build:sms, deploy:dev:build:fas
SERVICES.forEach((svc) => {
gulp.task(`deploy:dev:build:${svc.name}`, (done) => {
buildImage(svc);
done();
});
});
// 一括タスク: deploy:dev:build(全サービス)
gulp.task('deploy:dev:build', gulp.series(
...SERVICES.map((svc) => `deploy:dev:build:${svc.name}`)
));
7. エラーハンドリング¶
execSync のエラーは適切にキャッチし、ユーザーにわかりやすいメッセージを表示する。
try {
execSync(command, { stdio: 'inherit', env: cleanDockerEnv() });
} catch (err) {
console.error(`エラー: ${err.message}`);
process.exit(1);
}
8. ヘルプタスク¶
各カテゴリにヘルプタスクを提供する。
gulp.task('deploy:dev:help', (done) => {
console.log(`
=== 開発環境デプロイコマンド ===
deploy:dev:build 全サービスをローカルビルド
deploy:dev:push 全イメージを Registry にプッシュ
deploy:dev 全サービスをデプロイ
deploy:dev:status コンテナ状態を確認
deploy:dev:logs コンテナログを表示
deploy:dev:clean 開発環境を完全削除
deploy:dev:setup 初回セットアップ
deploy:dev:help このヘルプを表示
`);
done();
});
共通ユーティリティ(shared.js)¶
環境をまたいで共通的に使用するユーティリティ関数を shared.js に集約する。
'use strict';
/**
* DOCKER_HOST を除外した環境変数を返す
* Docker Desktop 使用時に DOCKER_HOST が設定されていると接続エラーが発生するため除外する
* @returns {Object} DOCKER_HOST を除外した環境変数
*/
export function cleanDockerEnv() {
const env = { ...process.env };
delete env.DOCKER_HOST;
return env;
}
SSH ヘルパー(ssh.js)¶
SSH/SCP 操作を共通化する。環境プレフィックスで接続先を切り替える。
/**
* SSH 接続パラメータを取得
* @param {string} [prefix='DEV'] 環境変数プレフィックス
* @returns {{ host: string, user: string, port: string, keyFile: string | undefined }}
*/
export function getSSHConfig(prefix = 'DEV') {
const host = process.env[`${prefix}_SSH_HOST`];
const user = process.env[`${prefix}_SSH_USER`];
const port = process.env[`${prefix}_SSH_PORT`] || '22';
const keyFile = process.env[`${prefix}_SSH_KEY`];
if (!host || !user) {
throw new Error(`${prefix}_SSH_HOST と ${prefix}_SSH_USER を .env に設定してください`);
}
return { host, user, port, keyFile };
}
/**
* SSH でリモートコマンドを実行
* @param {string} command 実行するコマンド
* @param {object} [options] オプション
* @param {boolean} [options.ignoreError] エラーを無視するか
* @param {boolean} [options.capture] 出力を文字列で返すか
* @param {string} [options.prefix] 環境変数プレフィックス
* @returns {string} 標準出力
*/
export function sshExec(command, options = {}) {
// 実装
}
/**
* SCP でローカルファイル/ディレクトリをリモートに転送
* @param {string} localPath ローカルパス
* @param {string} remotePath リモートパス
* @param {object} [options] オプション
* @param {boolean} [options.recursive] ディレクトリを再帰的に転送
* @param {string} [options.prefix] 環境変数プレフィックス
*/
export function scpUpload(localPath, remotePath, options = {}) {
// 実装
}
AWS 連携パターン¶
aws-vault ラッパー¶
AWS 操作では aws-vault exec 経由で認証情報を自動取得する。
/**
* aws-vault ラッパーを組み立てる
* @returns {string} コマンドプレフィックス
*/
function awsExecPrefix() {
const profile = process.env.STG_AWS_PROFILE || '';
if (!profile) return '';
return `aws-vault exec ${profile} -- `;
}
Terraform 操作¶
/**
* Terraform コマンドを実行
* @param {string} subcommand - Terraform サブコマンド
* @param {object} options - オプション
*/
function terraform(subcommand, options = {}) {
const prefix = awsExecPrefix();
const cmd = `${prefix}terraform ${subcommand}`;
execSync(cmd, { cwd: options.cwd, stdio: 'inherit' });
}
Gulp タスク登録パターン¶
gulpfile.js¶
import gulp from 'gulp';
import deployDev from './ops/scripts/deploy_dev.js';
import deployStg from './ops/scripts/deploy_stg.js';
import provisionStg from './ops/scripts/provision_stg.js';
// 各モジュールのタスクを登録
deployDev(gulp);
deployStg(gulp);
provisionStg(gulp);
package.json のスクリプト¶
{
"scripts": {
"deploy:dev": "npx gulp deploy:dev",
"deploy:stg": "npx gulp deploy:stg",
"provision:stg": "npx gulp provision:stg"
}
}
スクリプト作成の手順¶
新しい運用スクリプトを作成する際は以下の手順に従う。
- ネーミング:
{カテゴリ}_{環境}.jsでファイル名を決定 - テンプレート: 基本構造(設定→ヘルパー関数→Gulp タスク)に従って実装
- 共通関数:
shared.jsとssh.jsの既存関数を活用 - 環境変数:
.env.exampleに必要な環境変数を追記 - ヘルプ:
{カテゴリ}:{環境}:helpタスクを作成 - gulpfile.js: タスクを登録
- ドキュメント: コマンドリファレンスを作成・更新