아키텍쳐 설계 관련 글/서버,인프라

레거시 WAS & Nginx를 Docker로 현대화하기: 마이그레이션 A to Z 가이드

recording or reCoding 2025. 7. 10. 09:18

안녕하세요! 오늘은 기존 서버에서 운영 중이던 WAS(Tomcat)와 Nginx를 새로운 서버로 이관하면서, 더 나아가 Docker 컨테이너 환경으로 구축하는 전체 과정을 공유하고자 합니다. 이 가이드를 통해 의존성 문제에서 벗어나고, 배포를 자동화하며, 서버 환경을 코드(IaC)로 관리하는 첫걸음을 뗄 수 있을 겁니다.

왜 Docker로 마이그레이션해야 할까?

서버에 직접 Nginx나 Tomcat을 설치하는 방식은 익숙하지만, 다음과 같은 어려움이 있습니다.

  • 의존성 지옥: 서버의 OS나 라이브러리 버전에 따라 애플리케이션이 오작동할 수 있습니다.
  • 환경 불일치: 개발, 테스트, 운영 서버의 환경이 달라 예상치 못한 버그가 발생합니다.
  • 이관의 어려움: 지금 우리가 하려는 것처럼, 서버를 옮길 때마다 모든 설정을 수동으로 다시 해야 합니다.

Docker는 이러한 문제들을 컨테이너라는 격리된 환경에 애플리케이션과 그 실행 환경을 함께 패키징하여 해결합니다. 이제 지긋지긋한 수동 설정에서 벗어나 보시죠!


목차

  1. 1단계: 기존 서버 환경 분석하기 (AS-IS)
  2. 2단계: 새로운 서버에 Docker 환경 구축하기 (TO-BE)
  3. 3단계: Docker Compose로 WAS와 Nginx 함께 띄우기
  4. 4단계: DNS 설정 및 최종 테스트

1단계: 기존 서버 환경 분석하기 (AS-IS)

성공적인 마이그레이션의 첫 단추는 현재 시스템을 정확히 파악하는 것입니다. 기존 서버에 접속해서 다음 정보들을 수집해 봅시다.

1.1. Nginx 정보 확인

1) Nginx 버전 확인
Nginx의 버전에 따라 설정 가능한 옵션이 다를 수 있으므로 버전을 확인합니다.

# Nginx 버전 확인 명령어
nginx -v

# 출력 예시
# nginx version: nginx/1.18.0 (Ubuntu)

 

2) Nginx 실행 포트 및 설정 파일 경로 확인
어떤 포트로 서비스되고 있는지, 그리고 설정 파일이 어디 있는지 확인해야 합니다.

# 현재 실행 중인 Nginx 프로세스 확인
ps -ef | grep nginx

# 네트워크 포트 확인 (80, 443 포트를 사용 중인 프로세스가 nginx인지 확인)
# -n: 숫자 주소로 표시, -l: LISTEN 상태 소켓, -p: 프로세스 정보, -t: TCP
sudo netstat -nlpt | grep nginx

# nginx 설정 파일 문법을 검사하며 경로를 알려주는 가장 확실한 방법!
sudo nginx -t

# 출력 예시
# nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
# nginx: configuration file /etc/nginx/nginx.conf test is successful

위 명령어를 통해 제 Nginx 설정 파일이 /etc/nginx/nginx.conf에 있다는 것을 확인했습니다.

1.2. Nginx 핵심 설정 분석 (nginx.conf 또는 sites-available/default)

이제 가장 중요한 Nginx 설정 파일을 열어 어떤 내용이 있는지 분석합니다. 특히 WAS로 요청을 넘겨주는 proxy_pass 부분을 유심히 봐야 합니다.

# 설정 파일 내용 확인
cat /etc/nginx/sites-available/default # 또는 nginx -t 로 찾은 경로

 

핵심 설정 예시 및 설명

server {
    # 80번 포트로 들어오는 HTTP 요청을 수신
    listen 80;
    
    # 이 서버 블록이 처리할 도메인 이름
    server_name my-service.com;

    # / (루트 경로)로 들어오는 모든 요청을 처리
    location / {
        # 이 부분이 핵심! 모든 요청을 http://127.0.0.1:8080 으로 전달합니다.
        # 즉, 내부적으로 8080 포트에서 실행 중인 WAS(Tomcat)로 연결합니다.
        proxy_pass http://127.0.0.1:8080; 
        
        # 클라이언트의 실제 IP를 WAS에 전달하기 위한 헤더 설정
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
    }
}

1.3. WAS (Tomcat) 정보 확인

1) Tomcat 버전 확인
Tomcat 설치 경로의 bin 폴더에서 버전 확인 스크립트를 실행합니다.

# Tomcat 설치 경로로 이동 (경로는 다를 수 있음)
cd /usr/local/tomcat/bin

# 버전 확인 스크립트 실행
./version.sh

# 출력 예시
# Using CATALINA_BASE:   /usr/local/tomcat
# Using CATALINA_HOME:   /usr/local/tomcat
# ...
# Server version: Apache Tomcat/9.0.50

 

2) 배포된 WAS 애플리케이션(WAR 파일) 확인
보통 webapps 디렉터리에 배포된 애플리케이션 파일(ROOT.war 또는 my-app.war)이 있습니다. 이 파일을 새로운 서버로 가져와야 합니다.

Generated bash

ls -l /usr/local/tomcat/webapps

1.4. SSL 인증서 이관 (HTTPS 사용 시)

만약 HTTPS(443 포트)를 사용하고 있다면 SSL 인증서 파일(.pem, .crt, .key)도 가져와야 합니다. Nginx 설정 파일에서 ssl_certificate ssl_certificate_key 지시어를 찾아 경로를 확인하세요.

# nginx.conf 예시
server {
    listen 443 ssl;
    server_name my-service.com;

    ssl_certificate /etc/letsencrypt/live/my-service.com/fullchain.pem; # 이 파일
    ssl_certificate_key /etc/letsencrypt/live/my-service.com/privkey.pem; # 그리고 이 파일!
    ...
}

확인된 인증서 파일들을 scp와 같은 명령어를 사용해 로컬 PC나 새 서버로 안전하게 복사해 둡니다.


2단계: 새로운 서버에 Docker 환경 구축하기 (TO-BE)

이제 모든 분석이 끝났습니다. 새로운 서버에 Docker를 설치하고 마이그레이션을 위한 프로젝트 구조를 만들어 봅시다.

2.1. Docker 및 Docker Compose 설치 (Ubuntu 기준)

# 1. 패키지 목록 업데이트
sudo apt-get update

# 2. Docker 설치에 필요한 패키지 설치
sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common

# 3. Docker의 공식 GPG 키 추가
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

# 4. Docker 저장소 추가
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"

# 5. 패키지 목록 다시 업데이트
sudo apt-get update

# 6. Docker CE(Community Edition) 설치
sudo apt-get install -y docker-ce

# 7. Docker Compose 설치
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

# 8. 설치 확인
docker --version
docker-compose --version

2.2. 마이그레이션을 위한 프로젝트 구조 생성

새 서버에 작업 디렉터리를 만들고 다음과 같은 구조로 파일을 정리합니다. 이렇게 하면 설정 파일을 관리하기 매우 편해집니다.

/home/ubuntu/my-app/
├── docker-compose.yml       # Docker 컨테이너 오케스트레이션 파일
|
├── was/
│   ├── Dockerfile             # Tomcat 이미지를 만들기 위한 Dockerfile
│   └── ROOT.war               # 기존 서버에서 가져온 WAS 애플리케이션 파일
│
├── nginx/
│   └── nginx.conf             # Nginx 설정 파일
│
├── ssl/
│   ├── fullchain.pem          # 기존 서버에서 가져온 SSL 인증서
│   └── privkey.pem            # 기존 서버에서 가져온 SSL 키
│
└── logs/
    └── nginx/                 # Nginx 로그가 저장될 디렉터리 (호스트와 공유)

 

각 파일 및 디렉터리 생성 명령어

mkdir -p /home/ubuntu/my-app/{was,nginx,ssl,logs/nginx}
cd /home/ubuntu/my-app
touch docker-compose.yml nginx/nginx.conf was/Dockerfile
# 이후 scp 등을 이용해 ROOT.war와 ssl 인증서 파일들을 해당 위치에 복사합니다.

3단계: Docker Compose로 WAS와 Nginx 함께 띄우기

이제 각 컴포넌트에 대한 설정 파일을 작성하고, docker-compose.yml로 두 컨테이너를 한 번에 관리해 보겠습니다.

3.1. WAS (Tomcat) Dockerfile 작성

was/Dockerfile을 열어 아래와 같이 작성합니다. 기존 서버와 동일한 버전의 Tomcat 이미지를 기반으로, 우리가 만든 WAR 파일을 복사하는 내용입니다.

./was/Dockerfile

# 1단계에서 확인한 Tomcat 버전에 맞는 공식 이미지를 사용합니다. (예: 9.0)
# JDK는 11 버전을 사용하는 이미지로 선택했습니다.
FROM tomcat:9.0-jdk11-openjdk

# 작성자 정보 (선택 사항)
LABEL maintainer="Your Name <your-email@example.com>"

# 로컬에 있는 WAR 파일을 컨테이너의 webapps 디렉터리로 복사
# 이렇게 하면 Tomcat이 실행될 때 자동으로 이 애플리케이션을 배포합니다.
COPY ./ROOT.war /usr/local/tomcat/webapps/

3.2. Nginx 설정 파일 수정 (nginx.conf)

기존 nginx.conf를 Docker 환경에 맞게 수정해야 합니다. 가장 큰 차이점은 proxy_pass의 대상이 127.0.0.1이 아닌, **Docker Compose가 만들어 줄 WAS 서비스의 이름(컨테이너 이름)**으로 바뀐다는 점입니다.

./nginx/nginx.conf

# Docker 컨테이너는 기본적으로 포그라운드에서 실행되어야 하므로 daemon off; 추가
daemon off;

events {
    worker_connections 1024;
}

http {
    # Docker 내부 DNS가 WAS 컨테이너를 찾을 수 있도록 resolver 설정 (선택사항이지만 안정적)
    # resolver 127.0.0.11 valid=30s;

    server {
        listen 80;
        server_name my-service.com;

        # 로그 파일 경로를 컨테이너 내부 경로로 지정 (나중에 볼륨으로 연결)
        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;

        location / {
            # [중요!] proxy_pass 대상을 localhost가 아닌 docker-compose에서 정의할 서비스 이름 'was'로 변경
            # Docker의 내부 네트워크를 통해 'was'라는 이름의 컨테이너 8080 포트로 연결됩니다.
            proxy_pass http://was:8080; 

            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $http_host;
        }
    }

    # HTTPS 설정이 필요하다면 아래와 같이 추가
    # server {
    #     listen 443 ssl;
    #     server_name my-service.com;

    #     # SSL 인증서 경로 (나중에 볼륨으로 연결)
    #     ssl_certificate /etc/nginx/ssl/fullchain.pem;
    #     ssl_certificate_key /etc/nginx/ssl/privkey.pem;

    #     location / {
    #         proxy_pass http://was:8080;
    #         proxy_set_header X-Real-IP $remote_addr;
    #         proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    #         proxy_set_header Host $http_host;
    #     }
    # }
}

3.3. docker-compose.yml 작성 (모든 것을 하나로!)

이 파일이 바로 마법의 레시피입니다. WAS와 Nginx 서비스를 정의하고, 볼륨과 네트워크를 설정하여 두 컨테이너를 연결합니다.

./docker-compose.yml

version: "3.8" # Docker Compose 파일 버전

services:
  # WAS (Tomcat) 서비스 정의
  was:
    build: 
      context: ./was  # ./was 디렉터리의 Dockerfile을 사용하여 이미지를 빌드
    container_name: my-was-container # 컨테이너 이름 지정
    restart: always # 컨테이너가 중지되면 항상 다시 시작

  # Nginx 서비스 정의
  nginx:
    image: nginx:1.18.0 # 1단계에서 확인한 버전과 유사한 공식 이미지 사용
    container_name: my-nginx-container
    restart: always
    ports:
      - "80:80"     # 호스트의 80번 포트를 컨테이너의 80번 포트와 연결
      - "443:443"   # 호스트의 443번 포트를 컨테이너의 443번 포트와 연결
    
    volumes:
      # [설정 파일 마운트]
      # 호스트의 nginx.conf 파일을 컨테이너의 nginx.conf 파일로 덮어씁니다.
      # 이렇게 하면 컨테이너를 다시 빌드하지 않고 설정만 바꿀 수 있습니다.
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf 
      
      # [SSL 인증서 마운트]
      # 호스트의 ssl 디렉터리를 컨테이너의 /etc/nginx/ssl 디렉터리에 연결합니다.
      - ./ssl:/etc/nginx/ssl

      # [로그 파일 마운트]
      # 호스트의 logs/nginx 디렉터리를 컨테이너의 로그 디렉터리에 연결합니다.
      # 이렇게 하면 컨테이너가 삭제되어도 로그가 서버에 남습니다.
      - ./logs/nginx:/var/log/nginx

      # [시간 동기화 마운트] - 중요!
      # 호스트 서버의 시간대 파일을 컨테이너에 읽기 전용(ro)으로 마운트합니다.
      # Nginx 로그에 찍히는 시간이 서버 시간과 동일하게 됩니다.
      - /etc/localtime:/etc/localtime:ro

    depends_on:
      - was # Nginx를 시작하기 전에 'was' 서비스가 먼저 실행되도록 보장합니다.

3.4. 컨테이너 실행 및 확인

모든 준비가 끝났습니다. docker-compose.yml 파일이 있는 디렉터리에서 아래 명령어를 실행하세요.

# 이미지 빌드(-build) 및 백그라운드에서 컨테이너 실행(-d)
sudo docker-compose up -d --build

# 실행 중인 컨테이너 목록 확인
sudo docker-compose ps

# 출력 예시
#        Name                      Command               State           Ports         
# --------------------------------------------------------------------------------------
# my-nginx-container   /docker-entrypoint.sh ngin ...   Up      0.0.0.0:443->443/tcp, 
#                                                                0.0.0.0:80->80/tcp  
# my-was-container     catalina.sh run                  Up      8080/tcp    

# 각 컨테이너의 로그 실시간 확인
# Nginx 로그 확인
sudo docker-compose logs -f nginx

# WAS(Tomcat) 로그 확인
sudo docker-compose logs -f was

이제 웹 브라우저에서 http://<새 서버 IP> 로 접속했을 때 WAS 애플리케이션 화면이 나타나면 성공입니다!


4단계: DNS 설정 및 최종 테스트

마지막으로, 사용자들이 기존 도메인(my-service.com)으로 접속했을 때 새로운 서버로 연결되도록 DNS 설정을 변경해야 합니다.

  1. DNS 관리 페이지 접속: 도메인을 구입한 곳(예: 가비아, GoDaddy) 또는 DNS 서비스(예: AWS Route 53, Cloudflare)에 로그인합니다.
  2. 'A' 레코드 수정: 도메인(my-service.com)에 연결된 'A' 레코드를 찾습니다.
  3. IP 주소 변경: 'A' 레코드의 값을 기존 서버의 IP에서 새로운 서버의 공인 IP로 변경하고 저장합니다.

DNS 전파(Propagation): DNS 정보가 전 세계 인터넷에 퍼지는 데에는 몇 분에서 최대 48시간까지 걸릴 수 있습니다. nslookup my-service.com 명령어로 IP가 잘 바뀌었는지 확인해 보세요.