티스토리 뷰

Ubuntu 환경에서 Docker-compose 사용해 Nginx, Spring Boot 컨테이너 두 대를 실행시키고, Nginx를 Reverse Proxy 로 구성해보자.

 

[ Reverse Proxy ]

1. Proxy

Proxy는 번역하면 대리라는 의미를 가진다. Proxy 서버는 클라이언트와 서버 사이에서 클라이언트 또는 서버를 대신해 기능을 수행하거나, 중계하는 역할을 한다.

 

2. Reverse Proxy

리버스 프록시는 클라이언트로부터 오는 요청을 대신 받아 내부 서버로 전달해주는 역할을 한다.

  • 로드 밸런싱: 많은 요청을 처리하기 위해 여러대의 서버에 부하 분산 수행 가능
  • 캐싱: 미리 렌더링된 버전의 페이지를 캐시하여 페이지 로드 시간을 단축할 수 있다.
  • 보안: 내부 WAS의 존재를 숨길 수 있다. 또한 Nginx는 ssh 설정이 가능하다.

 

[ 서버 아키텍처 ]

 

클라이언트가 80 포트로 요청을 하면, Nginx는 해당 요청을 spring boot 컨테이너의 8081 포트로 전달한다.

즉, 80번 포트에 요청을 해도 8081 포트에 요청한 것과 같은 결과가 나타나도록 해보자.

 

[ Spring Boot ]

간단하게 Spring으로 API를 만들고, 테스트해보자.  http://localhost:8081/ 로 요청하면 hello world! 를 반환하는 간단한 API를 작성했다.

@RestController
public class UserController {

    @GetMapping("/")
    public String hello() {
        return "hello world!";
    }
}

 

[ NGINX ]

default.conf 파일이다.

upstream spring-app {
    server springboot:8081;
}

server {
    listen 80;

    location / {
        proxy_pass http://spring-app;
    }
}

자세히 알아보자

 

1. 8081번 포트에서 springboot가 돌아가고 있다는 것을 명시해준다.

springboot는 docker-compose에 작성한 service 명이다.

upstream spring-app {
    server springboot:8081;
}

 

2. nginx 서버 포트를 80번으로 열어준다.

listen 80;

 

3. / 경로로 들어오는 요청을 http://spring-app 즉, http://springboot:8081 으로 보내준다.

location / {
    proxy_pass http://spring-app
}

 

[ Docker Compose ]

version: "3"
services:
  mysql:
    image: mysql:5.7
    restart: unless-stopped
    environment:
      - MYSQL_USER=haneul
      - MYSQL_PASSWORD=1234
      - MYSQL_DATABASE=myapp
      - TZ=Asia/Seoul
    volumes:
      - ./mysql/my.cnf:/etc/mysql/conf.d/my.cnf
      - ./mysql/data:/var/lib/mysql
      - ./mysql/init:/docker-entrypoint-initdb.d
    ports:
      - "33306:3306"
  springboot:
    build: .
    environment:
      - SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/myapp?characterEncoding=UTF-8
      - SERVER_PORT=8081
    ports:
      - "8081:8081"
    depends_on:
      - mysql
  nginx:
    restart: always
    image: nginx
    volumes:
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
    ports:
      - "80:80"
    depends_on:
      - springboot

각 service에 대해 자세히 알아보자.

 

- nginx

nginx:
    restart: always
    image: nginx
    volumes:
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
    ports:
      - "80:80"
    depends_on:
      - springboot

1. restart: always

nginx는 Proxy 역할을 하고 있으므로, 컨테이너가 멈추면 안된다. 따라서 컨테이너를 항상 재시작하도록 설정

  • restart: no : 어떠한 상황에서도 재시작을 하지 않는다.
  • restart: always : 항상 재시작을 한다.
  • restart: on-failure  on-failure 에러코드와 함께 컨테이너가 멈추었을때만 재시작을 한다.
  • restart: unless-stopped 개발자가 임의로 멈추려고 할 때 빼고는 항상 재시작을 한다.

 

2. volumes

로컬의 default.conf 파일과 컨테이너 내부의 default.conf 파일을 volume으로 연결해준다.

 

 

- mysql

mysql:
    image: mysql:5.7
    restart: unless-stopped
    environment:
      - MYSQL_USER=haneul
      - MYSQL_PASSWORD=1234
      - MYSQL_DATABASE=myapp
      - TZ=Asia/Seoul
    volumes:
      - ./mysql/my.cnf:/etc/mysql/conf.d/my.cnf
      - ./mysql/data:/var/lib/mysql
      - ./mysql/init:/docker-entrypoint-initdb.d
    ports:
      - "33306:3306"

1. environment

MySQL에 필요한 환경변수 지정해줘야 한다. 환경변수에 대한 설명은  MySQL DockerHub 목록 을 참조하자.

 

2. volumes

데이터베이스 컨테이너가 종료되더라도 컨테이너 내 저장된 자료를 유지하기 위해 사용한다.

컨테이너 내 /var/lib/mysql 에 저장된 데이터가 호스트 파일 시스템에도 저장된다.

 

my.cnf : 한글 인코딩을 위한 설정파일

[mysqld]
character-set-server=utf8

[mysql]
default-character-set=utf8

[client]
default-character-set=utf8

init/initialize.sql : db 초기화하기 위한 sql 파일

DROP DATABASE IF EXISTS myapp;

CREATE DATABASE myapp;
USE myapp;

CREATE TABLE user (
    id bigint auto_increment,
    name varchar(20),
    age bigint,
    primary key (id)
);

 

- springboot

springboot:
    build: .
    environment:
      - SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/myapp?characterEncoding=UTF-8
      - SERVER_PORT=8081
    ports:
      - "8081:8081"
    depends_on:
      - mysql

 

1. environment

spring boot는 environment를 통해 application.yml 환경 변수를 설정할 수 있다.

server.port 를 8081로 지정하고, spring.datasource.url는 위와 같이 지정했다.

(datasource의 호스트명을 mysql 로 지정)

  • docker compose 는 모든 컨테이너를 default 네트워크로 연결한다.
  • default 네트워크 내 컨테이너간 통신은 service 이름이 호스트명으로 사용된다.

 

[ Docker Compose 실행 ]

1. jar 파일 생성

$ ./gradlew build

2. docker-compose up

$ sudo docker-compose up --build

  • --build : 캐싱된 이미지를 체크하지 않고, 무조건 빌드하고 시작하라는 의미
  • 소스 수정이 이루어졌을 때는 다시 이미지를 빌드해야 하므로, 가급적 --build를 붙여 docker-compose up을 하자!
--build 옵션 없이 실행했다가 수정된 소스코드 반영이 안돼서 꽤나 삽질했다 .....

 

그 결과, 80번 포트에 요청을 하면 8081 포트에 요청한 것과 같은 결과가 나온다. (성공)

 

'DevOps > Docker' 카테고리의 다른 글

[Docker] Dockerfile COPY 사용 시 문제점  (0) 2023.03.10
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
글 보관함