배포할 프로젝트는 있겠지?
여기부턴 개인 프로젝트가 있다는 가정하에 진행한다
프로젝트가 있어야 배포를 하기 때문에 어찌보면 너무 당연한 소리
Docker 쓰는 방법, Jenkins 연동하는 방법 등 검색하면 참고할 글은 많은데 진짜 너무 많아서 못 고르겠다
맨날 하나 골라서 해보면 버전 다르다고 나는 똑같이 안 돼;;;
후... 한큐에 모든걸 끝내버리고 날 위해 정리해두겠단 마인드로 시작 모든걸 정리해두려한다
참고로 해보고 느낀건데 단순히 복붙하는 과정으로는 완벽히 따라할 순 없을 수 있다
일례로 프로젝트 JDK 버전만 달라도 이슈가 생길터이니...
원래 Docker + Jenkins 한큐에 끝내려했는데 너무 길어져서 나눴다 ㅠ
홈서버 사양
제품명 : Beelink S12 Pro
OS : window 10 pro & Ubuntu 22.04
CPU : Intel(R) N100
RAM : 16GB (3200 MHz)
SSD : 512GB (NVMe)
HDD : 500GB (Hitachi)
1) Docker-ce vs Docker.io
Docker는 크게 “docker-ce”와 “docker.io” 두가지 패키지가 존재함
- docker-ce : Docker의 개발사에서 직접 제공되는 인증된 릴리스
- docker.io : Debin/Ubuntu의 공식 패키지 관리 시스템 (APT)에서 제공되는 릴리스
docker.io가 비교적 안정적이나 Docker CE에 비해 업데이트가 느리거나, 기능이 제한될 수 있다
2) Docker 설치
기본적으로 나는 docker-compose 쓸거다
docker-compose는 컨테이너 관리를 한번에 할 수 있게 도와주는 도구로 생각하면 된다
그러니까 컨테이너 1, 2, 3을 한번에 띄우고 싶을 때 docker-compose는 셋팅까지 한번에 다 해놓고 명령어 한줄이면 (docker compose up -d) 끝나지만 docker로만 하려면 명령어를 옵션 달아가며 총 3줄을 다르게 써야한다 (귀찮)
근데 또 이제 docker, docker-compose는 엄연히 구분되는거라 둘 다 설치해줘야 함
아래에 전부 기술해 두었음.
(1) Ubuntu 업데이트
시스템을 최신 상태로 업데이트
sudo apt update && sudo apt upgrade -y
(2) Docker 설치
1. 필수 패키지 설치
sudo apt install apt-transport-https ca-certificates curl software-properties-common
2. Docker GPG 키 추가
curl -fsSL <https://download.docker.com/linux/ubuntu/gpg> | sudo apt-key add -
3. Docker 저장소 추가
sudo add-apt-repository "deb [arch=amd64] <https://download.docker.com/linux/ubuntu> $(lsb_release -cs) stable"
4. Docker 설치
sudo apt update
sudo apt install docker-ce
5. Docker 서비스 활성화 및 시작
sudo systemctl enable docker
sudo systemctl start docker
6. 현재 사용자에게 Docker 권한 부여 (sudo 없이 실행 가능하도록)
# ${USER}에는 현재 계정명을 적으면 된다
sudo usermod -aG docker ${USER}
3) Docker Compose 설치 방법
(1) Docker Compose 설치
sudo curl -L "<https://github.com/docker/compose/releases/download/v2.22.0/docker-compose-$>(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
(2) 실행 권한 부여
sudo chmod +x /usr/local/bin/docker-compose
(3) 설치 확인
docker-compose --version
4) Docker Compose에 Nginx와 Jenkins 설정
(1) 프로젝트 폴더 생성
먼저 Docker Compose 파일을 저장할 디렉토리 생성
나는 메인 디렉토리에 docker-compose라는 폴더에 넣어둘 것이다
mkdir ~/docker-compose
cd ~/docker-compose
(2) docker-compose.yml 파일 작성
아래와 같이 docker-compose.yml 파일을 작성하여 Nginx와 Jenkins 컨테이너를 설정한다
nano든 vim이든 편집기 써서 docker-compose 디렉토리 안에 docker-compose.yml 파일 만들어서 아래 내용 기입하면 됨
깔끔버전
version: '3.8'
services:
nginx:
image: nginx:latest
container_name: nginx-container
ports:
- "80:80"
volumes:
- ./nginx/html:/usr/share/nginx/html
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
networks:
- jenkins_network
jenkins:
image: jenkins/jenkins:lts
container_name: jenkins-container
ports:
- "8080:8080"
- "50000:50000"
volumes:
- jenkins_home:/var/jenkins_home
networks:
- jenkins_network
volumes:
jenkins_home:
networks:
jenkins_network:
driver: bridge
작성해둔 docker-compose.yml 설명
nginx
nginx:
image: nginx:latest
container_name: nginx-container # 컨테이너 명은 nginx-container
ports:
- "80:80" # 80번 포트를 nginx에 할당
volumes:
- ./nginx/html:/usr/share/nginx/html # 로컬의 /nginx/html은 컨테이너 내부의 /usr/share/nginx/html와 연결
- ./nginx/nginx.conf:/etc/nginx/nginx.conf # 로컬의 /nginx/nginx.conf(nginx 설정 파일)은 컨테이너 내부의 /etc/nginx/nginx.conf와 연결
networks:
- jenkins_network
- html과 nginx.conf를 로컬의 실제 파일과 연결하는 이유는 컨테이너 내부의 설정 파일, 웹 페이지와 관련된 두 파일을 편하게 서버에서 편집하기 위함이다.
Jenkins
jenkins:
image: jenkins/jenkins:lts
container_name: jenkins-container # 생성할 컨테이너 명은 jenkins-container
ports:
- "8080:8080" # 8080 포트와 50000 포트를 할당한다
- "50000:50000"
volumes:
- jenkins:/var/jenkins_home # jenkins라는 볼륨을 jenkins 컨테이너 내부의 /var/jenkins_home 디렉토리와 연결
- ./jenkins_home:/var/jenkins_home/data # 로컬의 jenkins_home 디렉토리를 컨테이너 내부의 /var/jenkins_home/data와 연결
networks:
- jenkins_network
- 컨테이너 내부의 디렉토리인 /var/jenkins_home를 volume과 연결하는 이유는 컨테이너는 휘발성이 강해 쉽게 삭제되기 쉬운데, 이 말인 즉 매번 컨테이너를 새로 만들 때마다 젠킨스 세팅을 새로 해야한다는 의미이다
- 이는 곧 지옥(?!) 이기 때문에 설정 파일이 존재해 있는 컨테이너 내부의 위치 /var/jenkins_home를 volume이라는 docker 저장소에 저장하는 것이다
- 이러면 껐다 켜도 젠킨스 설정이 남아있다. volume에 대한 자세한 설명은 여기서 풀면 너무 길어지니 구글링 추천
(3) Nginx 설정 파일 작성
위에서 기술한대로 nginx.conf를 내부의 설정 파일과 연결하려면 실제 로컬 파일에도 해당 파일이 존재해야만한다
없는걸 연결할 수는 없으니까
현재 폴더 구조
home
├─ docker-compose
└─ docker-compose.yml
먼저 로컬에 nginx 폴더를 만들고, 그 안에 설정 파일을 작성한다
mkdir -p nginx/html
touch nginx/nginx.conf
nginx/nginx.conf 파일에 기본 설정 추가
http {
server {
listen 80; # 80 포트에서 수신
location / {
root /usr/share/nginx/html; # HTML 파일이 위치한 경로
index index.html; # 기본 인덱스 파일
}
}
}
(4) 간단한 웹 페이지 띄워보기
간단히 nginx/html 디렉토리에 index.html을 하나 만들어 보겠다
# nano 사용시
sudo nano nginx/html/index.html
# vim 사용시
sudo vim nginx/html/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Welcom to WOMBAT WORLD</title>
</head>
<body>
<h1>Hello, Ratatou2!!!! :) </h1>
<p>This is a simple web page served by Nginx.</p>
<p>At least this is the Test For Wombat World!!</p>
</body>
</html>
일단 여기까지 했다면 nginx에 index.html 페이지를 물려놓았기 때문에 서버에 접속하면 해당 페이지를 보여주게 된다!
(5) 내 프로젝트 빌드 배포하기
이젠 내 프로젝트를 빌드해서 배포해보자
기본적으로 이 글은 SpringBoot를 기준으로 하고 있으며 .jar 파일을 배포하는 것을 기준으로 한다
또한 이 .jar 파일을 띄워줄 컨테이너를 docker-compose.yml에 추가해야한다
nginx.conf와 docker-compose.yml 두가지 다 수정해야 함
1. nginx.conf 수정
events {
worker_connections 1024; # 최대 연결 수
}
http {
server {
listen 80; # 80 포트에서 수신
location / { # 서버 주소로 들어오는 모든 요청을 아래의 proxy_pass로 보내겠다는 의미
#root /usr/share/nginx/html; # HTML 파일이 위치한 경로
#index index.html; # 기본 인덱스 파일
proxy_pass http://backend:8080; # proxy_pass해서 넘길 컨테이너 명은 backend이며 8080 포트로 넘길 것이다
}
}
}
2. docker-compose.yml 수정
n100@n100-S12-Pro:~/docker-compose$ cat docker-compose.yml
version: '3.8'
services:
nginx:
image: nginx:latest
container_name: nginx-container
ports:
- "80:80"
volumes:
- ./nginx/html:/usr/share/nginx/html
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
networks:
- jenkins_network
jenkins:
image: jenkins/jenkins:lts
container_name: jenkins-container
ports:
- "8080:8080"
- "50000:50000"
volumes:
- jenkins:/var/jenkins_home
- ./jenkins_home:/var/jenkins_home/data
networks:
- jenkins_network
backend: # 추가된 서비스
image: openjdk:21-jdk # OpenJDK 이미지 사용 (JAR 파일을 실행하기 위해)
container_name: backend
volumes:
- ./jenkins_home:/app # Jenkins의 볼륨을 컨테이너의 /app 경로에 마운트
command: ["java", "-jar", "/app/lab-0.0.1-SNAPSHOT.jar"] # JAR 파일 실행
networks:
- jenkins_network
volumes:
jenkins_home:
jenkins:
external: true
networks:
jenkins_network:
driver: bridge
5) Docker Compose로 Nginx 및 Jenkins 실행
(1) Docker Compose 실행
docker-compose up -d
(2) 실행한 컨테이너 잘 돌아가는지 상태 확인
docker-compose ps
TroubleShooting
위 사항들을 진행하며 맞닥뜨렸던 이슈들..
(1) nginx 실행 안됨
- nginx.conf 파일이 없어서 볼륨 마운트가 안되던 상황
n100@n100-S12-Pro:~/docker-compose$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2803f43c2d2e jenkins/jenkins:lts "/usr/bin/tini -- /u…" 8 minutes ago Up 8 minutes 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp, 0.0.0.0:50000->50000/tcp, :::50000->50000/tcp jenkins-container
n100@n100-S12-Pro:~/docker-compose$ docker logs nginx
Error response from daemon: No such container: nginx
n100@n100-S12-Pro:~/docker-compose$ sudo docker logs nginx-container
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2024/10/18 15:12:32 [emerg] 1#1: no "events" section in configuration
nginx: [emerg] no "events" section in configuration
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: IPv6 listen already enabled
/docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2024/10/18 15:17:39 [emerg] 1#1: "server" directive is not allowed here in /etc/nginx/nginx.conf:1
nginx: [emerg] "server" directive is not allowed here in /etc/nginx/nginx.conf:1
- 직접 파일 만들어주었음
(2) 웹 페이지 안 열리는 이슈
- index.html이 없었음 이 역시 만들어주었음
- 기본적으로 linsten이 80이니까 내부에선 그냥 서버 ip 치면 들어가짐
- 외부에선 80으로 접속하게 하기싫어서 포트포워딩(e.g. 12490) 하고 DNS:12490 하면 접속된다 (물론 외부 IP:12490도 잘됨)
(3) 제대로 컨테이너 생성하지 못하는 이슈
- temp_test_backend 처럼 _를 네이밍에 넣으면 에러 나더라
...
temp_test_backend: # 추가된 서비스
image: openjdk:21-jdk # OpenJDK 이미지 사용 (JAR 파일을 실행하기 위해)
container_name: temp_test_backend
volumes:
- ./jenkins_home:/app # Jenkins의 볼륨을 컨테이너의 /app 경로에 마운트
command: ["java", "-jar", "/app/lab-0.0.1-SNAPSHOT.jar"] # JAR 파일 실행
networks:
- jenkins_network
...
- '-' 로 바꿔줘야 한다
'Linux' 카테고리의 다른 글
Ubuntu 기본 언어 변경 방법 (feat. 영어 vs 한글) (1) | 2024.11.26 |
---|---|
홈서버 만들기 (5) - MySQL 세팅하기 (feat. Docker & DBeaver) (0) | 2024.11.25 |
홈서버 만들기 (4) - CI/CD 구축 (feat. Jenkins) (0) | 2024.11.25 |
홈서버 만들기 (2) - 서버 설정 (feat. 포트포워딩 & DDNS) (0) | 2024.11.25 |
홈서버 만들기 (1) - 듀얼 부팅 설정 (Window & Ubuntu) (0) | 2024.11.25 |