마지막 강의이다.

 

실습 전 설정

실습 디렉토리 : last (강의에서는 그대로 ex09에서하심)

  • db
  • product
  • docker-compose.yml
  • my-react-app-auto-build

실습 전에 해당 파일들을 ex09에서 last로 복사해놓자.

 

[강사님 GIT에서 nginx.conf 퍼오기]

https://github.com/codingspecialist/docker-study/blob/main/ex09/my-app/nginx/nginx.conf

 

docker-study/ex09/my-app/nginx/nginx.conf at main · codingspecialist/docker-study

Contribute to codingspecialist/docker-study development by creating an account on GitHub.

github.com

여기서 nginx.conf 퍼오자. 설명은 나중에 해준다고 하심.

 

[Nginx 설정하기 및 설명] 

위치 : last / my-react-app-auto-build / nginx 생성!

방금 퍼온 nginx.conf를 방금 생성한 nginx디렉토리에 넣어주자.

 

upstream backend {
	server backend: 8080;
}

 

upstream backend -> 변수를 하나 지정한다고 생각하자.

backend에 요청이 들어오면 backend:8080으로 가게 하겠다.

여기서 server backend:8080; 에서 backend는 도커 컴포즈의 서비스명이다. 이는 10.10.1.1로 치환된다고 생각하면된다.

 

#server_name metacoding.site www.metacoding.site;

실제로 도메인이 있으면 써야하는데 도메인이 없기 때문에 주석처리한다.

 

location / {
              root   /usr/share/nginx/html;
              index  index.html index.htm;

 

'/' 로 요청이 오면 /usr/share/nginx/html 안에 있는 index.html 파일을 전달해줄 것이다.

여기에서 index.html은 react가 build된 파일이다.

이는 도커 입문 30강 - 도커컴포즈 Dockerfile로 빌드와 nginx실행 한번에 하기

 

도커 입문 30강 - 도커컴포즈 Dockerfile로 빌드와 nginx실행 한번에 하기

[실습목표]이번 강의는 이전강의와 같이 React를 Nginx에서 실행하도록하는 목표를 공유하고있다.차이점은 이전강의에서는 직접 build해줬지만 이번 강의에서는 build조차 자동으로 되도록 하고자

ilikecoding.tistory.com

여기에서 한번 했었다.

 

저기에서 사용한 Dockerfile의 내용을 보면 

FROM node:alpine as build
WORKDIR /app
COPY package.json /app
RUN npm install --silent
COPY . /app
RUN npm run build

FROM nginx
#--from=build는 위에있는 FROM으로 부터 이미지가 구워지는데 그 결과로 나온 것을 의미한다.
# 위에서 나온 결과물인 /app/build 를 /usr/share/nginx/html로 복사하라는 의미이다.
COPY --from=build /app/build /usr/share/nginx/html
ENTRYPOINT ["nginx","-g","daemon off;"]

여기에서 마지막에서 2번째 줄에 있는 것을 보면 build한 것을 /usr/share/nginx/html로 넣어주게 되는 것을 볼 수 있다.

 

location /api/ {
              proxy_pass http://backend;
              rewrite ^/api(/.*)$ $1 break; # /api/ 제거가 되요!!

/api로 왔을 때의 설정인데 가장 중요한 것을 proxy_pass이다. http://, https:// 는 고정인데 backend 이부분이 docker 내부 IP는 컨테이너가 실행될 때 동적으로 바뀌게 되니까 미리 적어 놓을 수가 없다. 그래서 저렇게 backend라고 적어놓으면 upstream backend {

    server backend:8080; 

}

여기 upstream의 backend를 찾아간다. 근데 여기 적힌 server backend:8080은 도커 서비스명이다.

 

2번째 줄인 

rewrite ^/api(/.*)$ $1 break; # /api/ 제거가 되요!!

이 부분은 스프링에 Controller는 /api/ 로 시작되는 부분이 없으니까 nginx단에서 제거 해주는 것이다.

밑에 proxy_http_version~ 헤더 들은 다음 시간에 따로 알려주신다고 하심...

 

이제 해당 설정파일을 가진 nginx가 올라가서 nginx와 통신을 하면 [ 도커 입문 31강 - 도커컴포즈 React와 SpringDB포함 직접연결하기]  강의에서 설정한 cross origin은 필요가 없어진다.

왜냐면,
React에서 /api/ ---▶ nginx (/api를 없애주고 Spring에게 전달)  ---▶ Spring

이렇게 React에서 직접적으로 Spring에 요청한 것이 아니고 프록시 서버를 경유하는 요청이기 때문에 Cross Origin 에러에 걸리지 않게 된다.

 

[my-react-app-auto-build]

my-react-app-auto-build 디렉토리에 있는 Dockerfile에서 nginx를 띄우는데 그것을 수정해야한다.

FROM node:alpine as build
WORKDIR /app
COPY package.json /app
RUN npm install --silent
COPY . /app

RUN npm run build

FROM nginx
#--from=build는 위에있는 FROM으로 부터 이미지가 구워지는데 그 결과로 나온 것을 의미한다.
# 위에서 나온 결과물인 /app/build 를 /usr/share/nginx/html로 복사하라는 의미이다.
COPY --from=build /app/build /usr/share/nginx/html
#내가 커스텀한 nginx.conf파일로 넢어씌운다.
COPY ./nginx/nginx.conf /etc/nginx/nginx.conf
ENTRYPOINT ["nginx","-g","daemon off;"]

모두 똑같은데 마지막 COPY 하는 부분에서 위에서 설정한 nginx.conf 파일을 실제로 가동될 nginx 컨테이너로 덮어 씌우는 부분을 추가했다.

 

그리고 소스코드도 변경해야하는데 onLoad 함수의 fetch에서 요청하는 주소만 변경하면된다.

async function onLoad(){
       //let response = await fetch('http://localhost:8080/products');
       let response = await fetch('/api/products');
       let responseBody = await response.json();
       console.log("onLoad",responseBody);
       setProducts(responseBody);
}

http://192.168.0.3/products ----▶ /api/products 로 변경하면 된다.

 

[product]  : 딱히 변경점이 없다. 굳이 있다면 cross origin 설정 코드를 지우는 것?

[db]  : 딱히 변경점이 없다. 

 

※우리는 db의 데이터 파일들을 모두 외부 볼륨(store 디렉토리)로 연결시켜놨기 때문에 컨터이너 종료와 상관없이 계속 누적된다.

※ docker-compose.yml은 실제 배포할 때는 필요가 없다. 로컬에서 테스트 용으로만 사용하고, AWS같은 곳에 배포할 때는 Dockerfile만 잘 써두면 된다.

 

[docker-compose.yml]

server -> backend로 변경

 

frontend 추가

  backend:
    build:
      context: ./product
      dockerfile: Dockerfile
    restart: always
    ports:
      - 8080:8080
    depends_on:
      - db #db가 먼저 구축되고 나서 다 되면 server를 실행시키는 것을 의미한다.
    environment: #해당 값들은 application-prod.yml에서 ${SPRING_DATASOURCE_URL} 에서 사용한다.
      SPRING_DATASOURCE_URL: jdbc:mysql://db:3306/metadb?useSSL=false&serverTimezone=UTC&useLegacyDatetimeCode=false&allowPublicKeyRetrieval=true
      SPRING_DATASOURCE_DRIVER: com.mysql.cj.jdbc.Driver
      SPRING_DATASOURCE_USERNAME: root
      SPRING_DATASOURCE_PASSWORD: root1234
    networks: #동일 네트워크로 잡아주어야 datasource url에서 jdbc:mysql://db 로 쓸수있는 것이다. ip로 안쓰고..
      - network
  frontend:
    build:
      context: ./my-react-app-auto-build
      dockerfile: Dockerfile
    restart: always
    ports:
      - 80:80
    depends_on:
      - backend
    networks:
      - network

db, netowork 부분은 변경점이 없다.

 

 

docker-compose.yml 전체코드

version: '3'

services:
  db:
    build:
      context: ./db #Dockerfile의 위치-이걸 안잡아주면 COPY할 때 init.sql위치를 ex08(docker-compose.yml이 있는 곳)으로 봐버리는 문제가 생긴다.
      dockerfile: Dockerfile
    ports:
      - 3306:3306
    volumes:
      - ./db/store:/var/lib/mysql
    networks:
      - network

  backend:
    build:
      context: ./product
      dockerfile: Dockerfile
    restart: always
    ports:
      - 8080:8080
    depends_on:
      - db #db가 먼저 구축되고 나서 다 되면 server를 실행시키는 것을 의미한다.
    environment: #해당 값들은 application-prod.yml에서 ${SPRING_DATASOURCE_URL} 에서 사용한다.
      SPRING_DATASOURCE_URL: jdbc:mysql://db:3306/metadb?useSSL=false&serverTimezone=UTC&useLegacyDatetimeCode=false&allowPublicKeyRetrieval=true
      SPRING_DATASOURCE_DRIVER: com.mysql.cj.jdbc.Driver
      SPRING_DATASOURCE_USERNAME: root
      SPRING_DATASOURCE_PASSWORD: root1234
    networks: #동일 네트워크로 잡아주어야 datasource url에서 jdbc:mysql://db 로 쓸수있는 것이다. ip로 안쓰고..
      - network
  frontend:
    build:
      context: ./my-react-app-auto-build
      dockerfile: Dockerfile
    restart: always
    ports:
      - 80:80
    depends_on:
      - backend
    networks:
      - network
networks:
  network:

 

 

[product(backend)] Dockerfile 전체코드

FROM openjdk:11-jdk-slim

WORKDIR /app

# COPY만 docker-compose 파일의 위치를 기반으로 작동함
COPY . .

# 개행문자 오류 해결 [unix와 window 시스템 차이]
RUN sed -i 's/\r$//' gradlew

# RUN은 현재 파일을 위치를 기반으로 작동함
RUN chmod +x ./gradlew
RUN ./gradlew clean build

ENV JAR_PATH=/app/build/libs
RUN mv ${JAR_PATH}/*.jar /app/app.jar

ENTRYPOINT ["java", "-jar", "-Dspring.profiles.active=prod", "app.jar"]

 

 

[db] Dockerfile전체코드

FROM mysql:8.0

COPY init.sql /docker-entrypoint-initdb.d

ENV MYSQL_ROOT_PASSWORD=root1234
ENV MYSQL_DATABASE=metadb
ENV MYSQL_HOST=%

CMD ["--character-set-server=utf8mb4", "--collation-server=utf8mb4_unicode_ci"]

 

[React] Dockerfile전체코드

FROM node:alpine as build
WORKDIR /app
COPY package.json /app
RUN npm install --silent
COPY . /app

RUN npm run build

FROM nginx
#--from=build는 위에있는 FROM으로 부터 이미지가 구워지는데 그 결과로 나온 것을 의미한다.
# 위에서 나온 결과물인 /app/build 를 /usr/share/nginx/html로 복사하라는 의미이다.
COPY --from=build /app/build /usr/share/nginx/html
#내가 커스텀한 nginx.conf파일로 넢어씌운다.
COPY ./nginx/nginx.conf /etc/nginx/nginx.conf
ENTRYPOINT ["nginx","-g","daemon off;"]

+ Recent posts