# 운영툴 서버 설정 - 운영툴 주소 - 10.20.20.12 - 운영툴 구성을 위한 필요 프로그램 설치 - Docker Desktop Installer - Git-2.43.0-64-bit - jdk-17.0.10_windows-x64_bin - node-v20.11.0-x64 - python-3.12.1-amd64 - jenkins.msi * Docker MariaDB 구성 * 소스코트 내 \\Server\docker\admintool 에 있는 docker-compose 실행 * .env 파일에 root 계정의 패스워드 설정 * db\initdb.d 내에 최초 설치시 실행될 스크립트 구성 * 스키마 추가, 변경 경우 여기에 같이 추가해주는것이 좋음 - 젠킨스 구성 - 계정명 : admintool - 암호 : caliverse!1 - 주소 : http://10.20.20.23:8090 * 젠킨스 Git Credential 구성 * enkins 관리 → Credentials → (global)도메인 선택 → Add credential 선택 * kind → Username with password * Scope → Global * Username → jenkins_user * Password → jen3596!@ - Username, Password는 git 계정을 의미 * ID → admintool_git (표시 이름) - 젠킨스 플러그인 관련 설정 - 플러그인 설치 - - 기본적인 플러그인은 최초 설치시 설정 - NodeJs Plugin - Docker Pipeline - Docker - Gradle - Pipeline - Publish Over SSH - Subversion Plug-in - Tools 설정 - JDK installations 설정 - Name : jdk - JAVA_HOME : C:\Program Files\Java\jdk-17 - Gradle installations 설정 - name : gradle - version : 7.6.4 - NodeJS installation - name : nodejs - version : 21.6.2 - Frontend Stage 배포 작업 구성(24-08-23 기준) ```d pipeline { agent any environment { DOCKER_IMAGE = "caliverse/admintool-front" DOCKER_TAG = "1.0.0" // 신규 버전 DOCKER_TAG_PRE = "1.0.0" // 이전 버전 FILE_NAME = 'admintool_front.tar' DOCKER_NAME = 'admintool-front' DOCKER_PORT = '8080' } stages { stage('Docker Build') { steps { sh 'docker rmi $DOCKER_IMAGE:$DOCKER_TAG_PRE || true' //이전 이미지 삭제 sh 'docker build -t $DOCKER_IMAGE:$DOCKER_TAG .' //새 이미지 생성 echo 'Docker Image 생성' sh 'docker save -o $FILE_NAME $DOCKER_IMAGE:$DOCKER_TAG' //이미지 .tar 로 생성 echo "Docker Image > .tar 파일로 생성" } } stage('Transfer Docker Image') { steps { // aws .tar transfer sshPublisher( publishers: [ sshPublisherDesc( configName: 'stage-frontend', transfers: [ sshTransfer( sourceFiles: "${FILE_NAME}", remoteDirectory: '', execCommand: """ echo ".tar 전송 완료 """, execTimeout: 120000 ) ], usePromotionTimestamp: false, verbose: true ) ] ) } } stage('Deploy to Remote'){ steps{ // aws command sshPublisher( publishers: [ sshPublisherDesc( configName: 'stage-frontend', transfers: [ sshTransfer( execCommand: """ docker stop ${DOCKER_NAME} || true && docker rm ${DOCKER_NAME} || true && docker rmi ${DOCKER_IMAGE}:${DOCKER_TAG_PRE} || true && docker load -i ${FILE_NAME} && docker run -d \ -p ${DOCKER_PORT}:${DOCKER_PORT} \ --name ${DOCKER_NAME} \ -v ./admintool/log:/var/log/nginx \ -e TZ=\${TZ:-Asia/Seoul} \ ${DOCKER_IMAGE}:${DOCKER_TAG} && rm ${FILE_NAME} echo 'Docker Container Create Complete' """, execTimeout: 120000 ) ], usePromotionTimestamp: false, verbose: true ) ] ) } } } } ``` - Frontend Reverse Proxy(nginx.conf) ``` server { listen 8080; listen [::]:8080; server_name localhost; location / { root /usr/share/nginx/admintool; index index.html index.htm; try_files $uri $uri/ /index.html; } # api reverse proxy location /api/ { proxy_pass http://172.30.148.164:23450; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/admintool; } } ``` - Frontend Dockerfile ``` FROM node:20.11.0 as build WORKDIR /app COPY package*.json ./ RUN npm install COPY . . RUN npm run build FROM nginx:alpine COPY nginx.conf /etc/nginx/conf.d/default.conf COPY --from=build /app/build /usr/share/nginx/admintool # port 8080 EXPOSE 8080 CMD ["nginx", "-g", "daemon off;"] ``` - Backend Stage 배포 작업 구성(24-08-23 기준) ``` pipeline { agent any environment { DOCKER_IMAGE = 'caliverse/admintool-back' DOCKER_TAG = '1.0.0' DOCKER_TAG_PRE = '1.0.0' FILE_NAME = 'admintool_back.tar' DOCKER_NAME = 'admintool-back' DOCKER_PORT = '23450' } stages { stage('Gradle Build') { steps { script { sh 'chmod +x gradlew' //gradle 권한 설정 sh './gradlew clean build -x test' //빌드 test는 하지않는다 } } } stage('Docker Image Build') { steps { script { sh 'docker rmi $DOCKER_IMAGE:$DOCKER_TAG_PRE || true' //이전 이미지 삭제 sh 'docker build -t $DOCKER_IMAGE:$DOCKER_TAG .' echo 'Docker Image Create' sh 'docker save -o $FILE_NAME $DOCKER_IMAGE:$DOCKER_TAG' echo 'Docker Image > .tar File Create' } } } stage('SSH Tunneling') { steps { script { sh 'ssh -f -N -L 127.30.148.164:2211:172.30.148.164:2211 ubuntu@52.32.111.3 -p 2211 -i /home/admintool/USWest2-KeyPair.pem -o StrictHostKeyChecking=no &' } } } stage('Transfer Docker Image') { steps { // aws .tar transfer sshPublisher( publishers: [ sshPublisherDesc( configName: 'stage-backend', transfers: [ sshTransfer( sourceFiles: "${FILE_NAME}", remoteDirectory: '', execCommand: """ echo '.tar Transfer Complete' """, execTimeout: 120000 ) ], usePromotionTimestamp: false, verbose: true ) ] ) } } stage('Deploy to Remote'){ steps{ // aws command sshPublisher( publishers: [ sshPublisherDesc( configName: 'stage-backend', transfers: [ sshTransfer( execCommand: """ docker load -i ${FILE_NAME} && docker stop ${DOCKER_NAME} || true && docker rm ${DOCKER_NAME} || true && docker rmi ${DOCKER_IMAGE}:${DOCKER_TAG_PRE} || true && docker run -d \ -p ${DOCKER_PORT}:${DOCKER_PORT} \ --name ${DOCKER_NAME} \ -e TZ=\${TZ:-Asia/Seoul} \ -v ./admintool/log:/logs \ ${DOCKER_IMAGE}:${DOCKER_TAG} && rm ${FILE_NAME} """, execTimeout: 120000 ) ], usePromotionTimestamp: false, verbose: true ) ] ) } } } } ``` - Backend Dockerfile ``` FROM openjdk:17 ARG JAR_FILE=build/libs/CaliverseAdminAPI.jar COPY ${JAR_FILE} admintool.jar ENTRYPOINT ["java","-jar","/admintool.jar"] ``` * Frontend 작업 구성(24-02-21 기준) - 사용안함 pipeline { agent any environment { CI = 'false' } stages { stage('Pull Code') { steps { git branch: 'dev', credentialsId: 'admintool_git', url: 'http://44.227.18.113/caliverseadmin/backofficefront.git' } } stage('Move Files') { steps { bat 'xcopy /E /Y ..\\Dev_FrontEnd_Build\\* D:\\AdminTool\\FrontEnd\\' } } stage('Build') { steps { dir('D:\\AdminTool\\FrontEnd\\') { bat 'npm install' bat 'npm install pm2' bat 'npm run build' } } } stage('Stop') { steps { dir('D:\\AdminTool\\FrontEnd\\') { script { try { bat 'pm2 delete AdminTool' } catch (error) {} } } } } stage('Create ecosystem.config.js if not exists') { steps { script { def configFile = 'D:\\AdminTool\\FrontEnd\\ecosystem.config.js' def configContent = '''module.exports = { apps: [{ name: 'AdminTool', script: './node_modules/react-scripts/scripts/start.js', instances: 2, exec_mode: 'cluster' }] }''' if (!fileExists(configFile)) { writeFile file: configFile, text: configContent echo "Created ecosystem.config.js" } else { echo "ecosystem.config.js already exists" } } } } stage('Start') { steps { dir('D:\\AdminTool\\FrontEnd\\') { bat ''' set BUILD_ID=dontKillMe node_modules\\.bin\\pm2 start --name AdminTool ''' } } } } } * Backend 작업 구성(24-02-21 기준) - 사용안함 pipeline { agent any environment { CI = 'false' } stages { stage('Pull Code') { steps { git branch: 'dev', credentialsId: 'admintool_git', url: 'http://44.227.18.113/caliverseadmin/backofficeapi.git' } } stage('Move Files') { steps { bat 'xcopy /E /Y ..\\Dev_BackEnd_Build\\* D:\\AdminTool\\BackEnd\\' } } stage('Stop') { steps { script { bat ''' for /f "tokens=5" %%a in ('netstat -ano ^| findstr :9099') do ( set pid=%%a ) if not "%pid%"=="" ( taskkill /F /PID %pid% echo Process Ended. PID: %pid% ) else ( echo No PID!! ) ''' } } } stage('Build') { steps { dir('D:\\AdminTool\\BackEnd\\') { script { def buildResult = bat returnStatus: true, script: 'gradlew bootJar' if (buildResult != 0) { error 'Failed to build the project' } } } } } stage('Run') { steps { dir('D:\\AdminTool\\BackEnd\\build\\libs\\') { script { bat ''' set JENKINS_NODE_COOKIE=dontKillMe start /b cmd /c java -jar -Dspring.profiles.active=dev .\\CaliverseAdminAPI.jar & ''' } } } } } }