λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
NestJS

[NestJS] PM2 μ†Œκ°œλΆ€ν„° Docker + Github Action을 ν™œμš©ν•œ λ°°ν¬κΉŒμ§€

by LasBe 2024. 11. 24.
λ°˜μ‘ν˜•

πŸ“’ [NestJS] PM2 μ†Œκ°œλΆ€ν„° Docker + Github Action을 ν™œμš©ν•œ λ°°ν¬κΉŒμ§€


일반적으둜 NestJS ν˜Ήμ€ NextJSλŠ” Node.js의 λŸ°νƒ€μž„ μœ„μ—μ„œ λ™μž‘ν•˜κΈ° λ•Œλ¬Έμ— μ‹±κΈ€ μŠ€λ ˆλ“œ 기반으둜 μž‘λ™ν•©λ‹ˆλ‹€.

μ΄λŸ¬ν•œ κ΅¬μ‘°λŠ” λ§Žμ€ μš”μ²­μ΄ λ“€μ–΄μ˜¬ 경우 병λͺ©ν˜„상이 λ°œμƒν•΄ 이벀트 루프가 μ°¨λ‹¨λ˜μ–΄ 응닡성이 μ €ν•˜λ©λ‹ˆλ‹€.

이럴 λ•Œ μ—¬λŸ¬ ν”„λ‘œμ„ΈμŠ€λ₯Ό μƒμ„±ν•˜μ—¬ λ©€ν‹° μ½”μ–΄λ₯Ό ν™œμš©ν•˜κΈ° μœ„ν•΄ 주둜 μ‚¬μš©ν•˜λŠ” ν”„λ‘œμ„ΈμŠ€ λ§€λ‹ˆμ €κ°€ μžˆλŠ”λ°μš”, λ°”λ‘œ PM2μž…λ‹ˆλ‹€.

 

πŸ“Œ PM2λž€

PM2λŠ” Node.js μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ κ΄€λ¦¬ν•˜κΈ° μœ„ν•œ ν”„λ‘œλ•μ…˜ ν”„λ‘œμ„ΈμŠ€ λ§€λ‹ˆμ €μž…λ‹ˆλ‹€.

μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ μ‹€ν–‰, λͺ¨λ‹ˆν„°λ§, λ‘œλ“œ λ°ΈλŸ°μ‹±, 무쀑단 배포 등을 μ§€μ›ν•˜μ—¬, Node.js μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μ•ˆμ •μ μœΌλ‘œ μš΄μ˜ν•  수 있게 λ„μ™€μ€λ‹ˆλ‹€.

특히, μ„œλ²„μ—μ„œ Node.js μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μ‹€ν–‰ν•˜κ³  관리할 λ•Œ ν•„μš”ν•œ μ—¬λŸ¬ κΈ°λŠ₯을 ν†΅ν•©μ μœΌλ‘œ μ œκ³΅ν•˜μ—¬ κ°œλ°œμžμ™€ 운영자의 νŽΈμ˜μ„±μ„ λ†’μž…λ‹ˆλ‹€.

 

πŸ”Ž μž₯점

μ£Όμš”ν•œ 특μž₯점은 λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

  • ν”„λ‘œμ„ΈμŠ€ 관리
    • μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μ‹œμž‘, 쀑지, μž¬μ‹œμž‘, μ‚­μ œ λ“±μ˜ μž‘μ—…μ„ λͺ…λ Ήμ–΄λ‘œ κ°„λ‹¨νžˆ μˆ˜ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
    • ν”„λ‘œμ„ΈμŠ€ ν¬λž˜μ‹œ μ‹œ μžλ™ μž¬μ‹œμž‘μ„ μ§€μ›ν•˜μ—¬ μ„œλΉ„μŠ€ μ•ˆμ •μ„±μ„ 보μž₯ν•©λ‹ˆλ‹€.
  • ν΄λŸ¬μŠ€ν„° λͺ¨λ“œ 지원
    • λ©€ν‹° μ½”μ–΄ μ„œλ²„μ—μ„œ ν΄λŸ¬μŠ€ν„° λͺ¨λ“œλ‘œ μ‹€ν–‰ν•˜λ©΄ CPUλ₯Ό 효율적으둜 ν™œμš©ν•˜μ—¬ μ„±λŠ₯을 μ΅œμ ν™”ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
    • 단일 ν”„λ‘œμ„ΈμŠ€μ˜ ν•œκ³„λ₯Ό λ„˜μ–΄μ„œ 더 λ§Žμ€ μš”μ²­μ„ μ²˜λ¦¬ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  • 무쀑단 배포 (Zero Downtime Reload)
    • μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μž¬μ‹œμž‘ν•˜μ§€ μ•Šκ³ λ„ μƒˆ μ½”λ“œλ₯Ό μ μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
    • pm2 reload λͺ…λ ΉμœΌλ‘œ μ„œλΉ„μŠ€ 쀑단 없이 μ—…λ°μ΄νŠΈκ°€ κ°€λŠ₯ν•©λ‹ˆλ‹€.
  • 둜그 관리 및 λͺ¨λ‹ˆν„°λ§
    • μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ μ‹€ν–‰ 둜그(ν‘œμ€€ 좜λ ₯ 및 μ—λŸ¬)λ₯Ό μžλ™μœΌλ‘œ μ €μž₯ν•˜κ³  κ΄€λ¦¬ν•©λ‹ˆλ‹€.
    • μ‹€μ‹œκ°„μœΌλ‘œ 둜그λ₯Ό ν™•μΈν•˜κ±°λ‚˜(pm2 logs), 둜그 νŒŒμΌμ„ μ‘°νšŒν•  수 μžˆμŠ΅λ‹ˆλ‹€.
    • μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μƒνƒœλ₯Ό λͺ¨λ‹ˆν„°λ§ν•˜λŠ” CLI λ˜λŠ” μ›Ή λŒ€μ‹œλ³΄λ“œλ₯Ό μ œκ³΅ν•©λ‹ˆλ‹€.
  • ν™˜κ²½ λ³€μˆ˜ 관리
    • JSON λ˜λŠ” ecosystem.config.js 파일둜 ν™˜κ²½ λ³€μˆ˜λ₯Ό μ •μ˜ν•˜κ³  관리할 수 μžˆμŠ΅λ‹ˆλ‹€.
    • λ‹€μ–‘ν•œ μ‹€ν–‰ ν™˜κ²½(dev, staging, production)을 μ‰½κ²Œ μ„€μ •ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  • μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μƒνƒœ λͺ¨λ‹ˆν„°λ§
    • pm2 monit λͺ…λ ΉμœΌλ‘œ CPU, λ©”λͺ¨λ¦¬ μ‚¬μš©λŸ‰, μ‹€ν–‰ μƒνƒœ 등을 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.
    • PM2 Plus와 같은 μΆ”κ°€ μ„œλΉ„μŠ€λ₯Ό 톡해 더 μƒμ„Έν•œ λͺ¨λ‹ˆν„°λ§κ³Ό μ•Œλ¦Ό κΈ°λŠ₯을 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  • 배포 μžλ™ν™”
    • pm2 deploy λͺ…령을 μ‚¬μš©ν•΄ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ 원격 μ„œλ²„μ— μ‰½κ²Œ 배포할 수 μžˆμŠ΅λ‹ˆλ‹€.
    • Git 리포지토리와 μ—°λ™ν•˜μ—¬ μžλ™μœΌλ‘œ μ½”λ“œλ₯Ό 가져와 λ°°ν¬ν•˜λŠ” μ›Œν¬ν”Œλ‘œλ₯Ό ꡬ좕할 수 μžˆμŠ΅λ‹ˆλ‹€.

node μƒνƒœκ³„μ— λ„ˆλ¬΄λ‚˜ ν•„μš”ν•œ κΈ°λŠ₯듀을 꽉꽉 μ±„μ›Œ 넣은 것을 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.

 

πŸ”Ž μ£Όμš” λͺ…λ Ήμ–΄

pm2λ₯Ό μ‚¬μš©ν•˜κΈ° μœ„ν•΄μ„  사전에 μ„€μΉ˜κ°€ ν•„μš”ν•©λ‹ˆλ‹€.

$ npm i -g pm2

 

  • μ•± μ‹€ν–‰
$ pm2 start app.js --name my-app

 

  • ν™˜κ²½ νŒŒμΌμ„ μ‚¬μš©ν•œ μ•± μ‹€ν–‰
$ pm2 start ecosystem.config.js

  • μ•± 쀑지
$ pm2 stop my-app
$ pm2 delete my-app

 

  • pm2 μ’…λ£Œ
$ pm2 kill

  • μ‹€μ‹œκ°„ λͺ¨λ‹ˆν„°λ§
$ pm2 monit

  • μ‹€μ‹œκ°„ 둜그 확인
$ pm2 logs

 

πŸ“Œ ν™˜κ²½ 파일 (ecosystem.config.js)

PM2 ν™˜κ²½ νŒŒμΌμ€ 일반적으둜 ecosystem.config.js λ˜λŠ” ecosystem.json μ΄λ¦„μœΌλ‘œ μž‘μ„±ν•˜λ©° ν”„λ‘œμ νŠΈ λ£¨νŠΈμ— μœ„μΉ˜ν•©λ‹ˆλ‹€.

기본적인 속성은 λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

 

module.exports = {
  apps: [
    {
      // μ• ν”Œλ¦¬μΌ€μ΄μ…˜ 이름 (PM2μ—μ„œ μ‚¬μš©ν•  이름)
      // PM2 λͺ…λ Ήμ–΄μ—μ„œ 이 이름을 μ‚¬μš©ν•˜μ—¬ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μ œμ–΄ν•©λ‹ˆλ‹€.
      name: "my-app",

      // μ‹€ν–‰ν•  슀크립트 파일 경둜
      // Node.js 파일뿐만 μ•„λ‹ˆλΌ, Bash, Python λ“± λ‹€λ₯Έ μŠ€ν¬λ¦½νŠΈλ„ μ‹€ν–‰ κ°€λŠ₯ν•©λ‹ˆλ‹€.
      script: "./dist/main.js",

      // ν˜„μž¬ μž‘μ—… 디렉토리 (κΈ°λ³Έκ°’: ν˜„μž¬ 디렉토리)
      // μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ‹€ν–‰ 기쀀이 λ˜λŠ” 경둜λ₯Ό μ§€μ •ν•©λ‹ˆλ‹€.
      cwd: "/home/user/my-app",

      // μ‹€ν–‰ λͺ¨λ“œ: "fork" λ˜λŠ” "cluster"
      // fork: 단일 ν”„λ‘œμ„ΈμŠ€ μ‹€ν–‰
      // cluster: λ©€ν‹° μ½”μ–΄λ₯Ό ν™œμš©ν•˜μ—¬ μ—¬λŸ¬ ν”„λ‘œμ„ΈμŠ€ μ‹€ν–‰
      exec_mode: "cluster",

      // μ‹€ν–‰ν•  μΈμŠ€ν„΄μŠ€ 수
      // cluster λͺ¨λ“œμ—μ„œλ§Œ μœ νš¨ν•˜λ©°, "max"둜 μ„€μ •ν•˜λ©΄ λͺ¨λ“  CPU μ½”μ–΄λ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€.
      instances: "max",

      // μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ— 전달할 인수
      // μ‹€ν–‰ μ‹œ μ»€λ§¨λ“œλΌμΈ 인수둜 μ „λ‹¬λ©λ‹ˆλ‹€.
      args: ["--port", "3000"],

      // κΈ°λ³Έ ν™˜κ²½ λ³€μˆ˜ μ„€μ •
      // NODE_ENV, PORT λ“± μ‹€ν–‰ ν™˜κ²½μ„ μ •μ˜ν•©λ‹ˆλ‹€.
      env: {
        NODE_ENV: "development", // 개발 ν™˜κ²½
        PORT: 3000              // 기본 포트
      },

      // ν”„λ‘œλ•μ…˜ ν™˜κ²½μ—μ„œ μ‚¬μš©ν•  ν™˜κ²½ λ³€μˆ˜ μ„€μ •
      // "pm2 start ecosystem.config.js --env production"으둜 μ‹€ν–‰ μ‹œ μ μš©λ©λ‹ˆλ‹€.
      env_production: {
        NODE_ENV: "production", // ν”„λ‘œλ•μ…˜ ν™˜κ²½
        PORT: 8000              // ν”„λ‘œλ•μ…˜ 포트
      },

      // 둜그 파일 경둜 μ„€μ • (ν‘œμ€€ 좜λ ₯κ³Ό μ—λŸ¬ 둜그 톡합)
      log_file: "/var/logs/my-app-combined.log",

      // ν‘œμ€€ 좜λ ₯ 둜그 파일 경둜
      out_file: "/var/logs/my-app-out.log",

      // μ—λŸ¬ 둜그 파일 경둜
      error_file: "/var/logs/my-app-error.log",

      // 파일 λ³€κ²½ 감지 (κΈ°λ³Έκ°’: false)
      // true둜 μ„€μ •ν•˜λ©΄ 파일 λ³€κ²½ μ‹œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μžλ™μœΌλ‘œ μž¬μ‹œμž‘ν•©λ‹ˆλ‹€.
      watch: true,

      // κ°μ‹œμ—μ„œ μ œμ™Έν•  파일/폴더 (watchκ°€ true일 λ•Œ 유효)
      ignore_watch: ["node_modules", "logs"],

      // μžλ™ μž¬μ‹œμž‘ μ—¬λΆ€ (κΈ°λ³Έκ°’: true)
      // false둜 μ„€μ •ν•˜λ©΄ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ μ’…λ£Œλœ μƒνƒœλ‘œ μœ μ§€λ©λ‹ˆλ‹€.
      autorestart: true,

      // μž¬μ‹œμž‘ μ‹œλ„ 횟수 (κΈ°λ³Έκ°’: λ¬΄μ œν•œ)
      // νŠΉμ • 횟수 이상 μ‹€νŒ¨ν•˜λ©΄ ν”„λ‘œμ„ΈμŠ€λ₯Ό μ’…λ£Œν•©λ‹ˆλ‹€.
      max_restarts: 10,

      // μ΅œλŒ€ λ©”λͺ¨λ¦¬ μ‚¬μš©λŸ‰ (κΈ°λ³Έκ°’: μ œν•œ μ—†μŒ)
      // ν”„λ‘œμ„ΈμŠ€κ°€ 이 λ©”λͺ¨λ¦¬ μ œν•œμ„ μ΄ˆκ³Όν•˜λ©΄ μž¬μ‹œμž‘ν•©λ‹ˆλ‹€.
      max_memory_restart: "300M",

      // 개발 쀑 디버깅을 μœ„ν•œ 상세 둜그 ν™œμ„±ν™” (κΈ°λ³Έκ°’: false)
      // true둜 μ„€μ •ν•˜λ©΄ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ 디버그 둜그λ₯Ό 더 많이 좜λ ₯ν•©λ‹ˆλ‹€.
      debug: false,

      // μ‹€ν–‰ 쀑인 ν”„λ‘œμ„ΈμŠ€μ˜ CPU/λ©”λͺ¨λ¦¬ μ‚¬μš©λŸ‰μ„ 확인할 μ£ΌκΈ° (κΈ°λ³Έκ°’: 10초)
      // PM2 Dashboard와 같은 λͺ¨λ‹ˆν„°λ§ λ„κ΅¬μ—μ„œ μ‚¬μš©λ©λ‹ˆλ‹€.
      min_uptime: "1m",   // μ΅œμ†Œ μ‹€ν–‰ μ‹œκ°„ (ν”„λ‘œμ„ΈμŠ€κ°€ 이 μ‹œκ°„ 이전에 μ’…λ£Œλ˜λ©΄ λΉ„μ •μƒμœΌλ‘œ κ°„μ£Ό)
      max_uptime: "24h",  // μ΅œλŒ€ μ‹€ν–‰ μ‹œκ°„ (이 μ‹œκ°„μ΄ μ§€λ‚˜λ©΄ ν”„λ‘œμ„ΈμŠ€λ₯Ό μž¬μ‹œμž‘)

      // μ‚¬μš©μž μ •μ˜ 슀크립트λ₯Ό μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ‹€ν–‰ ν›„ μ‹€ν–‰
      post_start_script: "./scripts/postStart.sh"
    }
  ]
};

 

πŸ“Œ Github Action + Docker + PM2둜  NestJSλ°°ν¬ν•˜κΈ°

μ•„λ¬΄λž˜λ„ μš”μ¦˜μ€ 배포할 λ•Œ 도컀λ₯Ό μ‚¬μš©ν•˜λŠ” 게 선택이 μ•„λ‹Œ ν•„μˆ˜κ°€ λ˜μ–΄λ²„λ ΈμŠ΅λ‹ˆλ‹€.

이번 ν”„λ‘œμ νŠΈλ₯Ό 배포할 λ•Œ pm2와 도컀λ₯Ό μ‚¬μš©ν•œ 것을 μ˜ˆμ‹œλ‘œ λ“€μ–΄ μ†Œκ°œλ“œλ¦½λ‹ˆλ‹€.

 

πŸ”Ž ecosystem.config.js

module.exports = {
  apps: [
    {
      name: 'franchise-backend',
      script: './dist/main.js',
      exec_mode: 'cluster',
      instances: '2', // CPU μ½”μ–΄ 수
      max_memory_restart: '1000M', // ν”„λ‘œμ„ΈμŠ€μ˜ λ©”λͺ¨λ¦¬κ°€ 1000MB에 λ„λ‹¬ν•˜λ©΄ reload μ‹€ν–‰
      merge_logs: true, // ν΄λŸ¬μŠ€ν„° λͺ¨λ“œ μ‚¬μš© μ‹œ 각 ν΄λŸ¬μŠ€ν„°μ—μ„œ μƒμ„±λ˜λŠ” 둜그λ₯Ό ν•œ 파일둜 ν•©μΉ¨
      autorestart: true, // ν”„λ‘œμ„ΈμŠ€ μ‹€νŒ¨ μ‹œ μžλ™μœΌλ‘œ μž¬μ‹œμž‘ν• μ§€ 선택
      env_production: {
        NODE_ENV: 'production',
        PORT: 3000,
        DATABASE_URL: 'VAL_DATABASE_URL',
        OPENAPI_KEY: 'VAL_OPENAPI_KEY',
        DEFAULT_YEAR: 'VAL_DEFAULT_YEAR',
      },
    },
  ],
};

λ¨Όμ € λ°±μ•€λ“œ 앱을 μ–΄λ–»κ²Œ 싀행할지 pm2 μ„€μ •νŒŒμΌμ„ μž‘μ„±ν•©λ‹ˆλ‹€.

ν•„μš”ν•œ ν™˜κ²½ λ³€μˆ˜κ°€ μžˆλ‹€λ©΄ env_production λΈ”λŸ­ μ•ˆμ— μΆ”κ°€μ μœΌλ‘œ μž‘μ„±ν•΄ μ€λ‹ˆλ‹€.

μ €λŠ” μ²˜λ¦¬λŸ‰μ΄ 크게 λ§Žμ„ 것 같지 μ•Šμ•„ μš°μ„  μ½”μ–΄λ₯Ό 2개 μ •λ„λ§Œ μ‚¬μš©ν•˜λ„λ‘ ν–ˆμŠ΅λ‹ˆλ‹€.

 

πŸ”Ž Dockerfile

FROM node:22-alpine AS base

FROM base AS builder
  RUN apk add --no-cache libc6-compat
  WORKDIR /app
  COPY package.json pnpm-lock.yaml ./
  RUN corepack enable pnpm 
  RUN pnpm i --frozen-lockfile
  COPY . .
  ARG VAL_DATABASE_URL
  ARG VAL_OPENAPI_KEY
  ARG VAL_DEFAULT_YEAR
  RUN sed -i "s|VAL_DATABASE_URL|$VAL_DATABASE_URL|" ecosystem.config.js
  RUN sed -i "s|VAL_OPENAPI_KEY|$VAL_OPENAPI_KEY|" ecosystem.config.js
  RUN sed -i "s|VAL_DEFAULT_YEAR|$VAL_DEFAULT_YEAR|" ecosystem.config.js
  RUN pnpm build

FROM base AS runner
  WORKDIR /app
  RUN npm install -g pm2
  COPY --from=builder /app .
  RUN npm run prisma:generate
  EXPOSE 3000
  CMD ["pm2-runtime", "start", "ecosystem.config.js", "--env", "production"]

pnpm νŒ¨ν‚€μ§€ λ§€λ‹ˆμ €λ₯Ό μ΄μš©ν•œ λΉŒλ“œ λ°©λ²•μž…λ‹ˆλ‹€.

  • sed λͺ…λ Ήμ–΄λ‘œ 배포 μŠ€ν¬λ¦½νŠΈμ—μ„œ μ£Όμž…λ°›μ€ ν™˜κ²½λ³€μˆ˜λ₯Ό ecosystem에 μΉ˜ν™˜ν•΄ μ£Όμ—ˆμŠ΅λ‹ˆλ‹€.
  • μ‹€ν–‰ λΆ€λΆ„μ—μ„œ pm2λ₯Ό μ„€μΉ˜ν•΄ μ£Όμ—ˆμŠ΅λ‹ˆλ‹€.
  • pm2 startκ°€ μ•„λ‹Œ μ»¨ν…Œμ΄λ„ˆ ν™˜κ²½μ— μ΅œμ ν™”λ˜μ–΄
    데λͺ¬ 없이 ν”„λ‘œμ„ΈμŠ€λ₯Ό μ‹€ν–‰ν•˜λŠ” pm2-runtime startλͺ…λ Ήμ–΄λ₯Ό μ΄μš©ν•΄ μ‹€ν–‰ν•©λ‹ˆλ‹€.

 

πŸ”Ž Github Action Workflow

name: deploy

on:
  push:
    branches: [main]

jobs:
  app-build:
    runs-on: ubuntu-latest
    env:
      DOCKER_IMAGE_TAG: ${{ secrets.DOCKER_REPOSITORY }}/${{secrets.DOCKER_IMAGENAME}}:latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login docker hub
        uses: docker/login-action@v3
        with:
          registry: ${{ secrets.DOCKER_REPOSITORY }}
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}

      - name: Build and Push Docker Image
        uses: docker/build-push-action@v6
        with:
          push: true
          tags: ${{ env.DOCKER_IMAGE_TAG }}
          build-args: |
            VAL_DATABASE_URL=${{secrets.VAL_DATABASE_URL}}
            VAL_OPENAPI_KEY=${{secrets.VAL_OPENAPI_KEY}}
            VAL_DEFAULT_YEAR=${{secrets.VAL_DEFAULT_YEAR}}

      - name: execute remote ssh
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.SERVER_IP }}
          username: ${{ secrets.SERVER_USERNAME }}
          port: ${{ secrets.SERVER_PORT }}
          key: ${{ secrets.SERVER_KEY }}
          script: |
            docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
            docker pull ${{ env.DOCKER_IMAGE_TAG }}
            docker stop ${{secrets.DOCKER_IMAGENAME}} || true
            docker rm ${{secrets.DOCKER_IMAGENAME}} || true
            docker run -d --restart=always --name ${{secrets.DOCKER_IMAGENAME}} -p 3001:3000 ${{ env.DOCKER_IMAGE_TAG }}

이미지λ₯Ό λΉŒλ“œ 및 docker private repository에 push ν•˜κ³ , ssh λͺ…λ Ήμ–΄λ‘œ 배포 μ„œλ²„μ—μ„œ 이미지λ₯Ό 받은 ν›„ μ»¨ν…Œμ΄λ„ˆλ₯Ό μ‹€ν–‰μ‹œν‚€λŠ” 과정을 ν¬ν•¨ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.

ν•„μš”ν•œ ν™˜κ²½λ³€μˆ˜λ“€μ€ docker/build-push-actionμ—μ„œ build-argsλ₯Ό 톡해 도컀 파일둜 전달해 μ£Όλ©΄ λ©λ‹ˆλ‹€.

 

πŸ”Ž κ²°κ³Ό

μ»¨ν…Œμ΄λ„ˆμ— exec λͺ…λ Ήμ–΄λ‘œ 접속 ν›„ pm2 monit을 톡해 λͺ¨λ‹ˆν„°λ§ν•΄λ³΄λ‹ˆ μ—¬λŸ¬ μš”μ²­μ„ μ •μƒμ μœΌλ‘œ 각 ν”„λ‘œμ„ΈμŠ€μ— λΆ„λ°°ν•΄μ„œ μ²˜λ¦¬ν•˜λŠ” 것을 확인할 수 μžˆμ—ˆμŠ΅λ‹ˆλ‹€.

λ°˜μ‘ν˜•

λŒ“κΈ€


μ˜€ν”ˆ 채νŒ