저번 프로젝트 때 Jenkins에 대한 아쉬움이 많아서 이번엔 각잡고 제대로 해보려고 한다.
저번엔 Docker in Docker 방식으로 진행했었는데 다시 개념을 찾아보니 이러한 문제가 있다고 한다.
Docker in Docker는 Docker 컨테이너 내부에서 Docker를 실행하는 방식으로, 하나의 Docker 호스트에서 다른 Docker 호스트를 만드는 것과 유사하지만 문제점이 있다.
- DinD 방식은 컨테이너 안에서 호스트 시스템의 Docker 데몬을 실행하는 것이므로, 컨테이너 안에서 실행 중인 모든 애플리케이션은 호스트 시스템의 Docker 데몬에 대한 접근 권한을 가지게 됩니다. 이는 보안 문제를 발생시킬 수 있습니다.
- DinD 방식은 성능에 문제가 있을 수 있습니다. 컨테이너 안에서 Docker 데몬을 실행하면 추가적인 레이어가 생성되므로 컨테이너의 시작 시간이 느려질 수 있습니다.
- DinD 방식은 이식성 문제가 있습니다. 호스트 시스템의 Docker 데몬 버전과 컨테이너 안에서 실행되는 Docker 데몬 버전이 일치하지 않으면 호환성 문제가 발생할 수 있습니다.
이러한 문제 때문에 이번에는 pem키도 있으니 ssh 통신을 이용해서 Docker 이미지를 tar 아카이브 파일로 저장하여 서버에 보낸 후 컨테이너를 실행시키려고 한다.
그냥 DInD나 Dockerhub를 통한 배포방법도 있지만 이번엔 제대로!
저번에 진행했던 DinD 배포 방법이다. 미숙한게 너무 많지만 저당시엔 2주나 걸려서 진행했었다ㅠㅠ
Jenkins 설치(Docker에 설치)
sudo docker run -itd --name jenkins -p 8080:8080 -v /docker/jenkins:/var/jenkins_home -v /var/run/docker.sock:/var/run/docker.sock -e TZ=Asia/Seoul -u root jenkins/jenkins:lts
Jenkins 내부 들어가기
sudo docker exec -it jenkins bash
Jenkins Git 설정하기
여기서 제일 중요한 부분은 Branches to build인데 나는 이 item에서 be-develop만 하고 싶기 때문에 저렇게 적음
*/master라고 적으면 *가 와일드카드 이기 때문에 be-feature/master 이런것들도 다 해버리는 뜻이다
SpringBoot build.gradle
// 실행파일 생성
bootJar {
archiveFileName = "backend-0.0.1-SNAPSHOT.jar"
}
SpringBoot의 경우 DockerFile에서 Image 생성할 때 gradlew를 인식하지 못하는 경우가 있어 Jenkins에서 build.gradle을 찾아서 빌드 하도록 설정
Execute Shell
docker image prune -a --force
mkdir -p /var/jenkins_home/images_tar #이미지를 저장할 폴더 생성
cd /var/jenkins_home/workspace/bbkk_backend/BackEnd/
docker build -t spring .
docker save spring > /var/jenkins_home/images_tar/spring.tar
cd /var/jenkins_home/workspace/bbkk_django/backend_django/
docker build -t django .
docker save django > /var/jenkins_home/images_tar/django.tar
cd /var/jenkins_home/workspace/bbkk_frontend/FrontEnd
docker build -t react .
docker save react > /var/jenkins_home/images_tar/react.tar
ls /var/jenkins_home/images_tar
docker image prune -a --force
-a: 모든 이미지를 대상으로 삭제할 것임을 나타내며,
--force : 삭제할 이미지가 없더라도 오류를 발생시키지 않고 강제로 실행할 것임을 나타낸다
사용되지 않은 모든 이미지와 관련된 모든 컨테이너 및 기타 관련 리소스가 삭제되는데 이는 디스크 공간을 확보하고 시스템의 성능을 향상시키는 데 도움이 된다
Webhook 설정
Jenkins 사용자 설정 - Publish over SSH - SSH Servers 추가
EC2 Server Passwd 설정
EC2 로그인 차단 해제(기본적으로 id,pw을 이용한 로그인이 차단되어있어 이를 해제)
vim /etc/ssh/sshd_config
service sshd reload
다시 Jenkins로 돌아와서
key를 지우고 방금 설정한 passwd를 입력 후 Test Configuration을 눌렀을 때 success가 뜨면 ok
빌드 후 조치 - Send build artifacts over SSH
"Send build artifacts over SSH"는 빌드 결과물을 SSH를 통해 전송하는 것을 의미한다
Name에 프로젝트 이름을 써주고 Source file은 아무거나 입력해도 괜찮음. 빈칸 안만드려고 그냥 넣은거라고 생각하면 됨
Exec command 설정
#도커 이미지를 도커에 가져옴
sudo docker load < /jenkins/images_tar/django.tar
sudo docker load < /jenkins/images_tar/react.tar
sudo docker load < /jenkins/images_tar/spring.tar
#실행중인 컨테이너의 이름을 찾아 같은 이름이 있으면 컨데이너를 멈춤
if (sudo docker ps | grep "django"); then sudo docker stop django; fi
if (sudo docker ps | grep "react"); then sudo docker stop react; fi
if (sudo docker ps | grep "spring"); then sudo docker stop spring; fi
#도커 이미지를 실행시켜줌
# -d : 백그라운드 모드
# -p {localhost port}:{docker port}
# --rm : 컨테이너 종료시 삭제
# --name {container name} {image name} 해당 이름으로 이미지를 실행
sudo docker run -it -d --rm -p 8082:8082 --name django django
sudo docker run -it -d --rm -v /etc/nginx/conf.d:/etc/nginx/conf.d -p 3000:80 --name react react
sudo docker run -it -d --rm -p 8081:8081 --name spring spring
echo "Run testproject"
default.conf
server {
listen 80;
listen [::]:80;
server_name localhost;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri /index.html; #이렇게 해야 맞는거임
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
Error : docker not found
Jenkins에서 docker 플러그인을 설치했다고 해서 docker를 사용할 수 있는게 아니다.
EC2 서버에 설치된 Docker 컨테이너는 젠킨스 서버 자체를 위한 것이며, 빌드를 실행하는 노드(빌드 에이전트)에서도 Docker를 실행할 수 있도록 해당 노드에 별도의 Docker를 설치해야한다
Docker로 설치한 Jenkins의 내부는 debian으로 되어있기 때문에 debian에 맞는 Docker를 설치해야 한다
docker exec -it jenkins bash
apt-get update
apt install apt-transport-https ca-certificates curl gnupg2 software-properties-common
curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add -
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable"
apt update
apt install docker-ce docker-ce-cli containerd.io
docker -v
# 이건 필요에 따라서?
systemctl start docker
systemctl enable docker
Nginx Config.conf
server {
location /{
proxy_pass http://localhost:3000;
}
location /api {
rewrite ^/api(.*)$ $1 break;
proxy_pass http://localhost:8081;
}
location /rec {
rewrite ^/rec(.*)$ $1 break;
proxy_pass http://localhost:8082;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/bbkk.store/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/bbkk.store/privkey.pem; # managed by Certbot
# include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
# ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = bbkk.store) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name bbkk.store;
return 404; # managed by Certbot
}
Spring Dockerfile
FROM openjdk:11-jdk-alpine
WORKDIR /var/jenkins_home/workspace/bbkk_backend/BackEnd
COPY build/libs/bbkk-0.0.1-SNAPSHOT.jar /app.jar
EXPOSE 8081
ENTRYPOINT ["java", "-jar", "/app.jar"]
Django Dockerfile
FROM python:3.9.14
ENV JAVA_HOME /usr/lib/jvm/java-8-openjdk-amd64/jre
ENV PYTHONUNBUFFERED 1
RUN apt-get update && apt-get install -y g++ default-jdk
WORKDIR /var/jenkins_home/workspace/ggotmari/backend_django
COPY . .
RUN pip install --upgrade pip
RUN pip install -r requirements.txt
# RUN pip install gunicorn
# RUN python manage.py migrate --fake
# CMD ["gunicorn", "ggotmari.wsgi", "--bind", "0.0.0.0:8000"]
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
React Dockerfile << nginx안에 또 nginx를 하는 방법이라 리소스 낭비임
# nginx 이미지를 사용합니다. 뒤에 tag가 없으면 latest 를 사용합니다.
FROM nginx
# root 에 app 폴더를 생성
RUN mkdir /app
# work dir 고정
WORKDIR /app
# work dir 에 build 폴더 생성 /app/build
RUN mkdir ./build
# host pc의 현재경로의 build 폴더를 workdir 의 build 폴더로 복사
ADD ./dist /usr/share/nginx/html
# nginx 의 default.conf 를 삭제
#RUN rm /etc/nginx/conf.d/default.conf
# host pc 의 nginx.conf 를 아래 경로에 복사
#COPY ./config.conf /etc/nginx/conf.d
# 80 포트 오픈
EXPOSE 80
# container 실행 시 자동으로 실행할 command. nginx 시작함
CMD ["nginx", "-g", "daemon off;"]
React Dockerfile
FROM node:16.17.0 as build-stage
WORKDIR /var/jenkins_home/workspace/ggotmari/frontend/ggotmari
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
#COPY --from=build-stage /var/jenkins_home/workspace/ggotmari/frontend/ggotmari/build /usr/share/nginx/html
#COPY --from=build-stage /var/jenkins_home/workspace/deploytest/testproject_react/deploy_conf/nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 3000
CMD ["npm", "start"]
'DevOps' 카테고리의 다른 글
[Grafana] Customizing Grafana Alerting Notification Templates (0) | 2024.03.08 |
---|---|
[SonarQube/Jenkins] SonarQube + Jenkins + GitLab 연동하기 (0) | 2023.04.24 |
[AWS] EC2 인스턴스(Ubuntu)에서 Docker 설치 (1) | 2023.03.13 |
[Jenkins] Jenkins로 nginx + react 빌드 및 배포하기 (1) | 2023.02.03 |
[Jenkins] Jenkins로 Springboot 빌드 및 배포하기 (0) | 2023.01.26 |