[Openstack 스터디]3주차 - DevStack 인스턴스 생성 및 Docker Compose 기반 3-Tier 쇼핑몰 웹 서비스 배포


Ubuntu 인스턴스 생성을 위해 ubuntu-22.04.5-live-server-arm64.iso를 다운받은 후 대시보드에서 이미지를 생성하였다.
qcow2 이미지를 OpenStack에 등록하고 인스턴스(VM)를 생성하면, 별도의 우분투 설치 과정(언어 선택, 파티션 설정 등) 없이 부팅이 끝나자마자 바로 사용할 수 있는 완벽한 Ubuntu 상태가 된다고 한다.


보안을 위해 인스턴스는 외부와 격리된 Private 서브넷에 배치하였으며, 가상 라우터를 생성하여 Public 서브넷과 Private 서브넷 간의 가상 라우팅 및 NAT 환경을 구축하였다. 보안그룹은 SSH/HTTP 접근 허용 규칙을 추가하였다.

또한 Public 서브넷에 Floating IP를 생성하여 Private 인스턴스의 사설 IP와 1:1로 연결한 뒤 SSH 접속을 진행하였다.
실제 운영 환경에서는 보안 격리성을 유지하기 위해 인스턴스에 공인 IP를 직접 매핑하지 않고 Bastion Host를 경유하여 접속하는 것이 권장되나, 직접 실습할 때는 빠른 진행을 Floating IP를 직접 연결하는 방식으로 진행하였다.

version: '3.8'
services:
# -------------------------------------------------------------
# 1계층: 프론트엔드 Web Server (Nginx)
# -------------------------------------------------------------
web:
image: nginx:alpine
container_name: shopping-web
# OpenStack 보안 그룹에서 허용한 HTTP 80번 포트를 컨테이너와 매핑
ports:
- "80:80"
volumes:
- ./web/index.html:/usr/share/nginx/html/index.html
- ./nginx.conf:/etc/nginx/nginx.conf:ro
# 2계층 WAS 컨테이너가 먼저 구동된 후 Web 서버가 켜지도록 제어
depends_on:
- was
networks:
- shopping-network
# -------------------------------------------------------------
# 2계층: 백엔드 애플리케이션 WAS (Node.js)
# -------------------------------------------------------------
was:
image: node:18-alpine
container_name: shopping-was
volumes:
- ./was:/app
working_dir: /app
# 패키지 자동 설치 및 독립형 한글 방어 코드가 심어진 app.js 구동
command: sh -c "npm install && node app.js"
# 3계층 DB 컨테이너가 먼저 구동된 후 WAS가 켜지도록 제어
depends_on:
- db
networks:
- shopping-network
# -------------------------------------------------------------
# 3계층: 백엔드 데이터베이스 DB (MySQL)
# -------------------------------------------------------------
db:
image: mysql:8.0
container_name: shopping-db
environment:
# 외부 유출 방지를 위해 실제 운영 환경의 패스워드는 마스킹 처리합니다.
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD:-YOUR_ROOT_PASSWORD}
MYSQL_DATABASE: shopdb
MYSQL_USER: shopuser
MYSQL_PASSWORD: ${DB_PASSWORD:-YOUR_SHOP_USER_PASSWORD}
# 한글(utf8mb4) 규격을 유지하기 위한 인프라 설정 주입
volumes:
- ./my.cnf:/etc/mysql/conf.d/my.cnf:ro
networks:
- shopping-network
# 3개의 컨테이너가 서로 컨테이너 이름(도메인)으로 안전하게 통신할 수 있도록 독립 네트워크 격리
networks:
shopping-network:
driver: bridge
이후 인스턴스에 Docker 및 Docker Compose를 설치하였으며 Gemini를 통해 3-Tier 구조의 쇼핑몰 웹 서비스를 빌드 및 배포하였다.


브라우저에 접속하여 정상적으로 배포가 된 것을 확인하였다.
요청이 Web -> WAS -> DB로 이동하는 흐름 정리
1. 외부 사용자가 Public 서브넷에 생성된 Floating IP의 80번 포트로 접속하면, 가상 라우터가 NAT 기술을 통해 이를 Private 서브넷 내부 인스턴스의 사설 IP로 변환하여 전달한다.
2. 인스턴스 내부로 진입한 트래픽은 가장 먼저 호스트의 80번 포트를 대여한 최전방의 Web(Nginx) 컨테이너로 진입한다.
이후 요청은 Web에서 WAS(Node.js), 그리고 DB(MySQL) 순으로 순차적으로 이동하며 비즈니스 로직과 데이터 쿼리를 처리하게 된다.
이때 WAS(3000번)와 DB(3306번)는 오픈스택 보안그룹에서 해당 포트들을 외부에 개방하지 않았음에도 불구하고, 호스트의 물리 포트를 거치지 않는 독립된 '도커 가상 브릿지 네트워크' 내부망을 통해 서로 직접 통신하기 때문에 정상적인 데이터 교환이 가능하다.