1. 글의 목적
이번 글에서는 직접 웹서버를 해보고 싶어서 배포에 대해서 공부하다가 blue-green 배포가 있다고 해서 직접 실습을 해보고 정리하려고 한다.
2. blue-green 배포가 무엇일까?
Blue-Green 배포는 운영 중인 서버와 동일한 사양의 새로운 서버 세트를 하나 더 구축하여, 배포 시점에 트래픽을 한꺼번에 전환하는 방식입니다. 구 버전과 신 버전을 각각 Blue와 Green이라는 이름의 환경으로 정의하고 번갈아 가며 서비스를 제공합니다.
✅ 핵심 동작 원리
- Blue(기존): 현재 실제 사용자가 접속하여 서비스가 운영되고 있는 환경 (v1)
- Green(신규): 새롭게 배포할 코드가 설치된 환경 (v2). 사용자 트래픽이 아직 유입되지 않은 상태.
- 검증: Green 환경에서 내부 테스트를 진행하여 신규 버전에 문제가 없는지 최종 확인합니다.
- 전환(Switch): 로드 밸런서(Load Balancer)나 라우터 설정을 변경하여 사용자 트래픽을 Blue에서 Green으로 일시에 옮깁니다.
- 대기 및 롤백: 배포가 완료된 후 Blue는 즉시 삭제하지 않고 대기시킵니다. 만약 Green에서 치명적인 버그가 발견되면 즉시 트래픽을 다시 Blue로 돌려 원상복구합니다.
📊 Blue-Green 배포의 장단점
| 구분 | 장점 | 단점 |
| 가용성 | Zero Downtime: 트래픽 전환이 순식간에 일어나 서비스 중단이 거의 없습니다. | 비용 부담: 동일한 사양의 서버 인프라가 2배로 필요하여 비용이 많이 듭니다. |
| 안정성 | 빠른 롤백: 문제 발생 시 라우팅만 다시 바꾸면 즉시 이전 버전으로 복구됩니다. | DB 동기화: 신구 버전이 동일한 DB를 바라볼 때 데이터 스키마 변경 시 관리가 어렵습니다. |
| 테스트 | 환경 격리: 운영 환경과 동일한 조건에서 최종 테스트 후 배포할 수 있습니다. | 복잡한 설정: 로드 밸런서와 네트워크 전환 설정에 대한 자동화가 필요합니다. |
(설명 by gemini)
3. 사용한 기술스택 & 디렉토리 경로
서버: lightsnail Ubuntu 24.04.3 LTS
Docker 29.1.4
Docker Compose version v5.0.1
CI: github Actions
간단한 웹서버: nodejs 22, express ^5.2.1
디렉터리 구조
blue-green-test/
├──.github/workflows/deploy.yml
├── Dockerfile
├── app.js
└── package.json
4. 서버 초기 설정
sudo apt update
curl -fsSL https://get.docker.com | sudo sh
sudo apt install docker-compose-plugin -y
sudo apt install nginx -y
sudo usermod -aG docker ubuntu
exit
SSH 재접속 필수
groups
sudo mkdir -p /srv/blue-green
sudo chown ubuntu:ubuntu /srv/blue-green
groups에 docker가 있어야 함
sudo nano /etc/nginx/sites-available/bluegreen
nano 를 쓰던 vim을 쓰던 마음대로!
server {
listen 80;
location / {
proxy_pass http://localhost:3001; # blue
}
}
이렇게 적고
sudo ln -s /etc/nginx/sites-available/bluegreen /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl restart nginx
실행
4-1. github Actions에서 접속할 SSH 키 만들기
ssh-keygen -t ed25519 -f lightsail_ci
cat lightsail_ci.pub >> ~/.ssh/authorized_keys
를 통해 ssh키를 등록해둔다. 주의할점은 SSH 키를 만들때 passphrase는 입력하지 않으면 된다.
cat lightsail_ci
를 입력하여 -----BEGIN OPENSSH PRIVATE KEY----- 로 시작하여 -----END OPENSSH PRIVATE KEY-----로 끝나는 값을 전체 복사하여 안전하게 보관해두자. 반드시 -----BEGIN OPENSSH PRIVATE KEY----- 같은 구문도 포함해야 한다!
5. docker hub / github Acions 기초 설정
Docker Hub Container Image Library | App Containerization
Software supply chain Secure Your Supply Chain with Docker Hardened Images Use Docker's enterprise-grade base images: secure, stable, and backed by SLAs for Ubuntu, Debian, Java, and more. Regularly scanned and maintained with CVE remediation and long-term
hub.docker.com
docker hub에 접속해서 계정 만들기.
https://hub.docker.com/repositories 에서


레포지토리를 만들되 이름을 blue-green-test으로 해주기!
생성후 액세스 토큰을 발급받자.



오른쪽 위 자신 프로필을 클릭후 Account settings에 들어간후 PAT섹션 클릭후 오른쪽위의 access token만들기를 클릭후 Access permissions을 Read & Write로 만든후 만들어진 토큰을 잘 보관하자.

그후 github 레포로 이동해서 Setting-Secrets and variables-Actions에 들어가서 다음과 같은 것을 설정해주자.
DOCKER_PASSWORD - 조금 전에 발급받은 PAT
DOCKER_USERNAME - dokcer에 가입할때 입력한 username
SERVER_IP - 서버의 ip주소
SERVER_USER - 서버에서의 user (기본적으로 ubuntu 일 것이다)
SSH_KEY - 4-1에서 만든 ssh키
6. 코드 적기
// app.js
const express = require("express");
const app = express();
const COLOR = process.env.COLOR || "unknown";
app.get("/", (req, res) => {
res.send(`Hello from ${COLOR}`);
});
app.listen(3000, () => {
console.log(`Server running on ${COLOR}`);
});
app.js에 다음과 같이 적고 (package.json은 알잘딱깔센하게)
FROM node:22
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "app.js"]
Dockerfile에는 다음과 같이 적고
name: Deploy
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Docker build
run: docker build -t ${{ secrets.DOCKER_USERNAME }}/blue-green-test:latest .
- name: Docker login
run: echo ${{ secrets.DOCKER_PASSWORD }} | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin
- name: Docker push
run: docker push ${{ secrets.DOCKER_USERNAME }}/blue-green-test:latest
- name: SSH Deploy
uses: appleboy/ssh-action@v0.1.6
with:
host: ${{ secrets.SERVER_IP }}
username: ubuntu
key: ${{ secrets.SSH_KEY }}
script: |
cd /srv/blue-green
docker pull ${{ secrets.DOCKER_USERNAME }}/blue-green-test:latest
docker compose up -d
.github/workflows/deploy.yml에 이렇게 적자.
아직 코드는 push하지 말자.
7. docker compose 설정
서버에서 /srv/blue-green경로로 이동한 후
nano docker-compose.yml
를 입력하여 파일을 열어 수정모드로 전환후
services:
blue:
image: your-id/blue-green-test:latest # 본인의 Docker ID로 수정하세요
container_name: blue
environment:
- COLOR=blue
ports:
- "3001:3000"
green:
image: your-id/blue-green-test:latest # 본인의 Docker ID로 수정하세요
container_name: green
environment:
- COLOR=green
ports:
- "3002:3000"
을 적는다. your-id부분에 자신의 docker id를 적자.
저장을 하는것도 잊지 말자.
8. 코드 push 및 실행
아까 작성했던 코드를 push하면 github Actions가 실행될것이다. github의 Actions탭에서 확인해보자. 체크표시가 나왔다면 브라우저를 통해 주소창에 자신의 서버 ip주소를 입력하면 Hello from blue가 나올것 이다. 그럼 잘 된 것이다.
이후
curl -f http://localhost:3002
를 통해 헬스체크를 하여 켜져있는지 확인 후
sudo nano /etc/nginx/sites-available/bluegreen
를 사용하여 proxy_pass http://localhost:3001; 부분을 proxy_pass http://localhost:3002; 로 바꿔보자. 그후
sudo systemctl reload nginx
를 하여 nginx를 다시 켜주고 들어가면 Hello from green이 나올것이다. 그럼 잘 된 것이다.
9. 마무리
간단하게 blue-green배포가 어떻게 이루어지는 지 실습을 해보았다. 처음해서 많이 서툴고 에러를 보면 당황했지만 한 단계씩 진행할때마다 재밌었다. 다음 편에는 blue-green 버전 나누기, 롤백, 실행 자동화 등을 실습해보며 더 고급 실습을 해보려고 한다.
'프로그래밍 > 개발 일지' 카테고리의 다른 글
| [MS OAuth + Xbox Live] Xbox OAuth 인증 구현하기 (0) | 2026.03.14 |
|---|---|
| [CD/CI] blue-green 배포 공부해보기 2 (1) | 2026.01.14 |
| [Electron + Vite] 환경 설정과 트러블슈팅 가이드 (7) | 2025.08.11 |
| [Next.js App Router] lucide-react ESM 문제 해결하며 Jest 테스트 도입기 (1) | 2025.06.18 |
| [Supabase + Next.js App Router] 구글 OAuth 구현하기 (SSR 기반 세션관리 포함) (2) | 2025.06.15 |