본문 바로가기

[IT/Programming]

Linux (AWS Amazon Linux) 에 git 설치 및 nginx 설치 (초기 세팅들), Docker (Dockerfile and .dockerignore) and CI/CD GitHub Action (main.yml)

반응형
# Linux (AWS Amazon Linux) 에 git 설치 및 nginx 설치 (초기 세팅들), Docker (Dockerfile and .dockerignore) and GitHub Action (main.yml) EC2 로 인스턴스 생성 (AWS Amazon Linux) free tier 로. Amazon Linux 에 접속 .ssh 이용. (public IP 는 재부팅시 항상 바뀌기 때문에 돈을 내고 Elastic IP 를 이용하는게 좋긴 함.) 아래와 같이 터미널/cmd 창에서 EC2 로 접속. 43.202.97.246 ```[.linenums.lang-sh] # FE ssh -i "codeit-fs-key.pem" ec2-user@ec2-43-202-97-246.ap-northeast-2.compute.amazonaws.com # BE ssh -i "fitmate-be.pem" ec2-user@ec2-15-164-195-136.ap-northeast-2.compute.amazonaws.com ```/ ## PH
  • 2024-12-31 : First posting.
## TOC ## Git 및 Nginx 설치 ```[.linenums.lang-sh] sudo yum update -y sudo yum install git sudo yum install nginx # Amazon Linux sudo apt install nginx -y # Ubuntu (WSL) ```/ Git clone 하기. (Open Source 라서 따로 사용자 및 비번을 넣지 않아도 됨.) ```[.linenums.lang-sh] git clone https://github.com/FS-part4-1team-FitMate/FitMate-FE.git # 특정 branch 로 pull 하기. git branch git checkout Feat-kipid git pull origin Feat-kipid ```/ ## Windows 11 의 Local WSL (Windows Subsystem for Linux) 에서 Back-End 실행하기 ```[.linenums.lang-sh] wsl # Ubuntu 접속 cd ~ # Home directory 로 이동 git clone https://github.com/FS-part4-1team-FitMate/FitMate-BE.git # Clone Back-End repo git pull npx prisma migrate reset npx prisma migrate dev npm run seed npm run build npm run start ```/ ```[.linenums.lang-sh] ip addr show eth0 # ip 확인 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000 link/ether 00:15:5d:84:de:a6 brd ff:ff:ff:ff:ff:ff inet 172.21.104.225/20 brd 172.21.111.255 scope global eth0 valid_lft forever preferred_lft forever inet6 fe80::215:5dff:fe84:dea6/64 scope link valid_lft forever preferred_lft forever # 위와 같이 뜨면 localhost:3000 이 아니라 172.21.104.225:3000 으로 연결해야 함. # Front-End 의 .env 에서 NEXT_PUBLIC_API_URL="http://172.21.104.225:3000" 으로 설정해줘야 함. # wsl --shutdown 후 # wsl 로 접속해야 ip 들이 재설정 되는듯? # PostgreSQL 이 Windows 에서 돌아가고 있을거기 때문에. # BE 의 .env 의 DATABASE_URL="postgresql://..." 도 바꿔줘야 함. # cmd 창에서 ipconfig 쳤을때 나오는 Windows ip 로. DATABASE_URL="postgresql://postgres:[Password]@[Windows local ip address]:5432/fitmate_dev?schema=public" # 방화벽 확인 sudo ufw status Status: active To Action From -- ------ ---- 80/tcp ALLOW Anywhere 443/tcp ALLOW Anywhere 22/tcp ALLOW Anywhere 3000 ALLOW Anywhere 3001/tcp ALLOW Anywhere 80/tcp (v6) ALLOW Anywhere (v6) 443/tcp (v6) ALLOW Anywhere (v6) 22/tcp (v6) ALLOW Anywhere (v6) 3000 (v6) ALLOW Anywhere (v6) 3001/tcp (v6) ALLOW Anywhere (v6) # 와 같이 떠야 함. sudo ufw allow 3000/tcp # 와 같이 Back-End port 를 허용해줘야 할 수 있음. ```/ ## Windows 11 의 Local WSL (Windows Subsystem for Linux) 에서 Front-End 실행하기 ```[.linenums.lang-sh] wsl # Ubuntu 접속 cd ~ # Home directory 로 이동 git clone https://github.com/FS-part4-1team-FitMate/FitMate-BE.git # Clone Back-End repo git pull git checkout Feat-kipid # 자신의 branch 로 들어가야 자기가 작업한 것들을 불러올 수 있음. git pull npm run build npm run start ```/ ```[.linenums.lang-sh] ip addr show eth0 # ip 확인 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000 link/ether 00:15:5d:84:de:a6 brd ff:ff:ff:ff:ff:ff inet 172.21.104.225/20 brd 172.21.111.255 scope global eth0 valid_lft forever preferred_lft forever inet6 fe80::215:5dff:fe84:dea6/64 scope link valid_lft forever preferred_lft forever # 위와 같이 뜨면 localhost:3001 이 아니라 172.21.104.225:3001 으로 연결해야 함. (어쩔땐 그냥 localhost:3001 로도 접속이 되긴 했는데, 컴퓨터를 껐다 키니까 안됨 ㅡ,.ㅡ;;) ```/ ## Docker 설치 방법 (Amazon Linux 2) ```[.linenums.lang-sh] sudo yum update -y # Amazon Linux 2 sudo yum install -y docker sudo systemctl enable docker sudo systemctl start docker sudo systemctl status docker docker ps docker images ```/ Docker 만 깔면 Node.js 및 pm2 설치는 넘어가도 됨. Dockerfile 을 다음과 같이 작성. ```[.linenums.lang-sh] # Use the official Node.js LTS image for building FROM node:lts AS builder # Set working directory WORKDIR /app ARG NEXT_PUBLIC_KAKAO_API_KEY ENV NEXT_PUBLIC_API_URL="https://fitmate-be.asia" ENV NODE_ENV="production" ENV NEXT_PUBLIC_KAKAO_API_KEY=${NEXT_PUBLIC_KAKAO_API_KEY} # Install dependencies (only production deps for runtime) COPY package.json package-lock.json ./ RUN npm ci # Copy the rest of the application files COPY . . # Build the Next.js app RUN npm run build # Use a minimal runtime image FROM node:lts AS runtime # Create a non-root user # RUN addgroup -S appgroup && adduser -S appuser -G appgroup # Set working directory WORKDIR /app # pm2 글로벌 설치 RUN npm install -g pm2 # Copy necessary files from the builder stage COPY --from=builder /app/package.json /app/package-lock.json ./ COPY --from=builder /app/.next ./.next COPY --from=builder /app/public ./public COPY --from=builder /app/node_modules ./node_modules # Ensure correct permissions # RUN chown -R appuser:appgroup /app # Switch to non-root user # USER appuser # 환경 변수 설정 ENV NEXT_PUBLIC_API_URL="https://fitmate-be.asia" ENV NODE_ENV="production" ENV PORT=3001 # Expose application port EXPOSE 3001 # Define runtime command CMD ["pm2-runtime", "start", "npm", "--", "start"] ```/ .dockerignore 도 다음과 같이 작성. ```[.linenums.lang-sh] # 운영체제 파일 .DS_Store Thumbs.db # Node.js 관련 파일 (예: 로컬 개발 환경에서 설치된 모듈) node_modules/ .next/ .github/ .git/ # 빌드 아티팩트 dist/ build/ # 로그 파일 *.log # 기타 불필요한 파일 *.md *.txt Dockerfile ```/ 다음과 같은 명령어들로 Docker 실행. HTTPS 설정이랑 Nginx 설정은 따로 해줘야 함. ```[.linenums.lang-sh] # 1. Docker 이미지 빌드 (빌드는 Local 컴퓨터에서 하는게 좋아보임. 서버 성능이 좋지 않다면 특히나...) docker login # https://hub.docker.com/ 의 ID/Password 를 입력해야 함. # .env 를 production 에 맞춰서 바꿔준 뒤, build 해야 함. docker build -t kipid/fitmate-fe:v0.2 . docker push kipid/fitmate-fe:v0.2 # 2. 컨테이너 실행 (EC2 에 터미널로 연결해서) docker login # https://hub.docker.com/ 의 ID/Password 를 입력해야 함. docker images # 안쓰는 이미지 삭제 docker stop $(docker ps -aq) docker system prune -a docker rmi <이미지 ID 또는 이미지 이름> docker pull kipid/fitmate-fe:v0.2 docker stop fitmate-fe-container docker rm fitmate-fe-container docker run -d -p 3001:3001 --name fitmate-fe-container kipid/fitmate-fe:v0.2 docker run -d -p 3001:3001 --name fitmate-fe-container \ -e "NEXT_PUBLIC_API_URL='https://fitmate-be.asia'" \ -e "NODE_ENV='production'" \ -e "NEXT_PUBLIC_KAKAO_API_KEY='83c6b0fde64b363bd52e26fd41f2fbd6'" \ kipid/fitmate-fe:v0.2 # Nginx 시작 sudo systemctl start nginx # Docker 중단 docker stop <컨테이너_ID 또는 컨테이너_이름> ```/ ## CI/CD (Continuous Integration, Continuous Delivery/Deployment) .github/workflows/main.yml 파일에 다음과 같이 입력하고 저장 and Git push Settings - Secrets and variables - Actions - Repository secrets 에 New repository secret 에다 비번같은걸 등록해야 함! Environment secrets 이 아님! 이걸로 한참 고생함. Organization secrets 도 아님. ```[.linenums.lang-sh] name: CI/CD Pipeline # 워크플로우의 이름을 'CI/CD Pipeline'으로 설정 on: # 워크플로우 트리거 조건 설정 push: # Git push 이벤트 발생 시 실행 branches: ["Feat-kipid"] # Feat-kipid 브랜치에 push가 발생했을 때만 실행 jobs: # 실행할 작업들을 정의하는 섹션 build-and-deploy: # 작업 이름을 'build-and-deploy'로 설정 runs-on: ubuntu-latest # Ubuntu 최신 버전의 러너에서 작업 실행 steps: # 작업의 세부 단계들을 정의 - name: Checkout code # 코드 체크아웃 단계 uses: actions/checkout@v3 # GitHub 저장소 코드를 가져오는 공식 액션 사용 - name: Build Docker image # Docker 이미지 빌드 단계 env: DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} run: | echo "$DOCKER_PASSWORD" | docker login --username "$DOCKER_USERNAME" --password-stdin # Docker Hub 로그인 (보안을 위해 secrets 사용) docker --version sleep 3 docker build \ --build-arg "NEXT_PUBLIC_API_URL=https://fitmate-be.asia" \ --build-arg "NODE_ENV=production" \ --build-arg "NEXT_PUBLIC_KAKAO_API_KEY=${{ secrets.NEXT_PUBLIC_KAKAO_API_KEY }}" \ -t kipid/fitmate-fe:v0.2 . || exit 1 # Dockerfile을 사용하여 이미지 빌드, 태그는 v0.2로 지정 sleep 3 docker push kipid/fitmate-fe:v0.2 # 빌드된 이미지를 Docker Hub에 업로드 sleep 3 docker logout continue-on-error: false - name: Deploy to server # 서버 배포 단계 uses: appleboy/ssh-action@master env: DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} with: host: ${{ secrets.SERVER_IP }} username: ${{ secrets.SERVER_USERNAME }} key: ${{ secrets.SERVER_PRIVATE_KEY }} port: 22 script: | echo "$DOCKER_PASSWORD" | docker login --username "$DOCKER_USERNAME" --password-stdin docker pull kipid/fitmate-fe:v0.2 # 최신 이미지 다운로드 docker stop $(docker ps -a -q) || true docker rm -f $(docker ps -a -q) || true docker stop fitmate-fe-container || true # 기존 컨테이너 중지 (실패해도 계속 진행) docker rm fitmate-fe-container || true # 기존 컨테이너 제거 (실패해도 계속 진행) docker run -d -p 3001:3001 --name fitmate-fe-container \ -e "NEXT_PUBLIC_API_URL=https://fitmate-be.asia" \ -e "NODE_ENV=production" \ -e "NEXT_PUBLIC_KAKAO_API_KEY=${{ secrets.NEXT_PUBLIC_KAKAO_API_KEY }}" \ kipid/fitmate-fe:v0.2 sleep 5 # 컨테이너 실행 안정화 대기 docker system prune -f # 사용하지 않는 Docker 리소스 정리 sleep 3 ps -ef | grep docker # Check running processes docker logout ```/ Settings - Secrets and variables - Actions 들어가서 Environment secrets 저장해주면 끝. ## Node.js 설치 ```[.linenums.lang-sh] curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash nvm install --lts ```/ ## Redis server 띄우기 Redis server 까는 법은 ChatGPT 에게 문의. ```[.linenums.lang-sh] redis-server --daemonize yes redis-cli ping # Expected PONG ```/ ## pm2 start package.json 은 다음과 같이.. port 3001 로 start. ```[.linenums.lang-sh] "scripts": { "dev": "next dev -p 3001", "build": "next build", "start": "next start -p 3001", "lint": "next lint" }, ```/ ```[.linenums.lang-sh] npm i pm2 -g npm run build pm2 start "npm run start" pm2 start npm -- name 'my-app' -- start "pm2:start": "pm2 start npm -- name 'my-app' -- start" // npm run pm2:start pm2 list pm2 stop 0 pm2 restart 0 pm2 delete 0 and so on. ```/ ## HTTPS 연결로 만들기 및 Nginx 설정 ```[.linenums.lang-sh] sudo yum install -y certbot sudo certbot certonly --standalone -d fitmate.asia sudo certbot certonly --standalone -d fitmate-be.asia ```/ 성공적으로 인증서를 발급받으면 /etc/letsencrypt/live/fitmate.asia/ 에 인증서 파일이 저장됨. ```[.linenums.lang-sh] # Nginx 설정 파일 편집 sudo vi /etc/nginx/nginx.conf sudo vi /etc/nginx/conf.d/fitmate.asia.conf sudo vi /etc/nginx/conf.d/fitmate-be.asia.conf ```/ ```[.linenums.lang-sh] server { listen 80; server_name fitmate.asia www.fitmate.asia; # Redirect HTTP to HTTPS return 301 https://$host$request_uri; } server { listen 443 ssl; server_name fitmate.asia www.fitmate.asia; ssl_certificate /etc/letsencrypt/live/fitmate.asia/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/fitmate.asia/privkey.pem; location / { proxy_pass http://localhost:3000; # 애플리케이션 포트 proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; } } ```/ ```[.linenums.lang-sh] server { listen 80; server_name fitmate-be.asia www.fitmate-be.asia; # Redirect HTTP to HTTPS return 301 https://$host$request_uri; } server { listen 443 ssl; server_name fitmate-be.asia www.fitmate-be.asia; ssl_certificate /etc/letsencrypt/live/fitmate-be.asia/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/fitmate-be.asia/privkey.pem; location / { proxy_pass http://localhost:3001; # 애플리케이션 포트 proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; } } ```/ 전체 파일을 들여다 보면 다음과 같음. ```[.linenums.lang-sh] # For more information on configuration, see: # * Official English Documentation: http://nginx.org/en/docs/ # * Official Russian Documentation: http://nginx.org/ru/docs/ user nginx; worker_processes auto; error_log /var/log/nginx/error.log notice; pid /run/nginx.pid; # Load dynamic modules. See /usr/share/doc/nginx/README.dynamic. include /usr/share/nginx/modules/*.conf; events { worker_connections 1024; } http { log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; tcp_nopush on; keepalive_timeout 65; types_hash_max_size 4096; include /etc/nginx/mime.types; default_type application/octet-stream; # Load modular configuration files from the /etc/nginx/conf.d directory. # See http://nginx.org/en/docs/ngx_core_module.html#include # for more information. include /etc/nginx/conf.d/*.conf; server { listen 80; listen [::]:80; server_name fitmate.asia www.fitmate.asia; root /usr/share/nginx/html; # Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; # Redirect HTTP to HTTPS return 301 https://$host$request_uri; error_page 404 /404.html; location = /404.html { } error_page 500 502 503 504 /50x.html; location = /50x.html { } } # Settings for a TLS enabled server. server { listen 443 ssl; listen [::]:443 ssl; http2 on; server_name fitmate.asia www.fitmate.asia; root /usr/share/nginx/html; ssl_certificate "/etc/letsencrypt/live/fitmate.asia/fullchain.pem"; ssl_certificate_key "/etc/letsencrypt/live/fitmate.asia/privkey.pem"; ssl_session_cache shared:SSL:1m; ssl_session_timeout 10m; ssl_ciphers PROFILE=SYSTEM; ssl_prefer_server_ciphers on; # Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; location / { proxy_pass http://localhost:3001; # 애플리케이션 포트 proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; } error_page 404 /404.html; location = /404.html { } error_page 500 502 503 504 /50x.html; location = /50x.html { } } } ```/ ```[.linenums.lang-sh] sudo systemctl start nginx sudo vi /etc/nginx/nginx.conf ============================ server { listen 80 ...... location / { proxy_pass http://127.0.0.1:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } ============================ sudo nginx -t sudo systemctl restart nginx ```/ ## Typescript of APIspec ```[.linenums.lang-sh] export type APISpec<BU = any, P = any, B = any, T = any> = { method: 'GET' | 'POST' | 'PATCH' | 'DELETE' baseURL: BU path: P body?: B response: T } export type APISpecs< T extends { [K in string]: APISpec } > = T export type ProductAPI = APISpecs<{getProducts: { method: 'GET', baseURL: 'http://localhost:3100', path: '/products' response: Product[] }}> ```/ ## ESLint 무효화 ```[.linenums.lang-sh] // eslint-disable-next-line @typescript-eslint/no-explicit-any ```/ ## RRA
  1. https://www.docker.com/
반응형

'[IT/Programming]' 카테고리의 다른 글

12월 30일 2기 위클리 페이퍼 - 테스트의 필요성을 설명하세요. 본인이 생각하는 좋은 테스트란 무엇인지 설명해주세요.  (0) 2025.01.06
12월 23일 2기 위클리 페이퍼 - VPC는 무엇이며, 왜 중요한가요? S3 버킷의 사용 사례와 주의할 점은 무엇인가요? IAM은 무엇이며, 어떤 기능을 제공하나요?  (0) 2024.12.24
12월 16일 2기 위클리 페이퍼 - AWS의 글로벌 instructure에는 어떤 구성 요소들이 포함되어 있나요? EC2 인스턴스란 무엇이며, 어떻게 사용하나요?  (2) 2024.12.18
12월 09일 2기 위클리 페이퍼 - TypeScript의 동작 원리에 대해 설명해 주세요. d.ts 타입 정의파일이 무엇이며, 어떻게 만들 수 있는지 설명하세요.  (3) 2024.12.10
코드잇 풀스택 2기 - Part 3 - 중급프로젝트 - Docthru  (1) 2024.12.06
11월 11일 2기 위클리 페이퍼 - MVC(Model-View-Controller) 패턴이란 무엇인가요? 이 패턴의 각 구성 요소의 역할을 설명하고, MVC 패턴을 사용하는 이유와 그 장점에 대해 서술해주세요. OAuth란 무엇인가요? 그리고 왜 사용하는지 설명해주세요.  (1) 2024.11.15
11월 04일 2기 위클리 페이퍼 - 경험을 바탕으로 React 애플리케이션에서 JSON Web Token(JWT)을 사용하여 사용자 인증 시스템을 구현하는 방법에 대해 자세히 설명해주세요. 특히 로그아웃 구현 로직에 대해 설명해주세요. RESTful API의 개념과 주요 제약 조건을 설명하세요.  (3) 2024.11.11