SpringBoot 백엔드 와 Next.js 프론트를 Jenkins를 이용해서 gitlab에 업로드 될때마다 자동빌드 및 배포를 할 수 있도록 프로그래밍한 내용을 담고 있다.
Nginx로 리버스 프록시와 페이지 리다이렉션을 진행했고, https 세팅까지 진행했다.
삽질끝에 얻은 정보들을 이 배포 시리즈에 최대한 담아봤는데, 많은사람들에게 도움이 되면 좋겠다.😆😍
프로젝트 내에 Dockerfile
을 생성하자
Spring 공식문서에서 Dockerfile 문서를 가져왔다.
Java11
에 Gradle
을 사용하였기때문에, jar
파일이 생성되는 경로가 build/libs/
아래이므로, COPY
커맨드를 아래와같이 써주었다.Maven
을 사용하는 경우 target/
아래에 jar
파일이 생성되므로, 그렇게 작성해주면 된다.EXPOSE
로 8081 포트를 지정해주었다.Dockerfile은 컨테이너에 설치해야하는 패키지
, 소스코드
, 명령어
, 환경변수 설정
등을 기록한 하나의 파일로 애플리케이션 빌드 및 배포를 자동화하기위해 존재하는 것이다.
FROM adoptopenjdk/openjdk11:alpine
COPY build/libs/*.jar app.jar
EXPOSE 8081
ENTRYPOINT ["java","-jar","/app.jar"]
NextJS
에 yarn
을 사용하였다.yarn
명령어를 돌리기 위해, package.json
과 yarn.lock
을 COPY
명령어를 통해 나의 디렉토리에 가져온다.yarn
명령어는 프로젝트를 돌리기위해 필요한 패키지들을 다운받는 명령어다.COPY . .
dockerfile이 있는 장소에서의 모든것을 copy하는 명령어인데, yarn build
를 하기위하여 뭐가 필요할지모르니 그냥 다 받아왔다.CMD
는 ENTRYPOINT
와 같은 명령어이지만, 컨테이너 시작시 실행 명령에 대한 Default 지정 여부가 가장 큰 차이다.CMD
로 전달한 인자값은 명령어를 실행시키는 사용자에 의해 추가 및 변경이 가능하고, ENTRYPOINT
로 전달한 인자값은 사용자에의해 변경이나 추가가 불가능하다.FROM node:alpine
COPY package*.json ./
COPY yarn.lock ./
RUN yarn
COPY . .
RUN yarn build
EXPOSE 3000
CMD ["yarn","start"]
Dockerfile
와 같은 위치에 Jenkinsfile
도 생성해주자.
pipeline
을 최상위 레벨에 정의agent
에 대한 자세한 정의는 공식문서를 참조하면 좋다. → 공식문서any
를 사용하면, 에이전트로 사용할 수 있는 어떤것이든 사용하겠다 라는 말이다. 보통 많이 쓰는 것 같다.stages
는 는 stage
들을 돌릴 블록이라고 생각하면 된다. → 공식문서각각의 동작들을 통해 프로젝트 build와 run이 가능하고, 이 동작들에서 오류가 나면, 어떤 곳에서 에러가 나는지 Jenkins status를 통해 쉽게 파악이 가능하다.
stage
에 들어가는 이름은 자유롭게 정하면 된다. 나중에 status
에서 어떤 부분에서 에러가 났는지 확인하기 편하게 짓도록 하자.
도커 컨테이너 이름을 dockerhi
라고 치자.
Build
stage에서는 SpringBoot 프로젝트를 build 해준다.docker build
를 통해서 build가 완료된 실행파일로 dockerhi
라는 이름의 도커 컨테이너
를 생성해준다.docker run
을 통해 이 컨테이너를 run
시켜준다.docker run
쉘 명령어중-d
: Detached 모드로, 데몬 모드라고도 불리며, 백그라운드로 컨테이너를 실행시킴--name
: 컨테이너 이름을 설정함-p
: 포트번호를 지정하는데 외부포트:내부포트-net
: MySQL
을 도커위에서 돌리는데, 같은 네트워크내에서 돌아가도록 설정해주기위해서 해당 옵션을 사용했다. 필요없으면 빼도된다.pipeline {
agent any
stages {
stage('Build') {
steps {
sh 'chmod +x ./gradlew'
sh './gradlew bootJar'
}
}
stage('docker build'){
steps{
script{
docker.build('dockerhi')
}
}
}
stage('docker run'){
steps{
sh 'docker ps -f name=dockerhi -q | xargs --no-run-if-empty docker container stop'
sh 'docker container ls -a -f name=dockerhi -q | xargs -r docker container rm'
sh 'docker images --no-trunc --all --quiet --filter="dangling=true" | xargs --no-run-if-empty docker rmi'
sh 'docker run -d --name dockerhi --net {네트워크명} -p 8081:8081 dockerhi:latest'
}
}
}
}
pipeline {
agent any
stages {
stage('docker build'){
steps{
script{
docker.build('dockerhi')
}
}
}
stage('docker run'){
steps{
sh 'docker ps -f name=dockerhi -q | xargs --no-run-if-empty docker container stop'
sh 'docker container ls -a -f name=dockerhi -q | xargs -r docker container rm'
sh 'docker images --no-trunc --all --quiet --filter="dangling=true" | xargs --no-run-if-empty docker rmi'
sh 'docker run -d --name dockerhi -p 3000:3000 dockerhi:latest'
}
}
}
}
docker ps
명령어를 통해 현재 실행중인 컨테이너
확인이 가능하다.docker ps -a
명령어를 통해 존재하는 모든 컨테이너
를 확인할 수 있다.docker run
부분에서 에러가 나면 보통은 같은 이미지를 빌드하는 컨테이너가 있다는 에러가 뜰것이니, 필요없는 컨테이너들을 삭제해주도록 하자. docker rm [컨테이너ID]
docker logs [컨테이너명]
을 통해서 어느 부분에서 에러가 났는지 확인할 수 있다.version: '3.8'
services:
db:
container_name: my_db
image: mysql
restart: always
env_file:
- .env
environment:
TZ: Asia/Seoul
volumes:
- ./db_volumes/conf.d:/etc/mysql/conf.d
- ./db_volumes/data:/var/lib/mysql
- ./db_volumes/initdb.d:/docker-entrypoint-initdb.d
ports:
- '3307:3307'
networks:
- my_network
networks:
my_network:
docker-compose up -d
명령어를 통해 쉽게 mysql을 도커에 다운받을 수 있다.
.env
파일을 생성하여 민감한 정보들을 담아둘 수 있다.
MYSQL_HOST=
MYSQL_PORT=
MYSQL_ROOT_PASSWORD=
MYSQL_DATABASE=[db이름]
MYSQL_USER=[user]
MYSQL_PASSWORD=[pwd]
잘봤습니다~