웹 디자인 전면 개편
This commit is contained in:
114
scripts/deploy-nas-scp.cjs
Normal file
114
scripts/deploy-nas-scp.cjs
Normal file
@@ -0,0 +1,114 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const { execSync } = require("child_process");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
const isWin = process.platform === "win32";
|
||||
const projectName = "saju-web";
|
||||
const projectRoot = path.resolve(__dirname, "..");
|
||||
|
||||
// SSH 설정
|
||||
const sshTarget = process.env.NAS_SSH_TARGET || "bgg8988@192.168.45.54";
|
||||
const sshPath = process.env.NAS_SSH_PATH || `/volume1/docker/webpage/${projectName}`;
|
||||
const sshPort = process.env.NAS_SSH_PORT || "2300";
|
||||
|
||||
console.log("🚀 Saju Web NAS Deployment (SCP Mode)");
|
||||
console.log("=====================================");
|
||||
console.log(`Target: ${sshTarget}:${sshPath}`);
|
||||
console.log("");
|
||||
|
||||
try {
|
||||
const sshCmd = sshPort ? `ssh -p ${sshPort}` : "ssh";
|
||||
const scpCmd = sshPort ? `scp -P ${sshPort}` : "scp";
|
||||
|
||||
// 1. NAS에 디렉토리 생성
|
||||
console.log("📦 Step 1: Preparing NAS directory...");
|
||||
execSync(`${sshCmd} ${sshTarget} "mkdir -p ${sshPath}"`, {
|
||||
stdio: "inherit",
|
||||
});
|
||||
console.log("✅ Directory ready");
|
||||
console.log("");
|
||||
|
||||
// 2. 파일 전송 (tar + ssh pipe)
|
||||
console.log("📤 Step 2: Transferring files to NAS...");
|
||||
const excludeArgs = [
|
||||
"--exclude=node_modules",
|
||||
"--exclude=.next",
|
||||
"--exclude=.git",
|
||||
"--exclude=dist",
|
||||
"--exclude=out",
|
||||
"--exclude=.env.local",
|
||||
"--exclude=*.log",
|
||||
"--exclude=saju-web-deploy.tar.gz",
|
||||
].join(" ");
|
||||
|
||||
// tar로 압축하면서 동시에 ssh로 전송
|
||||
const transferCmd = `tar -czf - ${excludeArgs} . | ${sshCmd} ${sshTarget} "cd ${sshPath} && tar -xzf -"`;
|
||||
console.log("Transferring files (this may take a moment)...");
|
||||
|
||||
execSync(transferCmd, {
|
||||
cwd: projectRoot,
|
||||
stdio: "inherit",
|
||||
shell: true,
|
||||
});
|
||||
console.log("✅ Files transferred");
|
||||
console.log("");
|
||||
|
||||
// 3. NAS에서 배포
|
||||
console.log("📝 Step 3: Deploying on NAS...");
|
||||
|
||||
// Docker 명령어 경로 (Synology NAS)
|
||||
// 기본값: sudo 없이 실행
|
||||
const dockerCmd = process.env.NAS_USE_SUDO === "true"
|
||||
? "sudo /usr/local/bin/docker"
|
||||
: "/usr/local/bin/docker";
|
||||
|
||||
// 환경 변수 설정
|
||||
console.log(" - Setting up environment...");
|
||||
execSync(`${sshCmd} ${sshTarget} "cd ${sshPath} && if [ -f .env.nas ]; then cp -f .env.nas .env; fi"`, {
|
||||
stdio: "inherit",
|
||||
});
|
||||
|
||||
// Docker 빌드 및 배포
|
||||
console.log(" - Building Docker container...");
|
||||
execSync(`${sshCmd} ${sshTarget} "cd /volume1/docker/webpage && ${dockerCmd} compose build ${projectName}"`, {
|
||||
stdio: "inherit",
|
||||
});
|
||||
|
||||
console.log(" - Starting container...");
|
||||
execSync(`${sshCmd} ${sshTarget} "cd /volume1/docker/webpage && ${dockerCmd} compose up -d ${projectName}"`, {
|
||||
stdio: "inherit",
|
||||
});
|
||||
|
||||
console.log("✅ Deployment complete");
|
||||
console.log("");
|
||||
|
||||
// 5. 헬스체크
|
||||
console.log("🏥 Step 4: Health check...");
|
||||
setTimeout(() => {
|
||||
try {
|
||||
const healthCmd = `${sshCmd} ${sshTarget} "docker exec ${projectName} wget -q -O- http://localhost:3000/api/health"`;
|
||||
const health = execSync(healthCmd, { encoding: "utf-8" });
|
||||
console.log("Health check response:", health);
|
||||
console.log("✅ Service is healthy");
|
||||
} catch (err) {
|
||||
console.warn("⚠️ Health check failed (service may still be starting)");
|
||||
}
|
||||
console.log("");
|
||||
console.log("🎉 Deployment completed!");
|
||||
console.log("=====================================");
|
||||
console.log(`🌐 Access: http://gahusb.synology.me/saju`);
|
||||
console.log("");
|
||||
}, 3000);
|
||||
} catch (err) {
|
||||
console.error("❌ Deployment failed:", err.message);
|
||||
|
||||
// 에러 발생 시 임시 파일 정리
|
||||
const archivePath = path.join(projectRoot, "saju-web-deploy.tar.gz");
|
||||
if (fs.existsSync(archivePath)) {
|
||||
fs.unlinkSync(archivePath);
|
||||
}
|
||||
|
||||
process.exit(1);
|
||||
}
|
||||
@@ -17,9 +17,9 @@ const dstMac = `/Volumes/gahusb.synology.me/docker/webpage/${projectName}/`;
|
||||
const dst = isWin ? dstWin : dstMac;
|
||||
|
||||
// SSH 설정 (환경 변수에서 읽기)
|
||||
const sshTarget = process.env.NAS_SSH_TARGET || "gahusb@gahusb.synology.me";
|
||||
const sshTarget = process.env.NAS_SSH_TARGET || "bgg8988@192.168.45.54";
|
||||
const sshPath = process.env.NAS_SSH_PATH || `/volume1/docker/webpage/${projectName}`;
|
||||
const sshPort = process.env.NAS_SSH_PORT;
|
||||
const sshPort = process.env.NAS_SSH_PORT || "2300";
|
||||
|
||||
// 제외할 파일/폴더
|
||||
const excludePatterns = [
|
||||
@@ -56,9 +56,59 @@ if (process.env.NAS_DEPLOY_METHOD === "ssh" || sshTarget) {
|
||||
try {
|
||||
// 1. rsync로 파일 동기화
|
||||
console.log("📦 Step 1: Syncing files to NAS...");
|
||||
const rsyncCmd = `rsync -avz --delete ${excludeArgs} -e "${sshCmd}" ${projectRoot}/ ${sshTarget}:${sshPath}/`;
|
||||
|
||||
// Windows에서 rsync 찾기 (Git Bash 또는 WSL)
|
||||
let rsyncPath = "rsync";
|
||||
let sourcePath = projectRoot;
|
||||
|
||||
if (isWin) {
|
||||
// Git Bash에서 실행 중이면 rsync를 바로 사용 가능
|
||||
try {
|
||||
execSync("rsync --version", { stdio: "ignore" });
|
||||
rsyncPath = "rsync";
|
||||
console.log("✅ Using rsync from Git Bash");
|
||||
} catch (err) {
|
||||
// Git Bash가 아니면 rsync.exe 찾기
|
||||
const possiblePaths = [
|
||||
"C:\\Program Files\\Git\\usr\\bin\\rsync.exe",
|
||||
"C:\\Program Files (x86)\\Git\\usr\\bin\\rsync.exe",
|
||||
process.env.PROGRAMFILES + "\\Git\\usr\\bin\\rsync.exe",
|
||||
process.env.LOCALAPPDATA + "\\Programs\\Git\\usr\\bin\\rsync.exe",
|
||||
];
|
||||
|
||||
for (const testPath of possiblePaths) {
|
||||
if (fs.existsSync(testPath)) {
|
||||
rsyncPath = testPath;
|
||||
console.log(`✅ Found rsync at: ${testPath}`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// rsync를 못 찾으면 에러 메시지
|
||||
if (rsyncPath === "rsync") {
|
||||
console.error("❌ rsync not found on Windows");
|
||||
console.log("");
|
||||
console.log("💡 Debug: Let's find rsync");
|
||||
console.log(" Run this in Git Bash: which rsync");
|
||||
console.log("");
|
||||
console.log(" Then update the script with the correct path.");
|
||||
console.log("");
|
||||
console.log(" Or use SMB mount deployment:");
|
||||
console.log(" npm run release:nas");
|
||||
console.log("");
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Windows 경로를 Git Bash 스타일로 변환 (C:\... -> /c/...)
|
||||
sourcePath = projectRoot
|
||||
.replace(/\\/g, "/")
|
||||
.replace(/^([A-Z]):/, (match, drive) => `/${drive.toLowerCase()}`);
|
||||
}
|
||||
|
||||
const rsyncCmd = `"${rsyncPath}" -avz --delete ${excludeArgs} -e "${sshCmd}" "${sourcePath}/" ${sshTarget}:${sshPath}/`;
|
||||
console.log(`Command: ${rsyncCmd}`);
|
||||
execSync(rsyncCmd, { stdio: "inherit" });
|
||||
execSync(rsyncCmd, { stdio: "inherit", shell: true });
|
||||
console.log("✅ Files synced successfully");
|
||||
console.log("");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user