ローカルプロジェクトをサーバーに自動デプロイする方法

この記事では、ローカルプロジェクトをサーバーに自動デプロイするプロセスについて説明します。このプロセスには、プロジェクトのパッケージング、圧縮、ファイルのサーバーへのアップロード、サーバー上での解凍、指定ディレクトリへのデプロイ、最後に一時ファイルのクリーンアップが含まれます。以下は具体的な実装コードです。

準備作業

まず、必要なnpmパッケージをインストールします:

Terminal window
1
pnpm add node-ssh ssh2-sftp-client archiver

コードの実装

以下は、Node.jsを使用した完全なコード実装です:

1
import { NodeSSH } from "node-ssh";
2
import fs from "fs";
3
import path from "path";
4
import archiver from "archiver";
5
import { exec } from "child_process";
6
import { fileURLToPath } from "url";
7
import Client from "ssh2-sftp-client";
8
9
const __filename = fileURLToPath(import.meta.url); // ファイルの絶対パスを取得
10
const __dirname = path.dirname(__filename); // ディレクトリ名を取得
11
12
const ssh = new NodeSSH();
13
const sftp = new Client();
14
15
const serverConfig = {
16
host: "サーバーのIP", // サーバーIP
17
username: "ユーザー名", // ユーザー名
18
privateKey: "./private.pem", // 秘密鍵
19
// パスワードでログインする場合
20
//password: "パスワード", //
21
uploadPath: "/root/tmp/blog", // ファイルアップロードの一時ディレクトリ
22
path: "/deploy/path", // デプロイ先ディレクトリ
23
};
24
25
async function buildProject() {
26
console.log("プロジェクトをビルド中...");
27
28
return new Promise((resolve, reject) => {
29
exec("pnpm build", (error, stdout, stderr) => {
30
if (error) {
31
console.error(`ビルドエラー: ${error.message}`);
32
return reject(error);
33
}
34
if (stderr) {
35
console.error(`ビルドstderr: ${stderr}`);
36
return reject(new Error(stderr));
37
}
38
console.log(`ビルドstdout: ${stdout}`);
39
resolve();
40
});
41
});
42
}
43
44
async function deleteLocalDist() {
45
console.log("ローカルdistを削除中...");
46
47
return new Promise((resolve, reject) => {
48
exec("rm -rf shell/dist.zip", (error, stdout, stderr) => {
49
if (error) {
50
console.error(`削除エラー: ${error.message}`);
51
return reject(error);
52
}
53
if (stderr) {
54
console.error(`削除stderr: ${stderr}`);
55
return reject(new Error(stderr));
56
}
57
console.log(`正常に削除されました`);
58
resolve();
59
});
60
});
61
}
62
63
async function compressDist() {
64
console.log("distディレクトリを圧縮中...");
65
return new Promise((resolve, reject) => {
66
const output = fs.createWriteStream(path.join(__dirname, "dist.zip"));
67
const archive = archiver("zip", {
68
zlib: { level: 9 },
69
});
70
71
output.on("close", () => {
72
console.log(
73
`dist.zipが作成されました。合計バイト数: ${archive.pointer()}`,
74
);
75
resolve();
76
});
77
78
archive.on("error", (err) => {
79
console.error(`圧縮エラー: ${err.message}`);
80
reject(err);
81
});
82
83
archive.pipe(output);
84
archive.directory("dist/", true);
85
archive.finalize();
86
});
87
}
88
89
async function uploadToServer() {
90
console.log("dist.zipをサーバーにアップロード中...");
91
await sftp.connect({
92
host: serverConfig.host,
93
port: 22,
94
username: serverConfig.username,
95
privateKey: fs.readFileSync(serverConfig.privateKey, "utf8"),
96
});
97
98
await sftp.put(
99
path.join(__dirname, "dist.zip"),
100
path.posix.join(serverConfig.uploadPath, "dist.zip"), // path.posix.joinを使用してパスを処理
101
);
102
103
await sftp.end();
104
console.log("アップロード完了。");
105
}
106
107
async function deploy() {
108
try {
109
await buildProject();
110
await compressDist();
111
await uploadToServer();
112
113
console.log("サーバーに接続中...");
114
await ssh.connect({
115
host: serverConfig.host,
116
username: serverConfig.username,
117
privateKey: fs.readFileSync(serverConfig.privateKey, "utf8"),
118
});
119
120
console.log("古いファイルを削除中...");
121
await ssh.execCommand(`rm -rf ${serverConfig.path}/*`);
122
123
console.log("アップロードしたファイルを解凍中...");
124
await ssh.execCommand(
125
`unzip ${serverConfig.uploadPath}/dist.zip -d ${serverConfig.uploadPath}`,
126
);
127
128
console.log("ファイルをターゲットディレクトリに移動中...");
129
await ssh.execCommand(
130
`mv ${serverConfig.uploadPath}/dist/* ${serverConfig.path}`,
131
);
132
133
console.log("クリーンアップ中...");
134
await ssh.execCommand(`rm -rf ${serverConfig.uploadPath}/dist`);
135
await ssh.execCommand(`rm ${serverConfig.uploadPath}/dist.zip`);
136
137
console.log("デプロイ完了。");
138
ssh.dispose();
139
140
await deleteLocalDist();
141
} catch (error) {
142
console.error(`デプロイエラー: ${error.message}`);
143
ssh.dispose();
144
}
145
}
146
147
deploy();

コードの説明

  1. サーバー情報の設定

    • serverConfig オブジェクトには、サーバーのIPアドレス、ユーザー名、秘密鍵のパス、アップロードディレクトリ、およびターゲットディレクトリが含まれています。
  2. プロジェクトのビルド

    • exec 関数を使用して pnpm build コマンドを実行し、プロジェクトをビルドします。
  3. ビルド後のファイルを圧縮

    • archiver モジュールを使用して dist ディレクトリを dist.zip に圧縮します。
  4. ファイルをサーバーにアップロード

    • ssh2-sftp-client モジュールを使用して dist.zip をサーバーの一時ディレクトリにアップロードします。
  5. ファイルのデプロイ

    • node-ssh モジュールを使用してサーバーに接続し、古いファイルを削除し、アップロードしたファイルを解凍し、ファイルをターゲットディレクトリに移動します。
  6. 一時ファイルのクリーンアップ

    • サーバー上の一時ファイルとローカルの dist.zip を削除します。

以上の手順を実行することで、ローカルプロジェクトをサーバーに自動デプロイすることができます。この記事が参考になれば幸いです。