본문 바로가기
Spring boot

[Docker] 도커 + 도커 컴포즈 + Nginx + Spring boot(Local) 연동하기

by 리버🐦‍🔥 2024. 6. 26.

이번 포스팅은 무수히 많은 삽질 후 겨우겨우 성공한… 도커 컴포즈 사용기(feat. Nginx, Spring boot)이다.

추후 이 작업을 활용하여 EC2에 S3와 CodeDeploy를 사용하는 대신 Docker Hub를 사용하여 CI/CD를 사용하는 방법에 대해 포스팅하도록 하겠다.


사전 작업

1. application.properties → application.yml로 변경 후 yml파일 내용 수정

# application.yml
spring:
  application:
    name: Liver-Server

  profiles:
    default: local

 

 

2. 성공 확인을 위한 테스트 컨트롤러 작성

// TestController.java
package com.appledeveloperacademy.Liver_Server.domain.test.controller;

import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructors
@RequestMapping("/tests")
public class TestController {

    @GetMapping
    private String printTest() {
        return "test";
    }
}

도커 컴포즈 연결 순서

  1. Springboot Dockerfile 생성
  2. Nginx Dockerfile 생성
  3. nginx.conf 생성
  4. docker-compose.yml 생성
  5. 도커 컴포즈 실행

이해를 위한 프로젝트 구조

필자는 application.properties파일을 삭제하고, /src/main/resources 디렉토리에 application.yml파일을 작성해주었다.

(localhost.p12 파일은 로컬 환경에서 https를 설정하기 위해 넣어놓은 것이다. 사용하지 않으므로 무시해도 좋다.)

1. Springboot Dockerfile 생성

루트 디렉토리에 Spring boot 도커 이미지 생성을 위한 Dockerfile을 생성한다.

(파일 경로 : root)

# 도커 이미지 생성을 위한 설정 파일
FROM openjdk:17-jdk
LABEL authors="kyungsoolee"
EXPOSE 8080
ARG JAR_FILE=build/libs/*.jar
ARG SPRING_PROFILE=local
# 일반적인 복사이기 때문에 ADD보다는 COPY가 더 적절함
# ADD ${JAR_FILE} Liver-Server-springboot.jar
COPY ${JAR_FILE} Liver-Server-springboot.jar
ENV spring_profile=${SPRING_PROFILE}
# ENTRYPOINT : 컨테이너가 시작될 때 실행할 기본 명령 설정
# "-Djava.security.egd=file:/dev/./urandom" : Java의 난수 생성 속도 개선 명령어
ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom","-jar","/Liver-Server-springboot.jar", "--spring.profiles.active=${spring_profile}"]

2. Nginx Dockerfile 생성

nginx 디렉토리에 nginx 도커 이미지 생성을 위한 Dockerfile을 생성한다.

(파일 경로 : /nginx)

FROM nginx:latest
# 가상 공간의 nginx 기본 설정파일 삭제 후 작성한 설정파일로 대체
RUN rm /etc/nginx/conf.d/nginx.conf
COPY nginx.conf /etc/nginx/conf.d

여기서 proxy_pass의 설정과 이후에 나올 docker-compose.yml의 services.{스프링 부트 도커 이미지 이름}.container_name이 동일해야 한다. 필자는 이 부분이 이미지 이름과 컨테이너 이름이 헷갈려서 삽질을 엄청 많이 했다…

3. nginx.conf 생성

nginx 디렉토리에 nginx에서 스프링 서버에 redirection해줄 수 있게 nginx.conf 파일을 작성한다.

(파일 경로 : /nginx)

# 이벤트 블록을 설정합니다.
events {}

# NGINX의 HTTP 블록을 엽니다. HTTP 블록은 웹 서버의 모든 HTTP 기능을 정의합니다.
http {
    # 서버 블록을 정의합니다. 이 서버 블록은 클라이언트의 요청을 받아들이고 처리합니다.
    server {
        # 포트 80에서 들어오는 HTTP 요청을 수신할 것임을 나타냅니다.
        listen  [::]:80;
        listen 80;

        # 'localhost' 도메인으로 들어오는 요청을 처리할 것임을 나타냅니다.
        server_name localhost;

        # 모든 경로('/')에 대한 요청을 받아들이는 location 블록입니다.
        location / {
            # NGINX가 받은 모든 요청을 'http://{연결할 Spring boot 컨테이너 이름}:8080'으로 프록시하여 처리하도록 지시합니다.
            proxy_pass http://spring-boot-container:8080;

            # 프록시된 요청에 'Host' 헤더를 추가하여 백엔드 서버에 전달합니다.
            proxy_set_header Host $host;

            # 프록시된 요청에 클라이언트의 실제 IP 주소를 'X-Real-IP' 헤더에 추가하여 백엔드 서버에 전달합니다.
            proxy_set_header X-Real-IP $remote_addr;

            # 프록시된 요청에 클라이언트의 원래 IP 주소를 'X-Forwarded-For' 헤더에 추가하여 백엔드 서버에 전달합니다.
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

            # 프록시된 요청에 클라이언트가 사용하는 프로토콜(HTTP 또는 HTTPS)를 'X-Forwarded-Proto' 헤더에 추가하여 백엔드 서버에 전달합니다.
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }
}

4. docker-compose.yml 생성

(파일 경로 : root )

version: '3'

services:
  spring-boot: # services 내부에서 사용될 spring boot 서비스 이름. (컨테이너 이름과 다르다. 헷갈리면 안된다!!!)
    container_name: spring-boot-container # nginx.conf의 proxy_pass에서 설정한 컨테이너 이름과 동일해야 함. 추후 도커 컨테이너 이름으로 사용
    build: . # springboot Dockerfile 경로
    ports:
      - "8080:8080"
    networks:
      - Liver-Server

  nginx: # services 내부에서 사용될 Nginx 서비스 이름(=변수명?)
    container_name: nginx # 설정하고싶은 컨테이너 이름
    image: nginx:latest # 실행시킬 Nginx 도커 이미지의 이름.
    volumes:
      - ./nginx/:/etc/nginx/ # 왼쪽이 로컬 경로, 오른쪽이 도커 컨테이너 내부 경로
    ports:
      - 80:80
    depends_on: # 빌드 시작 순서를 정해주는 옵션
      - spring-boot # 빌드 시 spring-boot 라는 이름을 가진 서비스부터 실행 후 nginx 서비스를 실행하라는 의미
     	 # 이미지 빌드 순서: spring-boot -> nginx
    networks:
      - Liver-Server

networks: # 컨테이너를 연결할 네트워크
  Liver-Server:

5. docker-compose 실행

1. 아래 명령어를 docker-compose.yml파일이 있는 루트 디렉토리에서 실행하여 도커 컨테이너를 띄우고 동작시킨다.

docker compose up --build

2. 도커를 실행시켜 위(1)에서 실행시킨 컨테이너가 제대로 동작중인지 확인한다.

3. localhost/tests(테스트 컨트롤러에서 만들어놓은 api)에 접근가능한지 다시 한 번 확인한다.