-
Notifications
You must be signed in to change notification settings - Fork 2
[재하] 1119(일) 개발기록
- NCP에서 VPC/subnet 및 서버/DB 인스턴스 구성
- DB(MySQL) 설치 및 원격 접속 가능하도록 설정
- WEB, WAS Dockerfile 작성하고 build, push, pull
- nginx 설정파일 작성 및 docker 네트워크 학습
- docker-compose 설치, yml파일 작성, 실행
다음주엔 GitHub Actions 꼭 하자
- Web, WAS용 서버 인스턴스
- 서버 인스턴스에 Docker 설치
- DB용 인스턴스 생성
- MySQL 설치
- WAS 서버 Dockerfile 작성
- Docker build, push, pull로 WAS 배포
- MySQL 원격 연결 설정
- WEB 서버 Dockerfile 작성 후 build
- Docker-Compose 설치, 설정파일 작성, 실행
지난 주 목요일에 설정을 이미 마쳐서, 간단히 기록만 남기겠음
standard s2-g2 인스턴스를 만들었으며, 공인 IP 부여함.
- VPC 만들고 그 내부에 (10.11.0.0/16)
- public subnet 구성 (10.11.1.0/24)
- private subnet 구성 (10.11.51)
- nat subnet도 public으로 예비로 만들어뒀다
- ncloud 내부 repository가 존재해 private의 NAT 연결이 불필요할 수 있어서, 추후 사용되지 않으면 삭제해도 좋을 것 같음.
라우팅 테이블은 위와 같이 구성했다.
ACG 규칙도 위와 같이 설정. Inbound 3000, 5173은 NGINX 리버스 프록시 배치 전 테스트를 위해 등록해놓았으며, NGINX 구동 이후 삭제 예정
여기 들어가면 인스턴스 생성 시 만든 키페어 파일을 이용해 os 계정 비번을 확인할 수 있음
ssh -i ./b1g1-server-key.pem root@175.106.98.101
이제 다운받은 키페어 파일과 확인한 공인IP, 비밀번호를 이용해 위와 같이 SSH 접근을 해보자.
permission에 대한 경고메시지. 물론 이대로도 잘 되지만 보안을 위해 수정해주자.
chmod 400 b1g1-server-key.pem
깔끔하게 접근 잘 됨!
학습메모 4를 참고하여 서버 인스턴스에 Docker를 설치했다.
# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
# Add the repository to Apt sources:
echo \
"deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
"$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
인터넷 외부 연결만 잘 설정되어 있으면, 위 내용을 순서대로 입력만 해주면 원활히 설치된다.
잘 설치됨!
micro 서버로 DB용 Server 인스턴스를 만드려고 했더니, Classic 탭에 밖에 없는 줄 알고 다 만들어놓고 보니 VPC 설정 자체가 안되는 거였다...
VPC 탭에서 만들어야 한다...
그래서 쿨하게(사실 눈물을 머금음) 반납하고 다시 시작
왜 없나 했더니 64비트 우분투가 아니라, KVM 하이퍼바이저로 제공되는 우분투 이미지를 클릭해야만 micro 서버를 선택할 수 있다.. 참 비직관적이다..
그렇다고 함
설정은 최종적으로 이렇게 해 줬다. private 서브넷 이용.
Network Interface가 설정되지 않아서 넘어가지 않는 거였는데, 에러도 안뜨고 공인 IP 연결을 위해 Public Subnet을 선택하라는 걸 마치 에러처럼 표시해줘서 한참을 헤맸다. 참 비직관적...
최대 무료 스토리지 용량으로.
키 페어는 public쪽과 분리해주는 게 좋다고 함. 보안을 위해 새로 생성해뒀다.
ACG는 ssh용 22번, MySQL용 3306, ping 테스트용 ICMP까지 우선 열어뒀다. 추가되는 데이터베이스는 사용할 때 열어주기로 함.
Inbound, Outbound 모두 소스를 10.11.0.0/16
으로 설정해줬다.
VPC 내에서만 접근이 가능하도록 설정한 것!
그래서 외부에서 SSH로 접근하려면 public인 웹서버 인스턴스에 SSH 접속 후 거기서 SSH로 다시 private인 DB 인스턴스로 접근해야 한다.
적용 후 서버 생성!
SCP를 활용해 private 키페어를 서버 인스턴스로 넘겨준다.
비밀번호 확인 후 앞서 말한 대로 서버 인스턴스를 타고 접근! 성공이다.
sudo apt update
sudo apt install mysql-server
나는 한 인스턴스에 여러 DB를 설치하다보니 인스턴스 순정을 유지하기 위해 docker로 관리하는 게 맞다고 생각했지만, 데이터 손실 우려 등으로 로컬에다 설치하는 게 맞다는 페어분의 의견으로 인스턴스에 직접 설치하기로 했다.
apt로 설치. update 찍어보니 ncloud에 repo가 따로 있어서 따로 NAT 설정을 하지 않아도 설치가 가능했다! 오우.. NAT 필요없겠는걸?
mysql-server 설치 완료
잘됨!
FROM node:20-alpine
WORKDIR /app
ADD . /app
RUN yarn workspace server build
EXPOSE 3000
ENTRYPOINT ["yarn", "workspace", "server", "start:prod"]
WAS 서버용 도커파일이다. node:20-alpine으로 작업폴더에 프로젝트를 옮기고,
build 후 3000번 포트를 열고 yarn workspace server start:prod
로 실행해준다.
FROM node:20-alpine
WORKDIR /app
ADD . /app
EXPOSE 5173
ENTRYPOINT ["yarn", "workspace", "client", "dev"]
클라이언트용은 build를 해주는 게 맞다고 판단되지만, 현재 fe 프로젝트가 빌드 시 에러가 떠서,
문제를 해결할 때 까지 yarn workspace client dev
로 했었다.
이제 문제가 해결되어 WEB 서버에 build 한 내용을 정적으로 집어넣어 주는 것으로 변경.
docker build -t qkrwogk/web16-b1g1-be -f ./Dockerfile-server .
docker push qkrwogk/web16-b1g1-be
인스턴스에서 docker pull
docker pull qkrwogk/web16-b1g1-be
WARNING: The requested image's platform (linux/arm64/v8) does not match the detected host platform (linux/amd64/v3) and no specific platform was requested
95ea437f6b11ba59b710e519ba8741ad6ae3df169664bb6265d5274ba1f8a6b0
플랫폼 에러! linux/amd64로 다시 빌드
docker build -t qkrwogk/web16-b1g1-be -f ./Dockerfile-server . --platform linux/amd64
잘 빌드해서 실행시켰는데, 실행이 안된다!
에러 로그를 보니 bcrypt 로딩 오류
학습메모 3을 참고하니, bcrypt가 python에 의존하는데 alpine linux에 python이 기본 설치가 안돼있어서 생기는 오류랜다 ㅎ
그래서 bcryptjs모듈을 쓰거나 python을 따로 설치해주면 된다고 함.
bcryptjs 쓰기로함 ㅋ
bcryptjs로 의존성을 변경해서 다시 build해보자.
yarn workspace server remove bcrypt
yarn workspace server add bcryptjs
// from
import * as bcrypt from 'bcrypt';
// to
import * as bcrypt from 'bcryptjs';
의존성 변경
docker build -t qkrwogk/web16-b1g1-be:week2 -f ./Dockerfile-was . --platform linux/amd64
docker 이미지 빌드. 태그도 달아줬다.
docker push qkrwogk/web16-b1g1-be:week2
push!
서버 인스턴스에셔 pull!
latest 태그는 자동으로 바뀌지 않는다. 앞으로 같이 push해주거나 latest 태그로 넣어줘야 할듯.
docker container run -d -p 3000:3000 --name was qkrwogk/web16-b1g1-be:week2
실행 잘 되고요
근데 안되네요 TypeORM 설정을 다 채웠어야 하는데!
sudo apt install mysql-client
mysql client를 설치해서 DB 인스턴스에 연결이 되는지부터 보자.
응 안됨
SELECT Host,User,plugin,authentication_string FROM mysql.user;
그래 설정이 돼있을리가 없지.. 하자
host가 localhost인 user만 있으니까 다른 host로의 user를 추가해줘야 함.
학습메모 6 참고.
CREATE USER 'noroot'@'10.11.1.6' identified by '비밀번호';
GRANT ALL PRIVILEGES ON *.* to 'noroot'@'10.11.1.6';
FLUSH PRIVILEGES;
SHOW GRANTS FOR 'noroot'@'10.11.1.6';
이제 다시 원격 접속이 되는지 확인해보자.
안됨 ㅡㅡ 아 왜
service mysql restart
service mysql status
mysql service 재실행
그래도 안됨 후..
이거다 분명함 (학습메모 7)
sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf
bind-address 0.0.0.0
으로 바꾸고 (전체 허용)
다시 재실행
드디어 된다 이말씀.. 후 내가 이래서
.env 파일을 docker에 --env-file 옵션으로 전달하면 된다고 하니, 우선 이것부터 해보자.
docker run -d -p 3000:3000 --name was --env-file ./.env qkrwogk/web16-b1g1-be:week2
와 이거 될것같은데?
와 된다 대박
아 너무 행복해
DB에도 잘 들어가는거 확인 ^^
이제 FE랑 NGINX 차례다.
빌드한 fe 프로젝트와 nginx 이미지를 활용해서, NGINX + 정적 파일 서빙(FE)을 수행하는 Docker 이미지를 build해보자.
yarn workspace client build
우선 빌드해서 dist 폴더를 만들고
FROM nginx:alpine
WORKDIR /usr/share/nginx/html
ADD ./packages/client/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
해당 폴더를 /usr/share/nginx/html로 옮긴 후 실행
# nginx.conf
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ =404;
}
location /api {
proxy_pass http://[WAS 컨테이너 주소]:3000;
# /api 경로를 /로 재작성
rewrite ^/api(/.*)$ $1 break;
}
}
nginx 설정파일은 위와 같이 리버스 프록시가 잘 안되는 것 같은데 연구가 필요하겠다. 연구 완료!
- /api 경로를 WAS에 전달 시 /로 재작성 하는 건 위와 같이 rewrite 구문으로 해결할 수 있음
- proxy_pass를 localhost로 하면 컨테이너 안쪽으로만 요청이 가기 때문에, 다른 컨테이너인 WAS로 요청이 들어가려면 그 IP로 접근해야 함.
2번에 대해서 부연설명을 하자면 docker 내부 네트워크가 bridge 형태로 vmware 네트워크 설정처럼 따로 구성되어 있다.
docker inspect [container id] | grep IPAddress
그래서 각 주소가 위와 같이 172.17
대역으로 자동 부여가 되는데, 서로서로 통신을 해주려면 이 IP로 직접 접근을 하거나(근데 예측할수가 없지)
학습메모 5를 참고하여 --link 옵션으로 실행 시 네트워크를 연결해주면 되시겠다. 좀이따가 해보자.
docker container run -d -p 7777:80 --name nginx-test qkrwogk/web16-b1g1-fe:latest
로컬에서 테스트할 때는 호스트에서 BE 서버를 실행시켜놨으므로 host.docker.internal
을 BE 주소 자리에 넣어주시면 되겠다.
정적 파일 서빙 잘 된다! 근데 왜 landing만 뜨는거지 이건 좀 여쭤봐야 알듯.
된다된다!
docker build -t qkrwogk/web16-b1g1-fe:week2 -f ./Dockerfile-web . --platform linux/amd64
docker push qkrwogk/web16-b1g1-fe
이제 배포할 때, docker 땡겨와서 --link 옵션으로 was 주소를 설정해주는 걸 해보자. nginx.conf에서 WAS 컨테이너 주소는 was
로 채워줬다.
# 서버 인스턴스에서
docker pull qkrwogk/web16-b1g1-fe:week2
이제 학습메모 5를 참고해서 네트워크를 연결한 채로 컨테이너를 돌려보자.
docker container run -d -p 80:80 --name web --link was:was qkrwogk/web16-b1g1-fe:week2
요렇게 하면 될 것 같긴 한데,
가만히 보니 그리 좋은 방법은 아닌 듯 하다. 언제 deprecated 될지 모르니 도커 네트워크를 직접 정의해주면 되시겠다.
docker network create b1g1-network
docker network connect b1g1-network web
docker network connect b1g1-network was
그럼 자동으로 DNS가 세팅된다고 하니 최고다. 해보자.
docker container run -d -p 80:80 --name web qkrwogk/web16-b1g1-fe:week2
링크 옵션 빼고 이걸로 실행
was 주소때문에 안됨.
was 네트워크를 먼저 띄우고, network에 등록하고, 그 다음에 web을 띄워야겠다.
connect가 안 된 상태로 띄우니 매한가지로 에러.. 아니 그럼 순서를 어떡해야함?
학습메모 11에서 docker-compose로 해결할 방법을 찾음..
결국 오늘 docker-compose까지 건드리게 되는 건가 나.?
에라 모르겠다 끝까지 한 번 가보자 오늘. docker-compose 설치부터 함.
version: '3' # docker-compose 버전임. 이거 'week2'로 했다가 에러남
services:
was:
container_name: was
image: qkrwogk/web16-b1g1-be:week2
ports:
- 3000:3000
env_file:
- .env
networks:
- b1g1-network
web:
container_name: web
image: qkrwogk/web16-b1g1-fe:week2
ports:
- 80:80
networks:
- b1g1-network
networks:
b1g1-network:
driver: bridge
난 똑똑하니까 뚝딱 만들어버림
scp -i b1g1-server-key.pem ./docker-compose.yml root@175.106.98.101:/root/
scp로 docker-compose.yml
옮겨주고
이것저것 남아있던 컨테이너들 정리해주고
sudo docker-compose up
대망의 up
!
한 번에 되면 기분이 참 좋았을텐데..
찾아보니 이 version이 내가 정하는 태그같은게 아니라 docker-compose 버전이였다 ㅎ 머쓱 '3' 가자.
이것이 성공의 맛..?
나는 운다.. 감격받아서..
근데 이게 foreground로 계속 실행되고, 끄면 꺼지더라. 그래서 백그라운드로 실행시키는 -d 옵션을 줘서 실행함.
sudo docker-compose up -d
ssh 접속 끊어져도 되면 참 좋겠다.
된다 참 좋다.
오늘은 발 뻗고 잘 수 있겠다.
- MySQL 설치
- 도커파일 이름 지정하여 빌드하기
- bcrypt 모듈 에러 나는 이유
- Ubuntu에 Docker 설치 방법 공식문서
- docker --link 옵션으로 컨테이너 네트워크 연결
- MySQL 유저 원격접속 허용하기
- ERROR 2003 (HY000): Can't connect to MySQL server on 'x.x.x.x' (111)
- Docker Compose에서 각 서비스 컨테이너에 쓰이는 환경변수를 다루는 방법
- [Docker] 도커의 환경변수 설정
- Docker container IP 확인
- 컨테이너 환경 nginx에서 컨테이너 환경의 다른 어플리케이션 접근을 위한 네트워크 구성
- install docker compose 공식문서
- 도커 컴포즈를 활용하여 완벽한 개발 환경 구성하기
- Docker Compose 커맨드 사용법
© 2023 debussysanjang
- 🐙 [가은] Three.js와의 설레는 첫만남
- 🐙 [가은] JS로 자전과 공전을 구현할 수 있다고?
- ⚽️ [준섭] NestJS 강의 정리본
- 🐧 [동민] R3F Material 간단 정리
- 👾 [재하] 만들면서 배우는 NestJS 기초
- 👾 [재하] GitHub Actions을 이용한 자동 배포
- ⚽️ [준섭] 테스트 코드 작성 이유
- ⚽️ [준섭] TypeScript의 type? interface?
- 🐙 [가은] 우리 팀이 Zustand를 쓰는 이유
- 👾 [재하] NestJS, TDD로 개발하기
- 👾 [재하] AWS와 NCP의 주요 서비스
- 🐰 [백범] Emotion 선택시 고려사항
- 🐧 [동민] Yarn berry로 모노레포 구성하기
- 🐧 [동민] Vite, 왜 쓰는거지?
- ⚽️ [준섭] 동시성 제어
- 👾 [재하] NestJS에 Swagger 적용하기
- 🐙 [가은] 너와의 추억을 우주의 별로 띄울게
- 🐧 [동민] React로 멋진 3D 은하 만들기(feat. R3F)
- ⚽️ [준섭] NGINX 설정
- 👾 [재하] Transaction (트랜잭션)
- 👾 [재하] SSH 보안: Key Forwarding, Tunneling, 포트 변경
- ⚽️ [준섭] MySQL의 검색 - LIKE, FULLTEXT SEARCH(전문검색)
- 👾 [재하] Kubernetes 기초(minikube), docker image 최적화(멀티스테이징)
- 👾 [재하] NestJS, 유닛 테스트 각종 mocking, e2e 테스트 폼데이터 및 파일첨부
- 2주차(화) - git, monorepo, yarn berry, TDD
- 2주차(수) - TDD, e2e 테스트
- 2주차(목) - git merge, TDD
- 2주차(일) - NCP 배포환경 구성, MySQL, nginx, docker, docker-compose
- 3주차(화) - Redis, Multer 파일 업로드, Validation
- 3주차(수) - AES 암복호화, TypeORM Entity Relation
- 3주차(목) - NCP Object Storage, HTTPS, GitHub Actions
- 3주차(토) - Sharp(이미지 최적화)
- 3주차(일) - MongoDB
- 4주차(화) - 플랫폼 종속성 문제 해결(Sharp), 쿼리 최적화
- 4주차(수) - 코드 개선, 트랜잭션 제어
- 4주차(목) - 트랜잭션 제어
- 4주차(일) - docker 이미지 최적화
- 5주차(화) - 어드민 페이지(전체 글, 시스템 정보)
- 5주차(목) - 감정분석 API, e2e 테스트
- 5주차(토) - 유닛 테스트(+ mocking), e2e 테스트(+ 파일 첨부)
- 6주차(화) - ERD
- 2주차(화) - auth, board 모듈 생성 및 테스트 코드 환경 설정
- 2주차(목) - Board, Auth 테스트 코드 작성 및 API 완성
- 3주차(월) - Redis 연결 후 RedisRepository 작성
- 3주차(화) - SignUpUserDto에 ClassValidator 적용
- 3주차(화) - SignIn시 RefreshToken 발급 및 Redis에 저장
- 3주차(화) - 커스텀 AuthGuard 작성
- 3주차(수) - SignOut시 토큰 제거
- 3주차(수) - 깃헙 로그인 구현
- 3주차(토) - OAuth 코드 통합 및 재사용
- 4주차(수) - NestJS + TypeORM으로 MySQL 전문검색 구현
- 4주차(목) - NestJS Interceptor와 로거
- [전체] 10/12(목)
- [전체] 10/15(일)
- [전체] 10/30(월)
- [FE] 11/01(수)~11/03(금)
- [전체] 11/06(월)
- [전체] 11/07(화)
- [전체] 11/09(목)
- [전체] 11/11(토)
- [전체] 11/13(월)
- [BE] 11/14(화)
- [BE] 11/15(수)
- [FE] 11/16(목)
- [FE] 11/19(일)
- [BE] 11/19(일)
- [FE] 11/20(월)
- [BE] 11/20(월)
- [BE] 11/27(월)
- [FE] 12/04(월)
- [BE] 12/04(월)
- [FE] 12/09(금)
- [전체] 12/10(일)
- [FE] 12/11(월)
- [전체] 12/11(월)
- [전체] 12/12(화)