-
VULTR에 docker(nginx+next.js) CI/CD 설정Server/클라우드서버(AWS,VULTR) 2025. 12. 14. 22:21

코드변경 → 자동으로 빌드 → 자동으로 서버 배포
CI / CD란?
CI (Continuous Integration)
CI = GitHub Actions에서 Docker build 하는 단계
코드가 합쳐질 때 자동으로 검증/빌드
지금 우리가 하는 CI 요소:
- GitHub에 코드 push / merge
- GitHub Actions 실행
- Docker 이미지 빌드
- 이미지 정상 생성 확인
CD (Continuous Deployment)
CD = 서버에 자동 배포하는 단계
검증된 결과물을 자동으로 서버에 반영
지금 우리가 하는 CD 요소:
- 빌드된 Docker 이미지를 GHCR(GitHub Container Registry, Docker 이미지를 저장하는 GitHub 공식 저장소)에 push
- Vultr 서버에서 최신 이미지 pull
- docker-compose로 컨테이너 재시작
- nginx 통해 즉시 서비스 반영
CI/CD 흐름
git push / PR merge ↓ [GitHub Actions] - Docker build (CI) - GHCR push ↓ [Vultr 서버] - docker pull - docker compose up -d (CD) ↓ [유저] 새 버전 서비스 이용0. 전제 조건 (이미 된것)
- Vultr 서버 생성됨
- Docker / docker-compose 설치됨
- nginx, next.js 모두 Docker로 올릴 예정
- GitHub 저장소 있음
1. 서버(Vultr)에서 "딱 한 번" 해야 할 것들
이건 GitHub Actions가 서버에 접속해서 배포할 수 있게 만드는 준비
1-1. 서버에 배포 디렉토리 생성
$ mkdir -p /app $ cd /app1-2. 서버에 GitHub Actions용 SSH Key 생성
# 전부 Enter $ ssh-keygen -t ed25519 -C "github-actions" # GitHub Actions 공개키 $ cat ~/.ssh/id_ed25519.pub # GitHub Actions 비공개키(GitHub에 설정해야함) $ cat ~/.ssh/id_ed255191-3. Vultr 서버에 "GitHub Actions 공개키" 추가
# GitHub Actions 공개키 확인 cat ~/.ssh/id_ed25519.pub # Vultr서버에서 생성한 GitHub Action 공개키 추가 $ vi ~/.ssh/authorized_keys # authorized_keys에 추가하고 나면 아래처럼 2개의 공개키가 있어야함 # Mac에서 Vultr에 접속하기 위한 공개키 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... your-mac-key # GitHub Actions가 Vultr에 접속하기 위한 공개키 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... github-actions-key2. GitHub 설정
자동 배포의 80%는 여기
2-1. GitHub Secrets 설정
GitHub 저장소에서
Settings → Secrets and variables → Actions → Repository secrets -> [New repository secret]아래 4개 추가 (필수 Repository secrets)
- VULTR_HOST: 서버 IP
- VULTR_USERNAME: root
- VULTR_SSH_KEY: id_ed25519 개인키 전체 내용
# 서버에서 cat ~/.ssh/id_ed25519 -----BEGIN OPENSSH PRIVATE KEY----- ... -----END OPENSSH PRIVATE KEY------ GH_PAT: GitHub Personal Access Token (아래 과정에서 생성된 ghp 토큰)
계정 → Settings → Developer settings → Personal access tokens → Tokens (classic) → Generate new token (classic) # Note ghcr-deploy (아무 이름이나 OK) # Expiration 30 days # 30 days (처음에 추천, 30일 이후에 새 토큰 생성하고 GH_PAT Secret값 교체해줘야함) # 또는 # No expiration (운영용, 영구 수동으로 삭제해야함) # Scopes(이게 핵심) write:packages read:packages → Generate token
ghp 생성 
2-2. GH_PAT 생성 참고
Docker 이미지를 GitHub Container Registry(GHCR)에 push 하기 위함
GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic)- 권한
- read:packages
- (push까지 할 거면 write:packageseh 체크)
생성 후 -> 토큰 값 복사 -> GH_PAT에 저장
3. 레포 구조
. ├─ docker-compose.yml ├─ nginx/ │ └─ default.conf ├─ nextjs/ │ ├─ Dockerfile │ └─ ... └─ .github/ └─ workflows/ └─ deploy.yml4. docker-compose.xml (서버에서 돌릴 최종 형태)
version: "3.8" services: nginx: image: nginx:alpine ports: - "80:80" volumes: - ./nginx/default.conf:/etc/nginx/conf.d/default.conf depends_on: - nextjs restart: always nextjs: image: ghcr.io/OWNER/REPO:latest restart: alwaysOWNER/REPO는 GitHub레포명으로 변경
5. GitHub Actions (자동 배포 핵심)
- .github/workflows/deploy.yml
name: Deploy Next.js on: push: branches: - master jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Login to GHCR run: echo ${{ secrets.GH_PAT }} | docker login ghcr.io -u USERNAME --password-stdin - name: Build & Push Image run: | docker build -t ghcr.io/OWNER/REPO:latest ./nextjs docker push ghcr.io/OWNER/REPO:latest - name: Deploy to Vultr uses: appleboy/ssh-action@v1.0.0 with: host: ${{ secrets.VULTR_HOST }} username: ${{ secrets.VULTR_USERNAME }} key: ${{ secrets.VULTR_SSH_KEY }} script: | cd /app docker pull ghcr.io/OWNER/REPO:latest docker compose down docker compose up -d6. 서버에 최초 1번만 할 작업
6.1. Github에 SSH keys 등록
- 서버 공개키 복사
# 서버 접속 및 서버 공개키 복사 $ cat ~/.ssh/id_ed25519.pub ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... vultr-server- GitHub에 공개키 등록
GitHub (우측 상단 프로필) → Settings → SSH and GPG keys → New SSH key6.2. 서버에서 clone 및 서버 동
$ cd /app $ git clone https://github.com/OWNER/REPO.git . $ docker compose up -d- master 브랜치에 push / merge
- GitHub Actions 실행
- Docker 이미지 빌드 -> GHCR push
- Vultr 서버 접속
- docker compose up -d
- 배포 완료
핵심 정리
- 서버 설정 딱 1번
- GitHub Secrets 딱 1번
- 이후엔 merge = 배포
참고)
- docker compose up -d 안될때
docker compose up -d unknown shorthand flag: 'd' in -d Usage: docker [OPTIONS] COMMAND [ARG...] Run 'docker --help' for more information- docker compose로 통일하려면
# STEP 1. 필수 패키지 설치 $ sudo apt update $ sudo apt install -y ca-certificates curl gnupg # STEP 2. Docker 공식 GPG 키 등록 $ sudo mkdir -p /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 # STEP 3. Docker 공식 APT 저장소 추가 $ echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \ https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable" \ | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null # STEP 4. 패키지 목록 갱신 $ sudo apt update # STEP 5. docker-compose-plugin 설치 $ sudo apt install -y docker-compose-plugin # (선택) docker-compose(v1) 완전 제거 $ sudo apt remove -y docker-compose $ sudo rm -f /usr/bin/docker-compose최종 확인
- GitHub Actions

푸시하면 Git Actions의 workflow가 실행된다. - Deploy 에러 확인

deploy 과정을 확인 할 수 있다. - 필자는 authorized_keys에 GitHub Actions에서 Vultr에 접속하기 위한 공개키가 추가되어 있지 않아서 추가하고 빌드에 성공하였다.

성공 - 소스 정리하고 다시 테스트 (아래처럼 하고 push해서 배포되는지 확인)
# 기존 컨테이너 중지 $ docker compose down # 기존 git clone 파일들 삭제 (nginx 설정 등이 새로 복사됨) $ rm -rf /app/*'Server > 클라우드서버(AWS,VULTR)' 카테고리의 다른 글
VULTR 서버에 인증서 설정하기 (0) 2025.12.15 VULTR 서버 사용하기 (1) 2025.12.14 Node.js 애플리케이션 관리 프로세스 매니저, pm2란? (1) 2024.12.06 RDS 현재 활동 사용자 확인 및 타임아웃 설정 (0) 2024.12.02 [AWS] RDS timezone 변경 (0) 2024.07.19