프론트엔드 배포 준비물
1. vm
2. docker
3. git(선택)
4. front source
5. node.js
6. nginx
해야할 일
1. 클라우드 컴퓨팅을 대여한다
2. 클라우드에 도커를 설치한다.
3. 깃을 설치한다. (선택)
4. 프론트엔드 소스를 받아온다.
5. 도커를 이용해서 nginx 를 사용해 화면을 배포한다.
그림 한 장 요약
Docker + GCP 활용한 프론트 배포 과정
#1 GCP 환경 설정
1. VM 인스턴스 생성 (= AWS EC2 인스턴스 생성)
1-1.Google Cloud 가입
https://cloud.google.com/products/compute?hl=ko
1-2. 프로젝트 생성
원하는 이름으로 프로젝트 생성한다. 프로젝트 생성 후에 프로젝트 내에서 VM 인스턴스를 생성/사용한다.
1-3. 인스턴스 생성
이름과 부팅디스크와 방화벽 설정만 변경해주었다.
Ubuntu로 선택한 이유는 다른 배포판보다 자료가 많은 것 같아서 선택했다.
2. 외부 ip 할당(= AWS 탄력적 ip 할당)
2-1. VPC 네트워크의 IP 주소 메뉴로 이동
AWS는 고정 IP를 탄력적 IP라고 하는데, GCP에선 외부 IP라고 한다.
고정 IP를 쓰는 이유는, 여러 가지가 있지만 인스턴스를 중지했다가 재시작했을 때, IP주소가 변경되는 걸 방지하기 위해서이다.
"외부고정 IP 주소 예약" 클릭
default로 2개 IP주소가 나와 있다. 이는 임시 유형이라 새로 만들어줘야 한다.
고정 IP 유형이 고정으로 바뀐 것을 확인할 수 있다.
주의할 점은 꼭 VM(전 beach-combine에 연결했습니다)에 연결해야한다. 고정 IP를 할당만 하고 사용하지 않으면 요금이 부과된다. 안 쓰는 고정 IP는 고정주소해제로 삭제해야 한다.
참고링크 - https://choo.oopy.io/5c999170-dde5-4418-addc-00a0d263287c
3. 방화벽 설정
3-1. VPC 네트워크의 방화벽 메뉴로 이동
방화벽 설정을 하여 특정 프로토콜과 포트를 허용해준다. 외부망에서 GCP로 접속하는 Inbound는 TCP/UDP/ICMP 프로토콜과 80/443/22/3389 포트만 허용하고 있다. 포트가 허용되지 않으면, 나중에 배포 후 테스트해보실 때 접속이 안될 수 있다.
포트 80을 사용할 것이기 때문에 디폴트로 생성되어 있는 방화벽 규칙을 사용할 것이기 때문에,
따로 생성하지 않겠다.
(방화벽 규칙 만들기 - 서버 배포 게시글 참고)
3-2. 방화벽 규칙 만들기
저는 8000번 포트를 허용해주고 싶어서 아래와 같이 설정했습니다.
동일한 방법으로 IPv6도 만들어줬습니다.
#2 Docker로 배포하기
2-1. 로컬에 Docker 설치
2-2. 서버에 Docker 설치
1) Docker 인스턴스 접속
2) Docker 설치
공식 문서대로 Docker를 설치하면 된다
https://docs.docker.com/engine/install/ubuntu/
아래 명령어를 입력했을 때, 버전명이 나오면 다운로드 성공!
docker --version
#3 nginx
3-1. docker 권한 설정
혹시 명령어를 입력하는데 docker에 대해서 권한이 없다고 뜨면 docker그룹에 넣어주면 된다.
(/var/run/docker.sock 권한 오류, permission denied)
(명령어 docker를 쓰기 위해서. 계정에 권한이 없으면 sudo docker ~이런식으로 써야함..)
다음 명령어를 입력해서 docker group에 추가해주자
sudo usermod -aG docker $USER
💡 명령어 해석
요약: docker grop에 현재 로그인한 사용자($USER)를 추가하여 Docker 명령을 수행할 수 있게 된다.
sudo: 슈퍼 유저 권한으로 명령어를 실행한다. 일반적으로 관리자 권한이 필요한 작업을 할 때 사용한다.
usermod: 사용자 계정을 수정한다.
-aG docker: 사용자를 그룹에 추가하는 옵션이다. -a는 추가(add)를 의미하고, -G docker는 사용자를 docker 그룹에 추가한다.
$USER: 현재 로그인한 사용자의 이름을 나타내는 환경 변수이다. 실제 명령어 실행 시 이 부분은 로그인한 사용자의 이름으로 대체된다.
3-2. 입력하고 재부팅 해보자.
docker는 이미 실행중이기 때문에, 재부팅해야 옵션이 적용된다.
$ newgrp docker
3-3. nginx pull과 실행(nginx 컨테이너 생성)
Nginx 웹 서버가 백그라운드에서 실행되고, 호스트의 '3000' 포트로 접속하면 Nginx 웹 서버의 기본 페이지('80')가 표시된다.
docker run -d -p 3000:80 --name MyWeb nginx
포트 번호를 같게 하면 설명에서 헷갈릴까봐, 블로그 글에서는 포트번호를 다르게 설명했다.
3-4.에서 설명하겠지만, 실제 프로젝트에서는 위에 명령어에서 80:80 으로 해주었다.
외부 포트 80으로 접속하면 내부 포트 80을 보여주겠다.
💡 명령어 해석
요약 : Nginx 웹 서버가 백그라운드에서 실행되고, 호스트의 '3000' 포트로 접속하면 Nginx 웹 서버의 기본 페이지가 표시된다.
run : 실행, Image가 없다면 다운로드한다.
-d : detach, background로 실행한다.
-p : port넘버 지정, 외부:내부, 외부는 외부에서 접근할 때 쓰는 것이고 내부는 내부 프로그램에서 어떤 포트를 쓰는지 지정. docker가 외부 → 내부(nginx)로 전송해준다.
--name MyWeb : 생성된 컨테이너의 이름을 MyWeb으로 지정하는 옵션이다.
nginx : nginx 이미지를 사용하겠다. latest버전을 사용한다.
컨테이너 실행된 모습
docker ps
3-4. 방화벽 설정
Nginx를 실행 했으니, 이제 인스턴스 외부 ip : port번호(3000)로 접속하면 Nginx 기본 첫 페이지가 보이지 않는다.
이는 인스턴스의 방화벽에서 해당 포트 번호가 허용되지 않았기 때문이다.
포트 `3000`을 사용하려면 방화벽에서 이를 열어줘야 한다. 예를 들어, 포트 번호 3000을 사용하려면 이를 방화벽에서 허용하도록 규칙을 추가해야 한다.
(하지만, 최종적으로 포트 `80`을 사용하기로 결정했다.
게시글에 외부 포트 번호 3000으로 적혀 있지만, 실제 프로젝트에서는 80을 사용하였다.외부 포트번호와 내부 포트번호가 동일하면, 설명할 때 혼동이 올 수 있어서 게시글에서는 외부포트는 3000으로 적도록 하겠다..
포트 `80`은 HTTP의 기본 포트로, 대부분의 시스템에서 기본적으로 열려 있어 별도의 방화벽 규칙 설정이 필요 없다.
또한, 포트 `80`은 접속 시 포트 번호를 생략할 수 있어 URL이 깔끔하게 보여 사용자 경험이 개선된다.)
nginx 테스트 결과 화면
#4 프로젝트 적용
이제 내 프로젝트 화면으로 바꾸면 된다.
그러기 위해서 프론트 소스와 nginx로 이미지를 빌드한다.
4-1. Dockerfile 생성
위에서 본 Welecom to nginx! 기본 첫 페이지를 삭제하고 내 프로젝트를 빌드해서 첫페이지로 갈아끼면 된다.
(주의! 꼭 "D"ockfile 맨앞은 대문자로 해야한다.)
Dockerfile은 Nginx를 기반으로 하여, Nginx의 기본 HTML 파일들을 삭제하고, 사용자 정의 설정 파일과 애플리케이션의 빌드 결과물을 복사한 후, HTTP 포트 80을 노출하는 컨테이너 이미지를 생성한다.
FROM nginx // nginx 이미지 쓸거임
RUN ["rm" ,"-rf", "/usr/share/nginx/html/*"] // nginx 기본 첫 페이지 삭제
COPY ./default.conf /etc/nginx/conf.d/p.conf // 내가 만든 설정으로 대체(💡4-2에 파일있음💡 현재 ./default.conf를 nginx가 생성되면 해당 경로에 복사한다)
COPY build /usr/share/nginx/app // 빌드한 프론트 소스 복사(nginx가 생성되면 build디렉토리를 복사해서 /usr/share/nginx/app 경로에 넣는다. )
// build가 build를 하겠다!가 아니라 현재 경로의 build를 하겠다는 것이다. 앞에 ./생략되어 있다.
EXPOSE 3000 // 컨테이너가 외부와 통신할 때 사용할 포트 번호 80을 노출
4-2. default.conf 설정(nginx 커스텀 설정)
FROM nginx // nginx 이미지 쓸거임
RUN ["rm" ,"-rf", "/usr/share/nginx/html/*"] // nginx 기본 첫 페이지 삭제
COPY ./default.conf /etc/nginx/conf.d/p.conf // 내가 만든 설정으로 대체(💡4-2에 파일있음💡 현재 ./default.conf를 nginx가 생성되면 해당 경로에 복사한다)
COPY build /usr/share/nginx/app // 빌드한 프론트 소스 복사(nginx가 생성되면 build디렉토리를 복사해서 /usr/share/nginx/app 경로에 넣는다. )
// build가 build를 하겠다!가 아니라 현재 경로의 build를 하겠다는 것이다. 앞에 ./생략되어 있다.
EXPOSE 3000 // 컨테이너가 외부와 통신할 때 사용할 포트 번호 3000을 노출
4-3. 프론트 소스를 빌드
프론트 소스를 빌드(npm run build
)하여 생성된 파일들을 Nginx에 넣는다.
프론트 프로젝트의 빌드는 Node.js를 사용하여 수행한다. 이 작업은 윈도우에서 터미널을 통해 실행했다.
이유는 인스턴스의 메모리가 작아서 Node.js 설치와 빌드 작업이 부담되기 때문이다.
따라서, 윈도우에서 빌드를 완료한 후, 빌드 결과물을 Docker Hub에 업로드하고, 인스턴스에서는 Docker Hub에서 이미지를 풀(pull) 받아서 사용한다.
npm run build
build하면 build 디렉토리가 생긴다.
4-4. DockerHub에 올리기
이제 인스턴스에서 프론트엔드 소스를 가져오기 위해서 4-3.에서 만든 프론트엔드 소스를 DockerHub에 올리자!
1) DockerHub 접속
2) repository 생성
3) 이미지 생성
docker login
→ 혹시 안된다면 Docker Desktop을 실행시키고 다시 해보세요!
Docker 이미지 빌드/생성
docker build -t 계정명/리포지토리명 ./
→ ex) docker build -t sesamdocker/villion-fe ./
터미널에서 프로젝트 루트 경로로 이동한 후 위 명령어를 입력한다.
(그냥 인텔리제이 아래 뜨는 터미널 쓰는 걸 추천드립니다,, 경로가 들어가져있어서 편해서요,,)
데스크탑 도커에서 확인 할 수있다.
4) DockerHub로 push
docker push 계정명/리포지토리명
→ ex) docker push sesamdocker/villion-fe
5) DockerHub에 올라간 모습
#5 인스턴스에서 dockerHub에 올린 프로젝트 pull
5-1. 인스턴스에서 DockerHub에서 pull
docker pull sesamdocker/villion-fe
pull받은거 확인
5-2. 컨테이너 실행
run : 실행, Image가 없다면 다운로드함.
고로, 사실 앞에서 pull 안해도 되긴함.. 과정을 보기 위해 넣었음..
docker run --name villion-fe -d -p 80:3000 sesamdocker/villion-fe:latest
인스턴스 포트 80과 프론트 프로젝트 포트 3000번을 연결해주는 작업이 필요하다.
혹시 프로젝트 화면이 아닌 Nginx 화면이 나온다면 Ngnx 컨테이너를 없애준 다음에 실행하자.
배포 끝
❓ 만약, 배경을 바꿔서 업뎃을 해야한다면?
순서 1: 프로젝트에서 배경 변경
순서 2: 빌드 및 Docker 이미지 생성
- 방법 1:
- 프론트엔드 프로젝트 빌드: npm run build 명령어를 사용하여 빌드 파일 생성.
- Docker 이미지 생성: 빌드된 파일을 사용해 Docker 이미지를 생성.
- DockerHub에 푸시: 생성된 Docker 이미지를 DockerHub에 푸시.
- 방법 2:
- 변경된 사항을 Git에 푸시한 후, 인스턴스에서 git pull을 통해 코드 업데이트.
그러나 이 방법은 인스턴스에서 Node.js를 설치하고 프로젝트를 빌드해야 하므로 메모리와 비용 면에서 부담이 크다. 이러한 이유로, 윈도우에서 빌드를 수행하는 방법 1을 선택했다.
- 변경된 사항을 Git에 푸시한 후, 인스턴스에서 git pull을 통해 코드 업데이트.
💡 Git 사용할 때 참고
참고링크 - https://developerkkyu37.tistory.com/86
Git
3-1. gitHub 연동 SSH Key 생성
$ ssh-keygen -t rsa -C “{자기 깃허브 이메일}”
생성되었는지 확인
$ cat ~/.ssh/id_rsa.pub
3-2. 나오는 키를 복사해 깃허브 ssh키에 등록해주어야 한다.
gitHub 접속
Settings에 들어간다.
New SSH key 클릭
key에 복사한 키 내용 붙여넣기
3-3. 다시 우분투로 돌아와 다음 명령어로 접속이 되는지 확인해본다.
$ ssh -T git@github.com
4. front source(프로젝트 연동)
4-1. 깃허브 Repositories안에 있는 프로젝트의 SSH 클론을 복사한다.
4-2. 다음 명령어로 폴더 클론
$ git clone (복사한 깃허브 주소)
4-3. 폴더가 잘 클론되었는지 확인해본다
순서 3: 인스턴스에서 Docker 이미지 실행
- 인스턴스 접속: 인스턴스에 접속한다.
- Docker 이미지 실행:
docker run --name villion-fe -d -p 80:3000 sesamdocker/villion-fe:latest
이 과정에서 사이트가 잠깐 중단될 수 있다. 이를 방지하려면 쿠버네티스와 같은 무중단 배포 도구를 사용할 수 있다.
자동화 도구 사용
이 과정이 번거로울 수 있으므로, Git에 푸시할 때 위의 모든 과정을 자동화할 수 있는 툴로 Jenkins를 사용할 수 있다. Jenkins는 CI/CD 파이프라인을 구축하여 배포 프로세스를 자동화하는 데 가장 널리 사용되는 도구이다.
참고링크
Docker+GCP로 Springboot 배포 총정리(AWS EC2,RDS 대신 GCP VM,cloud SQL을 써보아요)
[Google Cloud Platform/GCP] 구글 클라우드 플랫폼에 Docker로 웹서버 띄우기
[Spring] GCP로 깃허브 연동해서 스프링 프로젝트 예제(with Ubuntu) - 2
'Project > Collabo Project' 카테고리의 다른 글
[Villion] Gateway와 User-Service 간 네트워크 문제 해결 및 Docker 설정 방법 (0) | 2024.09.05 |
---|---|
[Villion] eureka 배포 (0) | 2024.08.29 |
[Villion] FullText Index를 활용한 도서 검색 기능 구현 (0) | 2024.08.15 |
[Villion] 이 책과 함께 구매한 도서 목록 구현하기 (0) | 2024.08.14 |
[Villion] JPA 양방향에서 단방향으로 변경 (0) | 2024.07.26 |