๐Ÿค ์€์ง€log ๐Ÿค

[Front-end] CI/CD ๋ณธ๋ฌธ

๐Ÿ’š DevOps

[Front-end] CI/CD

Eun_zii 2022. 10. 31. 17:48

 

 

Jenkins๋กœ CI/CD Pipeline ๊ตฌ์ถ•ํ•˜๊ธฐ - ํ†ตํ•ฉ๋ณธ

CI/CD ๋ž€? CI ๋ž€? ๊ฐœ๋ฐœ์ž๋ฅผ ์œ„ํ•œ ์ž๋™ํ™” ํ”„๋กœ์„ธ์Šค์ธ ์ง€์†์ ์ธ ํ†ตํ•ฉ ( Continuous Integration ) ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ƒˆ๋กœ์šด ์ฝ”๋“œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ์ •๊ธฐ์ ์œผ๋กœ ๋นŒ๋“œ/ ํ…Œ์ŠคํŠธ ๋˜์–ด ๊ณต์œ  Repository์— (ex. git,github) ํ†ตํ•ฉํ•˜

code00.tistory.com

โฌ†๏ธ ๐Ÿ’™< ์ง„์งœ์ง„์งœ_์ตœ์ข…_ํ†ตํ•ฉ๋ณธ >๐Ÿ’™ โฌ†๏ธ

 

 

CI/CD ๋ž€?

CI ๋ž€?   ๊ฐœ๋ฐœ์ž๋ฅผ ์œ„ํ•œ ์ž๋™ํ™” ํ”„๋กœ์„ธ์Šค์ธ  ์ง€์†์ ์ธ ํ†ตํ•ฉ ( Continuous Integration ) 

์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ƒˆ๋กœ์šด ์ฝ”๋“œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ์ •๊ธฐ์ ์œผ๋กœ ๋นŒ๋“œ/ ํ…Œ์ŠคํŠธ ๋˜์–ด ๊ณต์œ  Repository์— (ex. git,github) ํ†ตํ•ฉํ•˜๋Š”๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค.

๋‹ค์ˆ˜์˜ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ž‘์—…ํ•  ๊ฒฝ์šฐ ๋ ˆํฌ์ง€ํ† ๋ฆฌ์— ์Œ“์ด๋Š” commit๋“ค์ด ์ถฉ๋Œํ•˜๋Š” ๊ฒƒ์„ ์ž๋™ํ™”๋œ ๋นŒ๋“œ์™€ ํ…Œ์ŠคํŠธ๋กœ ๋ฐฉ์ง€ํ• ์ˆ˜ ์žˆ๋‹ค.

CD ๋ž€?  ์ง€์†์ ์ธ ๋ฐฐํฌ ( Continuous Deployment ) 

“์ˆ˜๋™์ " ์œผ๋กœ ๋ฐฐํฌํ•˜๋Š”๊ฒƒ์„ ์ง€์†์ ์ธ ์ œ๊ณต์ด๋ผ ํ•˜๋Š”๋ฐ, ์ด๊ฒƒ์„ “์ž๋™ํ™””ํ•˜๋Š”๊ฒƒ์ด ์ง€์†์ ์ธ ๋ฐฐํฌ ( Continuous Deployment ) ์ด๋‹ค.

 

๐Ÿ“Œ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ ๋‹จ๊ณ„ ๋ถ€ํ„ฐ ๋ฐฐํฌ ๋•Œ ๊นŒ์ง€ ๋ชจ๋“  ๋‹จ๊ณ„๋“ค์„ ์ž๋™ํ™”๋ฅผ ํ†ตํ•ด์„œ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ฐฐํฌ ํ• ์ˆ˜์žˆ๋„๋ก ๋งŒ๋“œ๋Š”๊ฒƒ 

 

โœ… ๊ฐœ๋ฐœํŒ€์—์„œ ์ฒดํฌํ•ด์•ผ๋  ์‚ฌํ•ญ

  • ๋ณ€๊ฒฝ์ด ์ƒˆ๋กœ์šด ๊ฒฐํ•จ์„ ์œ ๋ฐœํ•˜์ง€ ์•Š๋Š”์ง€ ํ™•์ธํ•˜๋Š” ์ฝ”๋“œ ์ปค๋ฒ„๋ฆฌ์ง€๋กœ ์ง€์†์  ํ…Œ์ŠคํŠธ
  • ๋ณด์•ˆ, ์„ฑ๋Šฅ ๋ฐ ๊ธฐํƒ€ ์ฝ”๋“œ ํ’ˆ์งˆ ๋ฌธ์ œ๋ฅผ ํ…Œ์ŠคํŠธํ•˜๋Š” ์ •์ /๋™์  ์ฝ”๋“œ ๋ถ„์„ ํˆด
  • API ๋ณด์•ˆ์„ ์œ„ํ•ด ๋ชจ๋ฒ” ์‚ฌ๋ก€๋ฅผ ํฌํ•จํ•œ ์‹œํ”„ํŠธ-๋ ˆํ”„ํŠธ(shift-left) ๋ณด์•ˆ ์‹ค์ฒœ (์กฐ๊ธฐ๊ฒฐํ•จ ๊ฐ์ง€)
  • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๊ณผ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค์— ๋Œ€ํ•œ ๊ด€์ฐฐ ๊ฐ€๋Šฅ์„ฑ ํ‘œ์ค€
  • ์‚ฌ์šฉ์ž ์ผ๋ถ€์— ๋Œ€ํ•ด ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์„ ์ผœ๊ณ  ๋„๊ฑฐ๋‚˜ ์ œ์–ดํ•˜๊ธฐ ์œ„ํ•œ ๊ธฐ๋Šฅ ํ”Œ๋ž˜๊น…โ€‹

ํ”„๋กœ๋•์…˜์˜ ๋ฐฐํฌ ์ž๋™ํ™”๋Š” ๊ทธ ๊ฒฐ๊ณผ๊ฐ€ ๋น„์ง€๋‹ˆ์Šค, ์ตœ์ข… ์‚ฌ์šฉ์ž์—๊ฒŒ ์˜ํ–ฅ์„ ๋ฏธ์น˜๋Š” ๋งŒํผ ์œ„ํ—˜์ด ํฌ๊ธฐ ๋•Œ๋ฌธ์—

๋ฐฐํฌ ํ”„๋กœ์„ธ์Šค์—๋Š” ์ง€์†์  ํ…Œ์ŠคํŠธ์™€ ์ฒ ์ €ํ•œ ์˜ค๋ฅ˜์ฒ˜๋ฆฌ๊ฐ€ ํฌํ•จ๋˜์–ด์•ผํ•œ๋‹ค.

โ€‹

โ€‹

 

ํด๋ผ์šฐ๋“œ ์„œ๋น„์Šค | ํด๋ผ์šฐ๋“œ ์ปดํ“จํŒ… ์†”๋ฃจ์…˜| Amazon Web Services

๊ฐœ๋ฐœ์ž, ๋ฐ์ดํ„ฐ ์‚ฌ์ด์–ธํ‹ฐ์ŠคํŠธ, ์†”๋ฃจ์…˜์Šค ์•„ํ‚คํ…ํŠธ ๋˜๋Š” AWS์—์„œ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์šฐ๋Š” ๋ฐ ๊ด€์‹ฌ์ด ์žˆ๋Š” ๋ชจ๋“  ์‚ฌ์šฉ์ž์šฉ ๋ฌด๋ฃŒ ์˜จ๋ผ์ธ ๊ต์œก AWS ์ „๋ฌธ๊ฐ€๊ฐ€ ๊ตฌ์ถ•ํ•œ 500๊ฐœ ์ด์ƒ์˜ ๋ฌด๋ฃŒ ๋””์ง€ํ„ธ ๊ต์œก ๊ณผ์ •

aws.amazon.com

 

AWS ๊ฐ€์ž…

  • ๊ฒฐ์ œ ๊ด€๋ จ E-mail ๋กœ ๋ฐ›๊ธฐ ํ•„์ˆ˜
  • MFA ์ฝ”๋“œ๋กœ ์ด์ค‘ ๋ณด์•ˆ ํ•ด์ฃผ๊ธฐ

 

๐Ÿ”† AWS EC2 ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ

 

 

 

์ œ์ผ๋จผ์ € AWS ์— ์ ‘์†ํ›„ EC2 ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•ด ์ค๋‹ˆ๋‹ค.

* ์ƒ์„ฑ์ „ Resion ์„ ํƒ ํ•„ํžˆ ํ•ด์ฃผ์„ธ์š”.

๋‹ค๋ฅธ Resion์˜ ๋‚ด์šฉ์€ ์„œ๋กœ ๊ณต์œ ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

 

 

์ด๋ฆ„ ์นธ์— EC2์˜ ์šฉ๋„ ํ˜น์€ ์ด๋ฆ„์ ๊ธฐ.

* ์ถ”ํ›„ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ

 

 

Server OS ์„ ํƒ ํ•˜๊ธฐ

* ๋ณธ๊ธ€์—์„œ๋Š” Amazon Linux๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

 

๐Ÿ’ก AWS ์ตœ์ดˆ ๊ฐ€์ž…์‹œ ํ”„๋ฆฌํ‹ฐ์–ด ์„œ๋น„์Šค 80~90๊ฐœ ์ด์šฉ ๊ฐ€๋Šฅ. EC2๋Š” ํ•œ๋‹ฌ ๊ธฐ์ค€ 750์‹œ๊ฐ„์”ฉ ๋ฌด๋ฃŒ๋กœ ๊ฐ€๋Šฅ.

๋‹จ, EC2๋Š” ์ธ์Šคํ„ด์Šค ๊ฐœ ๋‹น์ด ์•„๋‹Œ ๋งŒ๋“ค์–ด๋†“์€ ์ธ์Šคํ„ด์Šค ์ด ์‹œ๊ฐ„์œผ๋กœ ์ ์šฉ. ex) 10๊ฐœ์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์‚ฌ์šฉํ• ์‹œ ๊ฐ 75์‹œ๊ฐ„์”ฉ ์ด์šฉ ๊ฐ€๋Šฅ ๐Ÿ’ก

 

 

์ธ์Šคํ„ด์Šค ์œ ํ˜• ์„ ํƒ - ๋ฌด๋ฃŒ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ธ์Šคํ„ด์Šค ์œ ํ˜• ์„ ํƒ

* ๋‚ด๊ฐ€ ๊ฐ–๊ณ ์ž ํ•˜๋Š” ์ปดํ“จํ„ฐ์˜ CPU, Memory ๋ฅผ ์„ ํƒํ•˜๋Š”๊ฒƒ

 

 

ํ‚คํŽ˜์–ด

* ์ธ์Šคํ„ด์Šค์— ์ ‘์†ํ•˜๊ธฐ ์œ„ํ•œ ์•”ํ˜ธํ™”๋œ ํ† ํฐ ํ˜น์€ ์•”ํ˜ธํ™”๋œ Key-file

 

๐Ÿ”† ํ‚คํŽ˜์–ด ์ƒ์„ฑํ•˜๊ธฐ

 

์ƒˆ ํ‚คํŽ˜์–ด ์ƒ์„ฑ โžก <๋ณธ์ธ์ด ์‹๋ณ„ํ• ์ˆ˜ ์žˆ๋Š” ์ด๋ฆ„ ์ž‘์„ฑ> โžก ์œ ํ˜•, ํŒŒ์ผ ํ˜•์‹ ์„ ํƒ โžก ํ‚ค ํŽ˜์–ด ์ƒ์„ฑ

 

* Mac OS ์‚ฌ์šฉ์ž๋“ค์€ Putty๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— .pem 

Window ์‚ฌ์šฉ์ž์ค‘ Putty,Xshell์„ ์ด์šฉํ•  ์˜ˆ์ •์ด๋ผ๋ฉด .ppk๋ฅผ ์„ ํƒ

 

 

 

๋„คํŠธ ์›Œํฌ ์„ค์ •์€ ๋„˜์–ด๊ฐ€์ฃผ๊ธฐ

 

 

์Šคํ† ๋ฆฌ์ง€๋Š” 30GB ๊นŒ์ง€ ๋ฌด๋ฃŒ์ด๋ฏ€๋กœ 30GB๋กœ ์„ค์ • ํ•ด์ฃผ๊ธฐ

 

 

๊ณ ๊ธ‰ ์„ธ๋ถ€ ์ •๋ณด๋„ ๋„˜์–ด๊ฐ€๊ธฐ

 

 

์ธ์Šคํ„ด์Šค ๊ฐœ์ˆ˜ <2> ๋กœ ์„ค์ •ํ•ด์ฃผ๊ธฐ

* Jenkins ์šฉ / Nginx ์šฉ ์ด 2๊ฐœ ํ•„์š”ํ•จ

 

์š”์•ฝ ์ •๋ณด ํ™•์ธํ›„ ์ธ์Šคํ„ด์Šค ์‹œ์ž‘ โญ๏ธ

 

 

๋งŒ๋“ค์–ด์ง„ ์ธ์Šคํ„ด์Šค๋Š”

Docker / Nginx ๋˜๋Š” Jenkins / Nginx 

๋ณธ์ธ์ด ๊ด€๋ฆฌํ•˜๊ธฐ ํŽธํ•œ ์ด๋ฆ„์œผ๋กœ ๋ณ€๊ฒฝํ•ด์ฃผ๊ธฐ.

 

๐Ÿ”† SSH Client Tool์„ ์ด์šฉํ•ด EC2 ์ธ์Šคํ„ด์Šค ์ ‘์†

 

 

Termius for macOS | Download

- Split view. You can open up to 4 terminals inside a single tab. - Enterprise SSO. Termius supports more than 30 identity providers.

termius.com

ํŽธ๋ฆฌํ•˜๊ฒŒ ์ธ์Šคํ„ด์Šค ์ ‘์†ํ•˜๋ ค๋ฉด SSH Client Tool์„ ์ด์šฉํ•˜๋Š”๋ฐ

๋‹ค์–‘ํ•œ tool์ด ์žˆ๊ธฐ๋•Œ๋ฌธ์— ์ž์‹ ์—๊ฒŒ ๋งž๋Š”๊ฒƒ์„ ์„ ํƒํ•˜๋ฉด ๋จ

* ๋‚ด๊ฐ€ ์‚ฌ์šฉํ•œ Tool 

 

ํšŒ์›๊ฐ€์ž… ํ•ด์ฃผ๊ธฐ

 

์„ค์น˜๊ฐ€ ์™„๋ฃŒ๋˜์—ˆ๋‹ค๋ฉด New Host๋ฅผ ๋งŒ๋“ค์–ด์ค๋‹ˆ๋‹ค.

 

 

AWS์—์„œ ๋งŒ๋“  ์ธ์Šคํ„ด์Šค ์ด๋ฆ„ ์œผ๋กœ Label ์ž…๋ ฅํ›„ ,

Adress ์นธ์— Ec2 ์ธ์Šคํ„ด์Šค Public IPv4 ์ฃผ์†Œ ์ž…๋ ฅ (์ƒ์„ฑ๋œ AWS ์ธ์Šคํ„ด์Šค์—์„œ ํ™•์ธ ๊ฐ€๋Šฅ)

 

 

EC2 ์ธ์Šคํ„ด์Šค๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ " ec2-user " ์ด๋ผ๋Š” ๊ณ„์ •์ด ๋งŒ๋“ค์–ด ์ง€๊ณ 

๋กœ๊ทธ์ธ ๋ฐฉ์‹์€ ID,PW๊ฐ€ ์•„๋‹Œ KEY (EC2 ํ‚คํŽ˜์–ดํ• ๋•Œ ๋ฐ›์€ .pemํŒŒ์ผ) ๋กœ ๋กœ๊ทธ์ธ์„ ํ•จ

 

 

 

Password ์˜† Keys ํด๋ฆญํ›„ (๋“ฑ๋กํ‚ค๊ฐ€ ์—†๋‹ค๋ฉด) <create a new key>  โžก
์ด๋ฆ„ ๋“ฑ๋กํ›„ Drag & Drop ๋˜๋Š” import from keyfile ๋กœ KEY-file (EC2 ํ‚คํŽ˜์–ดํ• ๋•Œ ๋ฐ›์€ .pemํŒŒ์ผ) ๊ฐ€์ ธ์˜ค๊ธฐ
โžก (์•”ํ˜ธํ™”๋œ ํŒŒ์ผ์ด ์—ด๋ ธ๋‹ค๋ฉด) ์˜ค๋ฅธ์ชฝ ์ƒ๋‹จ save

 

 

๊ฐ™์€ ๋ฐฉ๋ฒ•์œผ๋กœ Nginx ๋„ ๋งŒ๋“ค์–ด ์ฃผ๊ธฐ

 

 

์ด๋Ÿฐ ํ™”๋ฉด์ด ๋‚˜์™”๋‹ค๋ฉด

์„ฑ๊ณตโญ๏ธ

 

โš ๏ธ ERROR โš ๏ธ

 

๋งŒ์•ฝ ์ด๋Ÿฐ ํ™”๋ฉด์ด ๋‚˜์˜ค์…จ๋‹ค๋ฉด ?

 

 

Username์„ ๋ฐ”๊ฟ”์„œ ํ•œ๋ฒˆ ํ•ด๋ณด์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค!

*ec2-user ์ด ๋งž๋Š” name ์ž…๋‹ˆ๋‹ค. ์ž„์˜ ์„ค์ •ํ•˜์‹œ๋ฉด ์—๋Ÿฌ ๋‚ฉ๋‹ˆ๋‹ค.

 

๐Ÿ”† Docker ์„ค์น˜

* Command ๊ถŒํ•œ ์—†์„๋•Œ๋Š” ์ปค๋งจ๋“œ ์•ž์— โŒจ๏ธ   sudo su ์ž…๋ ฅํ›„ ์ปค๋งจ๋“œ ์ž…๋ ฅํ•˜๊ธฐ *

 

 

โŒจ๏ธ   sudo yum update -y 

* ์ตœ์ดˆ yum Repository๋ฅผ ์ตœ์‹ ํ™” ํ•ด์ค๋‹ˆ๋‹ค.

 

โŒจ๏ธ   yum install docker -y

* Docker ์„ค์น˜

 

โŒจ๏ธ   docker -v

* Docker ๋ฒ„์ „ ํ™•์ธ

 

โŒจ๏ธ   sudo service docker start

* Docker ์‹คํ–‰ ํ™•์ธ

 

โŒจ๏ธ   usermod -aG docker ec2-user

* Docker์— ์œ ์ €๋ฅผ ๋“ฑ๋ก

 

โŒจ๏ธ   exit

* ์ ‘์† ์ข…๋ฃŒ ํ›„ ๋‹ค์‹œ ์žฌ์ ‘์†

 

โŒจ๏ธ   docker run hello-world

* Docker ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•ด์„œ ํ…Œ์ŠคํŠธ

 

๋„์ปค ์„ค์น˜ ์™„๋ฃŒ โญ๏ธ

 

 

๐Ÿ”† Docker ์— Jenkins ์„ค์น˜ํ•˜๊ธฐ

 

โŒจ๏ธ   docker run -itd --name jenkins -p 8085:8080 jenkins/jenkins:lts

* Docker์— Jenkins ๋ฅผ ์ตœ์‹ ๋ฒ„์ „์œผ๋กœ ์„ค์น˜ํ•˜๊ณ  ์ปจํ…Œ์ด๋„ˆ๋กœ ์‹คํ–‰

 

โŒจ๏ธ   docker ps

* ์  ํ‚จ์Šค๊ฐ€ ์ž‘๋™ํ•˜๋Š”์ง€ ํ™•์ธํ•ด์ฃผ๊ธฐ

 

 

EC2 ์ธ์Šคํ„ด์Šค์—์„œ Docker ์ธ์Šคํ„ด์Šค ํด๋ฆญํ›„ ํ•˜๋‹จ์— ๋‚˜์˜ค๋Š” 

๋ณด์•ˆ โžก ๋ณด์•ˆ๊ทธ๋ฃน ๋ฐ‘ sg-04ab805... ํด๋ฆญ โžก ์ธ๋ฐ”์šด๋“œ ๊ทœ์น™ โžก ์ธ๋ฐ”์šด๋“œ ๊ทœ์น™ ํŽธ์ง‘ โžก  ๊ทœ์น™ ์ถ”๊ฐ€

์—์„œ <8085> ํฌํŠธ ์ถ”๊ฐ€ํ•ด์ฃผ๊ธฐ

 

 

์ธ์Šคํ„ด์Šค ํŽ˜์ด์ง€๋กœ ๋Œ์•„๊ฐ€์„œ ํผ๋ธ”๋ฆญ IPv4 ์ฃผ์†Œ๋ฅผ ๊ฐ€์ ธ์™€์„œ, http://ip:8085/ ๋กœ ์ ‘์†ํ•ฉ๋‹ˆ๋‹ค.

* http://๋‚ด ๋„์ปค ํผ๋ธ”๋ฆญIPv4์ฃผ์†Œ:8085/

 

 

์  ํ‚จ์Šค์˜ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•˜๋ผ๊ณ  ๋‚˜์˜ค๋Š”๋ฐ, ํŒจ์Šค์›Œ๋“œ๋Š” ์  ํ‚จ์Šค ์ปจํ…Œ์ด๋„ˆ์˜ ๊ฒฝ๋กœ์— ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— exec ๋ช…๋ น์–ด๋กœ ํ„ฐ๋ฏธ๋„์—์„œ ์‹คํ–‰์ค‘์ธ ์  ํ‚จ์Šค ์ปจํ…Œ์ด๋„ˆ์— ์ ‘๊ทผํ•ด์„œ ์–ด๋“œ๋ฏผ ํŒจ์Šค์›Œ๋“œ๋ฅผ ์ฐพ์•„๋ด…๋‹ˆ๋‹ค.

 

 

โŒจ๏ธ   docker exec -it jenkins /bin/bash

โŒจ๏ธ   cat /var/jenkins_home/secrets/initialAdminPassword

 

ํŒจ์Šค์›Œ๋“œ๋ฅผ ์ž…๋ ฅํ•˜๊ณ  ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์„ค์น˜ํ•ด์ค๋‹ˆ๋‹ค.

 

 

ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ์„ค์น˜๋˜๋ฉด ์–ด๋“œ๋ฏผ ๊ณ„์ •์„ ๋งŒ๋“ค๊ฒŒ๋ฉ๋‹ˆ๋‹ค.

 

 

ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ์„ค์น˜๋˜๊ณ  ์–ด๋“œ๋ฏผ ๊ณ„์ • ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค.

 

 

Jenkins ์ ‘์† ์™„๋ฃŒ โญ๏ธ

 

๐Ÿ”† Jenkins ์™€ Gitea ์—ฐ๋™ ํ•ด์ฃผ๊ธฐ

 

 

Jenkins ๋Œ€์‹œ๋ณด๋“œ์—์„œ Jenkins ๊ด€๋ฆฌ๋กœ ๋“ค์–ด๊ฐ€์ฃผ์„ธ์š”.

 

 

Jenkins ๊ด€๋ฆฌ ์—์„œ  ํ”Œ๋Ÿฌ๊ทธ์ธ ๊ด€๋ฆฌ์— ๋“ค์–ด๊ฐ€์ฃผ์„ธ์š”.

 

 

  • Multibranch Scan Webhook Trigger
  • Parameterizwd Trigger
  • jQuery
  • Delivery Pipeline
  • Gitea Plugin
  • NodeJS

ํ”Œ๋Ÿฌ๊ทธ์ธ ๊ด€๋ฆฌ โžก ์„ค์น˜ ๊ฐ€๋Šฅ โžก ๊ฒ€์ƒ‰ ์œผ๋กœ ํ•ด๋‹น ํ”Œ๋Ÿฌ๊ทธ์ธ๋“ค ์„ค์น˜ํ•ด์ฃผ์„ธ์š”.

 

 

๋‹ค์‹œ Jenkins ๊ด€๋ฆฌ โžก ์‹œ์Šคํ…œ ์„ค์ • ์—์„œ ์Šคํฌ๋กค ๋‚ด๋ฆฌ๋‹ค๋ณด๋ฉด

 

 

Gitea Server ์„ค์ • ์ด ๋‚˜์˜ค๊ณ  ์ž‘์„ฑํ•ด์ฃผ์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

* Name, URL (Gitea ์ฃผ์†Œ), Manage hooks ์ฒดํฌโœ… ํ›„ Credentials ์ ์šฉ (์—†์œผ๋ฉด + Add ํด๋ฆญ)

 

 

* Server URL ์ž‘์„ฑํ›„ ๋ฐ‘์— Gitea Version ์ด ๋– ์•ผ ์ •์ƒ์ ์œผ๋กœ ์—ฐ๋™ ๋œ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

๐Ÿ”† Gitea Token ๋งŒ๋“ค๊ธฐ

 

 

Gitea ์ ‘์†ํ›„ ์šฐ์ธก ์ƒ๋‹จ ํ”„๋กœํ•„ โžก ์„ค์ •์— ๋“ค์–ด๊ฐ€์ค๋‹ˆ๋‹ค.

 

 

์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ โžก ํ† ํฐ์ด๋ฆ„ ์ž…๋ ฅํ›„ ํ† ํฐ์ƒ์„ฑ โžก ๊ฐ€๋ ค์ง„ ๋ถ€๋ถ„ ํ† ํฐ์€ ๋ณต์‚ฌํ•ด๋†“์•„์ฃผ์„ธ์š”.

* ํ† ํฐ์€ ์ƒ์„ฑ๋•Œ ๋ง๊ณ  ๋‹ค์‹œ ๋ณผ์ˆ˜ ์—†์œผ๋‹ˆ ์•ˆ์ „ํ•œ๊ณณ์— ๋ณต์‚ฌ ํ•ด๋‘์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

๋‹ค์‹œ Jenkins๋กœ ๋Œ์•„์™€์„œ Credentials-Gitea์šฉ ์œผ๋กœ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”.

* Kind ์—์„œ Gitea Personal Access Token ์„ ํƒํ›„ ํ† ํฐ ์ž…๋ ฅํ•ด์ฃผ๊ธฐ

 

Credentials ๊นŒ์ง€ ์„ ํƒํ•ด์ค€ ๋’ค ์™ผ์ชฝ ํ•˜๋‹จ ์ €์žฅ ๋ˆŒ๋Ÿฌ์ฃผ๊ธฐ

 

 

Jenkins ๋Œ€์‹œ๋ณด๋“œ ์—์„œ <์ƒˆ๋กœ์šด Item> ์œผ๋กœ ๋“ค์–ด๊ฐ‘๋‹ˆ๋‹ค.

 

 

Item name ์ž‘์„ฑํ›„ Multibranch Pipeline ์œผ๋กœ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”.

 

 

name ๊ณผ ์„ค๋ช… ์ž‘์„ฑํ›„ Branch Sources ์— Gitea ์„ ํƒํ›„ ์ •๋ณด ์ž…๋ ฅํ•ด์ฃผ๊ธฐ

* Gitea ๊ฐ€ ๋œจ์ง€ ์•Š๋Š”๋‹ค๋ฉด gitea plugin ์„ค์น˜ ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

 

 

gitea server ์—ฐ๊ฒฐ (์‹œ์Šคํ…œ์„ค์ •์—์„œ ์ž…๋ ฅํ•œ Gitea server) โžก Credentials ์„ ํƒ โžก

Owner (Gitea ๋ณธ์ธ name) ๋“ฑ๋กํ•˜๋ฉด ํ•˜๋‹จ์— ๋ ˆํฌ์ง€ํ† ๋ฆฌ๊ฐ€ ์ž๋™์œผ๋กœ ๋“ฑ๋ก ๋ฉ๋‹ˆ๋‹ค.

 

์™ผ์ชฝ ํ•˜๋‹จ์— Save ํด๋ฆญ

 

 

์—ฐ๋™ ์™„๋ฃŒ โญ๏ธ

 

๐Ÿ”† Jenkins File

 

๋งŒ๋“ค์–ด๋‘” Multibranch pipeline repository ์ด๋ฆ„์˜† ํ™”์‚ดํ‘œ ํด๋ฆญ โžก Configure๋กœ ๋“ค์–ด๊ฐ€์ฃผ์„ธ์š”.

 

 

์—ฐ๊ฒฐ ํ•ด๋‘์—ˆ๋˜ Branch Sources ์— Gitea server ์•„๋ž˜์— Behaviours ์™€ Property strategy ๋ฅผ ์‚ฌ์ง„๋Œ€๋กœ ์„ค์ •

* ์•„๋ž˜ Add ๋ฒ„ํŠผ ํด๋ฆญํ›„ Filter by name (with regular expression) ์ถ”๊ฐ€ ํ›„ " (main.*) " ์ž‘์„ฑ

 

 

Build Configuration์€ Jenkins-file์ด default ๊ฐ’์œผ๋กœ ๋˜์–ด์žˆ์Œ์œผ๋กœ ๊ทธ๋Œ€๋กœ ๋‘๊ณ  ๋„˜์–ด๊ฐ€์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

 

Multibranch Scan Webhook Trigger ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์„ค์น˜ ํ–ˆ๋‹ค๋ฉด 

Scan Multibranch Pipeline Triggers ์ด ์ƒ๊ธฐ๊ณ  ๋‘˜๋‹ค ์ฒดํฌ๋ฐ•์Šคโœ… ์„ ํƒํ›„ ์‚ฌ์ง„๊ณผ ๊ฐ™์ด ์ž‘์„ฑ

* Trigger token ์ด๋ฆ„์€ Gitea์—์„œ webhook ์„ค์ •์„ ํ•  ๋•Œ header์— ๋‹ด์„ token์„

์ง€์ •ํ•ด์ฃผ๋Š” ๊ฑฐ๊ธฐ ๋•Œ๋ฌธ์— ์ž์‹ ์ด ์›ํ•˜๋Š” ์ด๋ฆ„์œผ๋กœ ์ง€์ •ํ•ด์ฃผ๋ฉด ๋จ

 

์™ผ์ชฝ ํ•˜๋‹จ Save ํด๋ฆญ

 

Jenkins ์—ฐ๋™์€ ๋˜์—ˆ์ง€๋งŒ Jenkinsfile not found ๋ผ๊ณ  ๋œจ์…จ์„ ๊ฒ๋‹ˆ๋‹ค.

 

 VSCODE์— ํด๋” ๋งŒ๋“ค์–ด์ฃผ์‹œ๊ณ 

์ƒˆํŒŒ์ผ โžก  Jenkinsfile ์„ ๋งŒ๋“ค๋ฉด ์•„์ €์”จ์–ผ๊ตด ๋ชจ์–‘์˜ ํŒŒ์ผ์ด ์ƒ์„ฑ๋จ

 

๐Ÿ“Œ Gitea์™€ VSCODE๋ฅผ ๋จผ์ € ์—ฐ๋™ํ•ด์ฃผ์…”์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Gitea ์—์„œ ์ƒˆ๋กœ์šด ๋ ˆํฌ์ง€ํ† ๋ฆฌ ์ƒ์„ฑํ›„ VSCODE์—์„œ ์—ฐ๋™ํ•ด์ฃผ์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

def FAILED_STAGE
pipeline {
    agent any
        tools {
            nodejs "node16.10.0"
        }
    stages {
         // pull >> test >> build >> sonarqube >> deploy
        stage("Checkout") {
            steps{
                echo "checkout start"
                
                script{ 
                    FAILED_STAGE=env.STAGE_NAME
                    // source code management 
                    // ์•„์ดํ…œ์—์„œ ์—ฐ๊ฒฐํ•œ git ์„ ํ†ตํ•ด ์†Œ์Šค๋ฅผ ๋ฐ›์•„์˜จ๋‹ค.
                    checkout scm;
                }
                echo "checkout end"
            }
        }
        stage('Lint') {
            steps {
                script {
                    FAILED_STAGE=env.STAGE_NAME
                    sh "npm install"
                    sh "npm run lint"
                }
            }
        }
        stage('Test') {
            steps {
                script {
                    FAILED_STAGE=env.STAGE_NAME
                    sh 'npm run test'
                }
            }
        }
        stage("Build") {
            steps {
                script{
                    FAILED_STAGE=env.STAGE_NAME
                }
                sh "npm run build"
                
            }
        }
        stage("Sonarqube") {
            steps{
                script{
                    FAILED_STAGE=env.STAGE_NAME
                    def scannerHome = tool 'sonarqube-scanner';
                    withSonarQubeEnv(๐Ÿ“ŒcredentialsId:"SONARQUBE",installationName:'sonarqube'๐Ÿ“Œ) {
                        sh "${scannerHome}/bin/sonar-scanner"
                    }
                }
            }
        }
        // stage('Quality Gate'){
        //     steps{
        //         timeout(time: 1, unit: 'MINUTES') {
        //             script{
        //                 echo "Start"
        //                 FAILED_STAGE=env.STAGE_NAME
        //                 def qg = waitForQualityGate()
        //                 echo "Status: ${qg.status}"
        //                 if(qg.status != 'OK') {
        //                     echo "NOT OK Status: ${qg.status}"
        //                     error "Pipeline aborted due to quality gate failure: ${qg.status}"
        //                 } else{
        //                     echo "OK Status: ${qg.status}"
        //                 }
        //                 echo "End"
        //             }
        //         }
        //     }
        // }
        stage("Transfer") {
            steps([$class:"BapSshPromotionPublisherPlugin"]){
                script{
                    FAILED_STAGE=env.STAGE_NAME
                    sshPublisher(
                        publishers:[
                            sshPublisherDesc(
                                configName:"nginx",
                                verbose:true,
                                transfers:[
                                    sshTransfer(
                                        sourceFiles:"**/**",
                                        excludes:"**/node_modules/**",
                                        execCommand:"chmod +x /home/ec2-user/deploy/deploy.sh"
                                    )
                                ],
                            )
                        ]
                        
                    )
                }
            }
        }
        stage("Deploy") {
            steps([$class:"BapSshPromotionPublisherPlugin"]){
                script{
                    FAILED_STAGE=env.STAGE_NAME
                    sshPublisher(
                        publishers:[
                            sshPublisherDesc(
                                configName:"nginx",
                                verbose:true,
                                transfers:[
                                    sshTransfer(
                                        execCommand:"/home/ec2-user/deploy/deploy.sh"
                                    )
                                ]
                            )
                        ]
                    )
                }
            }
        }
    }
    // post { 
    //     success { 
    //         discordSend description: "์•Œ๋ฆผํ…Œ์ŠคํŠธ", 
    //             footer: "ํ…Œ์ŠคํŠธ ๋นŒ๋“œ๊ฐ€ ์„ฑ๊ณตํ–ˆ์Šต๋‹ˆ๋‹ค.", 
    //             link: env.BUILD_URL, result: currentBuild.currentResult, 
    //             title: "ํ…Œ์ŠคํŠธ ์  ํ‚จ์Šค job", 
    //             webhookURL: "https://discord.com/api/webhooks/1033587512351916064/P4w8KClDjvlW3q7DFoK9MgbsN0P6mS1LRXKOKQ7Rkj9FVoJP7oZQLS6WWLyHnsWYRtIF"
    //     }
    //     failure { 
    //         discordSend description: "${env.JOB_NAME} ์•Œ๋ฆผํ…Œ์ŠคํŠธ", 
    //             footer: "ํ…Œ์ŠคํŠธ ๋นŒ๋“œ๊ฐ€ ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.", 
    //             link: env.BUILD_URL, result: currentBuild.currentResult, 
    //             title: "ํ…Œ์ŠคํŠธ ์  ํ‚จ์Šค ${FAILED_STAGE}", 
    //             webhookURL: "https://discord.com/api/webhooks/1033587512351916064/P4w8KClDjvlW3q7DFoK9MgbsN0P6mS1LRXKOKQ7Rkj9FVoJP7oZQLS6WWLyHnsWYRtIF"
    //     }
    //     // always { 
    //     //     echo 'I will always say Hello again!'
    //     // }
    // }
}

ํŒŒ์ผ์— ์œ„ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด์ฃผ๊ณ  push

* ์ค‘๊ฐ„์— SonarQube stage๋Š” ๋ณธ์ธ๊บผ์— ๋งž๊ฒŒ ์ˆ˜์ •ํ›„ push ํ•ด์ฃผ๊ธฐ

 

 

 

Gitea Repository ์— Commit ๋œ๊ฒƒ ํ™•์ธ

 

 

Jenkins ๋กœ ๋Œ์•„๊ฐ€์„œ ๋‹ค์‹œ Scan + Log ํ•ด๋ณด๊ธฐ 

 

Jenkins-file Found ์™„๋ฃŒ โญ๏ธ

 

๐Ÿ”† Webhook ์„ค์ •

 

Gitea ์—์„œ ๋ณธ์ธ ๋ ˆํฌ์ง€ํ† ๋ฆฌ๋กœ ๋“ค์–ด๊ฐ„๋’ค

์šฐ์ธก์— ์„ค์ • โžก ์›นํ›… โžก webhook ์ถ”๊ฐ€ โžก Gitea ํด๋ฆญ

 

 

URL ์—๋Š” http://์  ํ‚จ์Šค์ฃผ์†Œ/multibranch-webhook-trigger/invoke?token=(Trigger token)

* (Trigger token) ์—๋Š” ์œ„์— ์„ค์ •ํ–ˆ๋˜ Scan by webhook ์˜ Trigger token ์ ์–ด์ฃผ๊ธฐ

 

Webhook ๊ฐฑ์‹ 

 

 

webhook ๊ฐฑ์‹  ๋ฐ‘

" ์ „๋‹ฌ ์‹œํ—˜ " ๋ฒ„ํŠผ์„ ํ†ตํ•ด test๋ฅผ ์ง„ํ–‰

 

๐Ÿ’ก ์˜ค๋ฅ˜๊ฐ€ ๋‚˜๋Š” ์ด์œ ๋Š”?

Gitea ์‚ฌ์„ค๋ง์„ ์ด์šฉ์ค‘์ธ ์ƒํƒœ๋ผ EC2์—์„œ ์ธ๋ฐ”์šด๋“œ๊ทœ์น™ ์—์„œ ํฌํŠธ ๋ฅผ Public์œผ๋กœ ์—ด์–ด์ค˜์•ผํ•ฉ๋‹ˆ๋‹ค.

 

์›นํ›… ์„ฑ๊ณต โญ๏ธ

 

๐Ÿ”† Docker์— SonarQube ์„ค์น˜ํ•˜๊ธฐ

 

SonarQube๋Š” SSH๊ฐ€ ์•„๋‹Œ ๋กœ์ปฌ์— ์„ค์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ํ„ฐ๋ฏธ๋„ ์ด์šฉ์‹œ SSH ํ„ฐ๋ฏธ๋„์ด ์•„๋‹Œ (mac ๊ธฐ์ค€) iTerm ์œผ๋กœ ์„ค์น˜ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

 

Docker Desktop ์„ค์น˜

 

 

Docker Hub ์ ‘์†ํ›„ ์™ผ์ชฝ ์ƒ๋‹จ ๊ฒ€์ƒ‰ ์ฐฝ์— " sonarqube " ๊ฒ€์ƒ‰

 

 

์†Œ๋‚˜ํ๋ธŒ ๊ณต์‹ ๊ณ„์ • ์ด๋ฏธ์ง€์™€ ๋ช…๋ น์–ด๊ฐ€ ๋‚˜์˜ด

 

+์ถ”๊ฐ€๋กœ

docker pull sonarqube:lts

โ€‹๋ผ๊ณ  ์ž…๋ ฅํ›„ ์„ค์น˜๋„์ค‘์— ์—๋Ÿฌ๊ฐ€ ๋‚ฌ๋‹ค๋ฉด (with M1)

docker pull --platform linux/amd64 sonarqube:ltsโ€‹

์˜ต์…˜์„ ์ค˜์„œ linux์„ ๋ช…์‹œํ•ด์•ผ ์ •์ƒ ๋‹ค์šด๋กœ๋“œ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

โ€‹

๋งŒ์ผ ์ด์ƒ์ด ๋” ์žˆ์„ ๊ฒฝ์šฐ dockerhub์— public์œผ๋กœ ์˜ฌ๋ ค์ง„ m1์šฉ ์†Œ๋‚˜ํ๋ธŒ ์ด๋ฏธ์ง€๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ์ด๊ฑด ๊ณต์‹์œผ๋กœ ์ œ๊ณต๋˜๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ, ์ž˜ ๋ณด๊ณ  ๋ฐ›์•„์•ผํ•ฉ๋‹ˆ๋‹ค.

 

โ€‹

m1์šฉ ์œผ๋กœ๋„ ์•ˆ๋˜์‹ ๋‹ค๋ฉด?

mwizner์œผ๋กœ ์˜ฌ๋ผ๊ฐ„ ์†Œ๋‚˜ํ๋ธŒ๋ฅผ ์•„๋ž˜ ์ถ”๊ฐ€ํ•œ ๋ช…๋ น์–ด๋กœ ์ถ”๊ฐ€ํ•ด์„œ ์‚ฌ์šฉํ•ด๋ณด์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.


docker run -d -p 80:80 --name sonarqube sonarqube:lts

 

docker run -d -p 9000:9000 mwizner/sonarqube:8.7.1-community

Docker desktop gui์—์„œ๋Š” ๋‚ด๊ฐ€ ๋ฐฉ๊ธˆ ๋งŒ๋“  ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ๋™์ž‘ํ•˜๋Š” log๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ณผ ์ˆ˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

๐Ÿ“

 

no matching manifest for linux/arm64/v8 in the manifest list entries

๋ผ๋Š” ์˜ค๋ฅ˜ ๋ฐœ์ƒ์‹œ

โŒจ๏ธ   docker pull --platform linux/amd64 sonarqube

 

 

latest ํƒœ๊ทธ ๊นŒ์ง€ ์™„๋ฃŒ 

๐Ÿ“

 

 

โŒจ๏ธ   docker images

* sonarqube ์ด๋ฏธ์ง€๊ฐ€ ๋ฐ›์•„์ง„๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Œ

 

 

โŒจ๏ธ docker run -d --name sonarqube -p 9000:9000 sonarqube

* ์†Œ๋‚˜ํ๋ธŒ ์ปจํ…Œ์ด๋„ˆ ์‹คํ–‰

 

๐Ÿ“ -d ์˜ต์…˜์„ ํ†ตํ•ด ๋ฐฑ๊ทธ๋ผ์šด๋“œ๋กœ  ์‹คํ–‰ํ•˜๊ณ 

-- name ์˜ต์…˜์œผ๋กœ  sonarqube ๋ผ๊ณ  ๋ช…๋ช…

-p ์˜ต์…˜์œผ๋กœ ํฌํŠธ๋ฅผ ์„ค์ • ๐Ÿ“

 

โŒจ๏ธ    docker ps 

* sonarqube ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์‹คํ–‰๋˜๊ณ ์žˆ๋Š”๊ฒƒ์„ ํ™•์ธ

 

 

๐Ÿ“

๐Ÿ“ ์  ํ‚จ์Šค์—์„œ ์†Œ๋‚˜ํ๋ธŒ๋ฅผ ๋นŒ๋“œํ•˜๊ฒŒ๋˜๋ฉด EC2 ๋ฉ”๋ชจ๋ฆฌ ์šฉ๋Ÿ‰์˜ ๋ถ€์กฑ์œผ๋กœ ๋นŒ๋“œ๊ฐ€ ๋ฉˆ์ถ”๊ฒŒ ๋ ์ˆ˜ ์žˆ์Œ

๊ทธ๋ž˜์„œ ๋ฏธ๋ฆฌ ์Šค์™‘๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์„ค์ •ํ•ด๋‘๋ฉด ์ด๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Œ 

 

SSH Docker ํ„ฐ๋ฏธ๋„์— ๋“ค์–ด๊ฐ€์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•ด์ฃผ๊ธฐ

 

โŒจ๏ธ   sudo dd if=/dev/zero of=/mnt/swapfile bs=1M count=2048

โŒจ๏ธ   sudo mkswap /mnt/swapfile

โŒจ๏ธ   sudo swapon /mnt/swapfile

 

๋งŒ์•ฝ sudo not command ์—๋Ÿฌ๊ฐ€ ๋‚˜์˜จ๋‹ค๋ฉด

โŒจ๏ธ   apt-get install sudo -y

๋ฅผ ๋จผ์ € ์‹คํ–‰ํ•˜๊ณ  ๋‹ค์‹œ ์ง„ํ–‰ํ•˜๊ธฐ

๐Ÿ“

 

 

Docker Desktop ์— Sonarqube ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์ƒ์„ฑ๋œ๊ฒƒ์„ ํ™•์ธ

 

 

๋นจ๊ฐ„๋ณ„ ํ‘œ์‹œ๋ถ€๋ถ„์— โ–ถ๏ธ ํด๋ฆญ ํ›„

* ์‚ฌ์ง„ ์ƒ์œผ๋ก  โ—ผ๏ธ ๋กœ ๋˜์–ด ์žˆ์ง€๋งŒ Run ์‹œ์ž‘ ํ•˜์ง€ ์•Š์œผ์‹  ๋ถ„๋“ค์€ โ–ถ๏ธ ๋กœ ๋œธ

 

์†Œ๋‚˜ํ๋ธŒ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๋ˆŒ๋Ÿฌ๋ณด๋ฉด

 

 

์„ค์น˜๊ฐ€ ์ง„ํ–‰ ๋˜๊ณ  ์žˆ๋Š”๊ฒƒ์„ ํ™•์ธ

* ์ค‘๊ฐ„์ค‘๊ฐ„ ์ž ๊น ๋ฉˆ์ท„๋‹ค๊ฐ€ ๊ณ„์† ์„ค์น˜๊ฐ€ ๋˜๊ณ  ์žˆ๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์œผ๋‹ˆ

๋”์ด์ƒ ์„ค์น˜๊ฐ€ ์ง„ํ–‰๋˜์ง€์•Š์„๋•Œ ์ฏค ๋ธŒ๋ผ์šฐ์ € ์ ‘์†ํ•˜๋Š”๊ฒƒ์„ ์ถ”์ฒœ

 

 

{ ๋ณธ์ธ ๊ณต์ธ IP }:9000 ํ˜น์€ localhost:9000

์œผ๋กœ ์ ‘์†

* mac ์—์„œ ๊ณต์ธIP ์ปค๋งจ๋“œ โŒจ๏ธ   curl ifconfig.me

+ ๊ณต์ธ IP๋„ ์ธ๋ฐ”์šด๋“œ ๊ทœ์น™์—์„œ ์„ค์ •ํ•ด์ฃผ์…”์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

๋กœ๋”ฉ์ด ์‹œ๊ฐ„์ด ์ข€ ๊ฑธ๋ฆฌ๋‹ˆ ๊ธฐ๋‹ค๋ ค์ฃผ์„ธ์š”

 

 

์„ค์น˜๊ฐ€ ๋๋‚˜๊ณ  ์‹คํ–‰์ด ๋œ๋‹ค๋ฉด admin / admin ์œผ๋กœ ๋กœ๊ทธ์ธ

 

 

๋กœ๊ทธ์ธ ํ•˜๊ณ ๋‚˜๋ฉด Password ๋ณ€๊ฒฝ์ฐฝ์ด ๋‚˜์˜ค๊ณ  Password ๋ณ€๊ฒฝํ•ด์ฃผ๊ธฐ

 

 

์„ค์น˜ ์™„๋ฃŒ โญ๏ธ

 

๐Ÿ”† Jenkins ์™€ SonarQube ์—ฐ๋™ํ•˜๊ธฐ

 

 

Jenkins ๊ด€๋ฆฌ์—์„œ ํ”Œ๋Ÿฌ๊ทธ์ธ ๊ด€๋ฆฌ๋กœ ๋“ค์–ด๊ฐ€์ฃผ์„ธ์š”.

 

 

SonarQube Scanner for Jenkins ์„ค์น˜

* SonarQube Scanner ๋ผ๊ณ  ๋‚˜์™€๋„ OK

 

 

๋‹ค์‹œ Jenkins ๊ด€๋ฆฌ์—์„œ Global Tool Configuration ํด๋ฆญ

 

 

๋‚ด๋ฆฌ๋‹ค๋ณด๋ฉด SonarQube Scanner ์—์„œ Add SonarQube Scanner ํด๋ฆญ

 

 

Name ์ง€์ •ํ•ด์ฃผ๊ณ  version ๋„ ์ตœ์‹  ๋ฒ„์ „์œผ๋กœ ์„ ํƒ โžก ์™ผ์ชฝ ํ•˜๋‹จ SAVE

 

๐Ÿ”† SonarQube ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ

* ๋‚ด ์†Œ๋‚˜ํ๋ธŒ ์‹คํ–‰ํ•œ ์„œ๋ฒ„ ์ ‘์†์ด ์™ธ๋ถ€์—์„œ ์ž˜ ๋˜๋Š”์ง€ ํ™•์ธ ํ•ด๋ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ธ๋ฐ”์šด๋“œ ์„ค์ •์„ ํ•ด์ค˜์•ผํ•  ์ˆ˜ ๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

์†Œ๋‚˜ํ๋ธŒ ์‹คํ–‰์‹œ์ผœ์ฃผ๊ณ , Gitea๊ฐ€ ์—†๊ธฐ์— Manually ๋กœ ์„ ํƒ

 

 

Name ๊ณผ Key ์ž‘์„ฑํ›„ Set Up ํด๋ฆญ

 

 

์—ฌ๊ธฐ๋„ Gitea ๊ฐ€ ์—†์–ด์„œ Other CI ํด๋ฆญ

 

 

Token name ์ง€์ •ํ›„ Generate

 

 

Token ์ƒ์„ฑ ์™„๋ฃŒ โžก Continue ํด๋ฆญ

 

 

Others โžก macOS ์„ ํƒํ›„ ๋‚˜์˜ค๋Š”๊ฒƒ ํ™•์ธ (ํ™•์ธ๋งŒ ํ•˜์…”๋„ ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋กœ ์„ค์น˜ ์•ˆํ•˜์…”๋„ ๋˜์š”.)

 

 

Jenkins ๋กœ ๋Œ์•„์˜ค์…”์„œ Jenkins ๊ด€๋ฆฌ โžก Security ์— Manage Credentials ํด๋ฆญ

 

 

Stores scoped to Jenkins ์—์„œ (global) โžก Add credentials ํด๋ฆญ

 

 

๐Ÿ“ Kind = Secret text

๐Ÿ“ Scope = Global

๐Ÿ“ Secret = ์†Œ๋‚˜ํ๋ธŒ์—์„œ ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ์‹œ ๋งŒ๋“  ํ† ํฐ

๐Ÿ“ ID ์™€ Description ์€ ์ž„์˜๋กœ ์ง€์ •

 

Create ํด๋ฆญ

 

 

Jenkins ๊ด€๋ฆฌ โžก ์‹œ์Šคํ…œ ์„ค์ • ํด๋ฆญ

 

 

๋‚ด๋ฆฌ๋‹ค๋ณด๋ฉด SonarQube Servers ๊ฐ€ ๋‚˜์˜ค๋ฉด Environment variables ์ฒดํฌโœ… ํ›„ Add SonarQube ํด๋ฆญ

 

 

๐Ÿ“ Name = ์ž„์˜์ง€์ •

๐Ÿ“ Server URL = ๋ณธ์ธ ์†Œ๋‚˜ํ๋ธŒ URL

* 9000 ํฌํŠธ ๋’ค์— </> ๊ฐ€ ๋ถ™์œผ๋ฉด ์•ˆ๋จ

๐Ÿ“ Server authentication token = Credentials ์—์„œ ์ƒ์„ฑํ•œ ํ† ํฐ (์ด๋ฏธ ๋งŒ๋“ค์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์„ ํƒํ•˜๋ฉด ๋จ)

 

์™ผ์ชฝ ํ•˜๋‹จ SAVE ํด๋ฆญ

 

 

VSCODE ์—์„œ Jenkinsfile ๊ณผ ๊ฐ™์€ ํด๋” ๋‚ด์— sonar-project.properties ํŒŒ์ผ ์ƒ์„ฑ

 

# must be unique in a given SonarQube instance
sonar.projectKey=my:project ๐Ÿ“Œ ๋ณธ์ธ ์†Œ๋‚˜ํ๋ธŒ ํ”„๋กœ์ ํŠธ ์ด๋ฆ„ ์ ๊ธฐ ๐Ÿ“Œ

# --- optional properties ---

# defaults to project key
#sonar.projectName=My project
# defaults to 'not provided'
#sonar.projectVersion=1.0
 
# Path is relative to the sonar-project.properties file. Defaults to .
#sonar.sources=.
 
# Encoding of the source code. Default is default system encoding
#sonar.sourceEncoding=UTF-8

 

์ž‘์„ฑํ›„ Gitea์— push ํ•ด๋†“๊ธฐ

 

 

Jenkins Plugin ๊ด€๋ฆฌ์—์„œ NodeJS ์„ค์น˜ ์•ˆํ•˜์…จ๋‹ค๋ฉด ์„ค์น˜ํ•ด์ค๋‹ˆ๋‹ค. ( VSCODE npm build์‹œ ํ•„์š”ํ•จ )

 

 

Jenkins ๊ด€๋ฆฌ โžก Global Tool Configuration ์— ๋งจ๋ฐ‘ NodeJS ์„ค์ • ํ•ด์ฃผ๊ธฐ

 

 

Build ์„ฑ๊ณต โญ๏ธ

 

๐Ÿ”† Dockerfile ์ถ”๊ฐ€ํ•˜๊ธฐ

 

Jenkins ์—์„œ ๋„์ปค ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋„์ปค์™€ ๋„์ปค ํŒŒ์ดํ”„๋ผ์ธ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์„ค์น˜ ํ•ด์ฃผ์…”์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํ”Œ๋Ÿฌ๊ทธ์ธ ์—†์ด ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฉด ํŒŒ์ดํ”„๋ผ์ธ ์Šคํฌ๋ฆฝํŠธ๋‚ด์—์„œ ๋„์ปค ๊ด€๋ จ ์„ค์ •์ด ์ธ์‹๋˜์ง€ ์•Š์•„ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

 

โ€‹

 

#๊ธฐ์กด node 16๋ฒ„์ „์˜ ์ด๋ฏธ์ง€๋กœ๋ถ€ํ„ฐ ์ƒˆ๋กœ์šด ์ด๋ฏธ์ง€ ์ƒ์„ฑํ•จ์„ ์ง€์ •
FROM node:16-alpine

#dockerfile์„ ์ƒ์„ฑ/๊ด€๋ฆฌํ•˜๋Š”์‚ฌ๋žŒ
MAINTAINER ๐Ÿ“Œ๋ณธ์ธ ์ด๋ฆ„ <๋ณธ์ธ ์ด๋ฉ”์ผ>๐Ÿ“Œ

# ์ด๋ฏธ์ง€๋‚ด์— /app ๋””๋ ‰ํ† ๋ฆฌ ์ƒ์„ฑ
# ์ปจํ…Œ์ด๋„ˆ ์•ˆ์—๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ root๊ถŒํ•œ์œผ๋กœ ๋งŒ๋“ค์–ด์ง
# ๋งŒ์ผ, ์šด์˜๊ณ„์ •์„ ๋ณ„๋„๋กœ ๋งŒ๋“ค์–ด ๊ด€๋ฆฌํ•œ๋‹ค๋ฉด ํด๋” ์†Œ์œ ์ž ํ˜น์€ ๊ถŒํ•œ์— ๋Œ€ํ•œ ์„ค์ •๋„ ํ•ด์•ผ๋จ.
RUN mkdir -p /app

# ์ด๋ฏธ์ง€๋‚ด์˜ /app ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ WORKDIR ๋กœ ์„ค์ •
WORKDIR /app

# ํ˜„์žฌ Dockerfile ์žˆ๋Š” ๊ฒฝ๋กœ์˜ ๋ชจ๋“  ํŒŒ์ผ์„ /app ์— ๋ณต์‚ฌ
COPY ./ /app

# ์‹คํ–‰ํ•˜๋Š” ์ปจํ…Œ์ด๋„ˆ ์•ˆ์—์„œ work dir์— ์žˆ๋Š” package.json์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ชจ๋“ˆ ์„ค์น˜
RUN npm install

#ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์„ค์ • : ์šด์˜ or ๊ฐœ๋ฐœ
ENV NODE_ENV production

# ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ํ•˜๊ฒŒ๋  ์‹คํ–‰ ๋ช…๋ น ์„ ์–ธ. 
# RUN์€ ์ด๋ฏธ์ง€ ๋นŒ๋“œ ์ค‘ ์‹คํ–‰. ENTRYPOINT ์™€ CMD๋Š” ์ด๋ฏธ์ง€ ๋นŒ๋“œ ํ›„ ์ปจํ…Œ์ด๋„ˆ ์‹คํ–‰์‹œ์ ์— ์‚ดํ–‰
# ENTRYPOINT ์™€ CMD ์ฐจ์ด์ ์€, 
# ENTRYPOINT๋Š” ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์ˆ˜ํ–‰๋  ๋•Œ ๋ฐ˜๋“œ์‹œ ์ง€์ •ํ•œ ๋ช…๋ น์„ ์ˆ˜ํ–‰๋˜๋„๋ก ์ง€์ •
# CMD๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•˜๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ์— ๋”ฐ๋ผ ๋ณ€๋™๊ฐ€๋Šฅ
# ์ถ”ํ›„ ๋‘๊ฐœ์˜ ๋ช…๋ น์–ด ํ…Œ์ŠคํŠธ ํ•„์š”
CMD ["npm","start"]

 

Dockerfile ๋„ ๊ฐ™์ด ๋งŒ๋“ค์–ด์„œ ์œ„ ์ฝ”๋“œ๋กœ push ํ•ด์ฃผ๊ธฐ

* ์ฝ”๋“œ ์ค‘๊ฐ„์— ๐Ÿ“Œ๋ถ€๋ถ„์€ ๋ณธ์ธ ์ด๋ฆ„ <๋ณธ์ธ ์ด๋ฉ”์ผ์ฃผ์†Œ> ์ ์–ด์ฃผ๊ธฐ

 

 

๐Ÿ”† Jenkins ์—์„œ ์›๊ฒฉ ๋ฐฐํฌ ํ•˜๊ธฐ

 

mkdir /home/ec2-user/deploy

 

SSH docker ํ„ฐ๋ฏธ๋„์—์„œ deploy ํด๋”๋ฅผ ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค.

 

์  ํ‚จ์Šค์—์„œ npm build๋ฅผ ์ง„ํ–‰์‹œ,

์ปดํŒŒ์ผ์ด ์™„๋ฃŒ๋œ ํŒŒ์ผ๋“ค์„ ์‹ค์ œ ์„œ๋น„์Šค ํ•  ์ˆ˜ ์žˆ๋„๋ก ์šด์˜๋ 

์„œ๋ฒ„์— ์ž๋™์œผ๋กœ ์ด๋™ > ์‹คํ–‰๋˜๊ณ  ์žˆ๋Š” ์„œ๋ฒ„์— ์ˆ˜์ •ํ•œ ํŒŒ์ผ ๋ฐ˜์˜ > ์‚ฌ์ดํŠธ์—์„œ ๋ณด์—ฌ์•ผํ•ฉ๋‹ˆ๋‹ค.

 

 

Jenkins Plugin ๊ด€๋ฆฌ์—์„œ Publish over SSH ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์„ค์น˜ ํ•ด์ค๋‹ˆ๋‹ค.

 

 

๊ทธ๋Ÿฌ๋ฉด Jenkins ๊ด€๋ฆฌ์˜ ์‹œ์Šคํ…œ์„ค์ • ์ œ์ผ ํ•˜๋‹จ์— SSH Server ํ•ญ๋ชฉ์ด ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค.

 

 

SSH ์— ๋งŒ๋“ค์–ด๋‘” Nginx ์„œ๋ฒ„ ์ •๋ณด ์ž…๋ ฅํ•ด์ฃผ์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

๐Ÿ“ Name : nginx

๐Ÿ“ Hostname: ์„œ๋ฒ„ ์ฃผ์†Œ(ip)

๐Ÿ“ Username: ec2-user

๐Ÿ“ Remote Directory : /home/ec2-user/deploy

 

 

ํ•˜๋‹จ์— Use passwoard authentication, or ....์˜ต์…˜์„ ์ฒดํฌโœ… ํ•˜๊ณ 

Nginx ์„œ๋ฒ„ ๋งŒ๋“ค๋•Œ ์‚ฌ์šฉํ•œ AWS key ๋ถ™์—ฌ๋„ฃ๊ธฐ ํ•ด์ค๋‹ˆ๋‹ค.

* SSH ์—์„œ Nginx ์„œ๋ฒ„ ์ •๋ณด ์ˆ˜์ •๋“ค์–ด๊ฐ€์‹œ๋ฉด,

key ์„ค์ •ํ•ด์ฃผ๋Š”๊ณณ์—์„œ +new ํด๋ฆญํ›„ AWS ์—์„œ ๋งŒ๋“  ํ‚ค ํŒŒ์ผ import ํ•ด์ฃผ์‹œ๊ณ 

private key ๋ž€์— ๋‚˜์˜ค๋Š” key ๋ณต๋ถ™ ํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

๐Ÿ”† Docker Compose  ์™€ Nginx ์„ค์น˜

 

 

Install the Compose plugin

 

docs.docker.com

 

docker compose :

๋„์ปค ์ด๋ฏธ์ง€๋กœ ๋งŒ๋“ค์–ด์ง„ ์ปจํ…Œ์ด๋„ˆ๋“ค์„ ๋งŒ๋“ค๊ณ  ์‹คํ–‰ํ• ๋•Œ

์šฐ๋ฆฌ๋Š” ํฌํŠธ๋ผ๋˜์ง€ ์—ฌ๋Ÿฌ ์˜ต์…˜๋“ค์„ ๊ธฐ์–ตํ•˜๊ณ  ์žˆ์–ด์•ผํ–ˆ๊ณ  ๋งŒ์ผ ํ•˜๋‚˜๊ฐ€ ์•„๋‹ˆ๋ผ ์—ฌ๋Ÿฌ ์ปจํ…Œ์ด๋„ˆ๋“ค์„ ๊ด€๋ฆฌ๋ฅผ ํ•ด์•ผ๋œ๋‹ค๊ณ  ํ•˜๋ฉด

์—ฌ๊ฐ„ ๋ถˆํŽธํ•œ์ผ์ด ์•„๋‹ ์ˆ˜ ์—†๋‹ค.

ํ•˜๋‚˜์˜ ์„ค์ •ํŒŒ์ผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก, ์กฐ๊ธˆ ๋” ์‚ฌ์šฉ์ž์—๊ฒŒ ํŽธ๋ฆฌํ•˜๋„๋ก ์ œ๊ณตํ•˜๋Š”๊ฒƒ์ด

docker์˜ ๊ธฐ๋Šฅ ์ค‘ ํ•˜๋‚˜์ธ docker compose ์ด๋‹ค.

 

 

$ DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker}
$ mkdir -p $DOCKER_CONFIG/cli-plugins
$ curl -SL https://github.com/docker/compose/releases/download/v2.12.0/docker-compose-linux-x86_64 -o $DOCKER_CONFIG/cli-plugins/docker-compose

 

SSH docker ์„œ๋ฒ„์— 

โŒจ๏ธ   DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker}

โŒจ๏ธ   mkdir -p $DOCKER_CONFIG/cli-plugins

โŒจ๏ธ   curl -SL https://github.com/docker/compose/releases/download/v2.11.2/docker-compose-linux-x86_64 -o $DOCKER_CONFIG/cli-plugins/docker-compose

 

 chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose

 

์‹คํ–‰ ๊ถŒํ•œ ๋ถ€์—ฌ๋ฅผ ํ•ด์ค๋‹ˆ๋‹ค.

 

docker compose version

 

๋„์ปค ์ปดํฌ์ฆˆ ๋ฒ„์ „ ํ™•์ธ

โŒจ๏ธ   docker compose version

 

๐Ÿ”† Docker ๋กœ Nginx ์„ค์น˜

 

Nginx :

๋™์‹œ์ ‘์† ์ฒ˜๋ฆฌ์— ํŠนํ™”๋œ ์›น ์„œ๋ฒ„ ํ”„๋กœ๊ทธ๋žจ์ด๋‹ค.

apache๋ณด๋‹ค ๋™์ž‘์ด ๋‹จ์ˆœํ•˜๊ณ  ์ „๋‹ฌ์ž ์—ญํ• ๋งŒ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋™์‹œ ์ ‘์†์ฒ˜๋ฆฌ์— ํŠนํ™”๋˜์–ด์žˆ๋‹ค.

 

๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ :

ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ์„ ๊ฐ€๋กœ์ฑ„์„œ ์ค‘๊ฐ„์— ์›น์„œ๋ฒ„์— ๋ณด๋‚ด๊ณ  ์‘๋‹ต์„ ๋ฐ›์•„์„œ ๋‹ค์‹œ ํด๋ผ์ด์–ธํŠธ์— ์ „๋‹ฌํ•œ๋‹ค.

์„ค์ •์— ๋”ฐ๋ผ์„œ ๋‹ค์ค‘ ์›น์„œ๋ฒ„์— ์—ฐ๊ฒฐํ•ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์„œ ๊ณผ๋ถ€ํ•˜๋ฅผ ๋ง‰์„ ์ˆ˜ ์žˆ๋‹ค.

๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ ์„œ๋ฒ„๋Š” ๋กœ๋“œ๋ฐธ๋Ÿฐ์‹ฑ (๋ถ€ํ•˜๋ฅผ ๋ถ„์‚ฐ=ํŠธ๋ž˜ํ”ฝ๊ด€๋ฆฌ)์— ์‚ฌ์šฉ๋œ๋‹ค

 

 

docker pull nginx

 

SSH docker ์— Nginx ์ด๋ฏธ์ง€ ๋‹ค์šด๋ฐ›๊ธฐ

 

docker run -d -p 80:80 --name nginx nginx

 

์ปจํ…Œ์ด๋„ˆ ์‹คํ–‰ 

 

โŒจ๏ธ   docker ps 

๋กœ ์ด๋ฏธ์ง€ ์‹คํ–‰ ํ™•์ธ

 

 

AWS Nginx ์ธ์Šคํ„ด์Šค์— ํผ๋ธ”๋ฆญIPv4 ๋กœ 

์›น๋ธŒ๋ผ์šฐ์ €์— ์ ‘์†ํ•˜๋ฉด 

Welcome to nginx! ํŽ˜์ด์ง€๊ฐ€ ๋‚˜์˜จ๋‹ค โญ๏ธ

* AWS ์„œ๋ฒ„ ์ธ๋ฐ”์šด๋“œ ๊ทœ์น™์— 80ํฌํŠธ ์ถ”๊ฐ€ํ•ด์ค˜์•ผํ•จ

โ€‹

 

 

728x90