Agile&DevOps/실습 with Jenkins

react/vue.js의 CI/CD 속도 높이기

Happy@Cloud 2023. 12. 20. 09:24

react나 vue.js를 Jenkins 파이프라인으로 CI/CD할 때 아래 예제와 같이 library를 install할 때 매우 시간이 걸립니다. 

이를 NFS(Network file server)의 volume을 이용하여 개선하는 방법입니다. 

 

예제는 아래 git repository의 deployment디렉토리 하위에 있는 Dockerfile-cicid와 Jenkinsfile을 참조 하십시오.

https://github.com/happykubepia/react-weather-app.git

아래와 같은 순서로 작업 하시면 됩니다. 

package.json의 build명령 수정

package.json파일의 "scripts"."build"의 명령 앞에 'CI= '을 추가하셔야 합니다. 

이걸 안 하면 Jenkins pipeline에서 'yarn build'나, 'npm run build' 시 compile error가 발생합니다. 

react는 'CI= react-scripts build'로 수정하시면 됩니다. 

vue.js는 'CI= vite build'로 수정하시면 됩니다. 

 

Jenskindfile 수정

Jenkins agent Pod안에 node.js 컨테이너를 추가합니다. 

podTemplate(
	label: label, 
	containers: [
		containerTemplate(name: "node", image: "node:alpine", ttyEnabled: true, command: "cat"),
		...
	]

 

NFS서버의 특정 디렉토리를 npm과 yarn의 캐싱 디렉토리로 마운트 합니다. 

NFS서버의 IP와 볼륨 디렉토리는 자신에 맞게 수정해야 합니다. 

podTemplate(
	label: label, 
    ...
	//volume mount
	volumes: [
		nfsVolume( mountPath: '/root/.npm', serverAddress: '10.193.24.247', serverPath: '/users/data/jenkins/.npm', readOnly: false ),
		nfsVolume( mountPath: '/root/.yarn', serverAddress: '10.193.24.247', serverPath: '/users/data/jenkins/.yarn', readOnly: false )
    ]
	
)

기존에 Dockerfile내에서 하던 Script build를 이제 Jenkins pipeline에서 하도록 Stage를 추가 합니다. 

'yarn install'하면서 cache 디렉토리를 지정 합니다.  

yarn install 시 특정 디렉토리 밑에 소스가 있는 경우 yarn build --module_folder {디렉토리명}을 사용 하십시오.

npm install이나 npm run build 시 특정 디렉토리 밑에 소스가 있는 경우는 --prefix파라미터를 사용하시면 됩니다. 

특정 디렉토리 밑에 있지 않고 최상위 디렉토리에 소스가 있다면 지정 않하셔도 됩니다. 

			stage("Build React Scripts") {
				container("node") {
					sh "yarn install --cache-folder /root/.yarn"
					sh "npm install"
					sh "npm run build"
				}
			}

* Typescript로 개발하는 경우 아래 명령도 추가 하셔야 build가 제대로 됩니다.

sh "npm i --save-dev @types/styled-components"

 

Container image를 Build할 때 사용하는 Dockerfile을 새로 만든 'Dockerfile-cicd'로 변경 합니다. 

이 파일은 바로 아래에서 설명합니다. 

			stage("Build Container image") {
				container("podman") {
					withCredentials([usernamePassword(
						credentialsId: "${credentialRegistry}",
						usernameVariable: 'USER',
						passwordVariable: 'PASSWORD'
						)]) {
						    sh 'echo user "$USER" pasword "$PASSWORD"'
						    sh "podman login ${registry} --username ${USER} --password ${PASSWORD}"
							sh "podman build -f ./deployment/Dockerfile-cicd -t ${registry}/${organization}/${repository}:${tag} ."
							sh "sleep 2"
							sh "podman push ${registry}/${organization}/${repository}:${tag}"
							sh "podman tag ${registry}/${organization}/${repository}:${tag} ${registry}/${organization}/${repository}:latest"
							sh "podman push ${registry}/${organization}/${repository}:latest"
					}
				}
			}

 

 

Dockerfile-cicd 생성

Jenkins 파이프라인에서 Script build를 하기 때문에 Dockerfile에서는 빌드된 script를 container image안으로 복사하는 작업만 해주면 됩니다. 

아래와 같이 작성하시면 됩니다. 

FROM nginx:latest

COPY ./build /usr/share/nginx/html

## Copy web configuration 
COPY ./deployment/default.conf.template /etc/nginx/conf.d/default.conf
#
## 80포트 오픈하고 nginx 실행
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

 

 

참고) Jenkins pipeline을 실행하고 NFS volueme(위 예에서는 /users/data/jenkins)을 보면 아래 예와 같이 디렉토리가 생깁니다. 

Jenkins agent pod의 volume과 연결되었기 때문입니다. 

drwxrwxrwx.  4 kbdemobastion kbdemobastion 4096 12월 19 22:56 .npm
drwxrwxrwx.  3 kbdemobastion kbdemobastion 4096 12월 19 23:05 .yarn