티스토리 뷰
2023.04.02 - [조미료 보관함] - [Trouble Shooting] net::ERR_NAME_NOT_RESOLVED
바로 이전 글에서 브라우저가 docker compose의 default 네트워크 외부에서 네트워크 내부에 있는 서비스에 접근하려고 시도함으로 인해 발생한 오류와 개발환경에서 꼼수로 사용할 수 있는 간단한 해결 방안을 적용해 보았다.
이번에는 브라우저에서 발생한 요청을 reverse proxing하여 서버로 전달하고, 서버로부터 받은 응답을 브라우저에게 전달할 수 있도록 nginx를 사용하여 reverse proxy를 설정해보았다.
# Nginx로 web app 제공하기
[Nginx가 추가된 Dockerfile]
# ==== CONFIGURE =====
# Use a Node 16 base image
FROM node:16-alpine As builder
# Set the working directory to /app inside the container
WORKDIR /app
# Copy app files
COPY ./web .
# ==== BUILD =====
# Install dependencies (npm ci makes sure the exact versions in the lockfile gets installed)
RUN npm ci
# Build the app
RUN npm run build
# Bundle the app with nginx
FROM nginx:1.23.4-alpine
# Set the env to "development"
ENV NODE_ENV development
# Copy the build output from the builder stage
COPY --from=builder /app/build /usr/share/nginx/html
# Copy the nginx config
COPY ./build/web/nginx.conf /etc/nginx/conf.d/default.conf
# Expose port 80
EXPOSE 80
# Start nginx
CMD ["nginx", "-g", "daemon off;"]
우선은 Nginx를 사용해 web app을 제공할 수 있도록 Dockerfile의 내용을 수정했다.
[기존의 Dockerfile]
# ==== CONFIGURE =====
# Use a Node 16 base image
FROM node:16-alpine
# Set the working directory to /app inside the container
WORKDIR /app
# Copy app files
COPY ./web .
# ==== BUILD =====
# Install dependencies (npm ci makes sure the exact versions in the lockfile gets installed)
RUN npm ci
# Build the app
RUN npm run build
# ==== RUN =======
# Set the env to "development"
ENV NODE_ENV development
# Expose the port on which the app will be running (3000 is the default that `serve` uses)
EXPOSE 3000
# Start the app
CMD [ "npx", "serve", "build" ]
기존에는 node로 빌드하고 npx serve build 명령어로 앱을 실행했다.
이렇게 만들어진 도커 이미지의 크기는 700MB가 넘었는데 Nginx로 빌드된 내용물만 가져와서 실행하니 이미지 크기가 40MB 밖에 되지 않는 것을 확인할 수 있었다.
# nginx.conf 작성
server {
listen 80; # 80번 포트에서 nginx 서버 실행
location / { # '/'와 매칭되는 URI에 대해
root /usr/share/nginx/html/; # /usr/share/nginx/html/ 디렉토리에 있는 정적 컨텐츠를 제공
include /etc/nginx/mime.types;
try_files $uri $uri/ /index.html;
}
location /api/ { # '/api/`와 매칭되는 URI에 대해
rewrite ^/api(.*) $1 break; # '/api/ 접두사를 제거하고 나머지 부분을 경로를 재설정하여
proxy_pass http://proxy-server:80; # proxy-server로 요청을 리버스 프록싱
}
}
1. 브라우저에서 http://localhost:80/api/v1/todo/all로 요청
2. nginx가 요청 경로에서 /api 접두사를 제거 -> /v1/todo/all
3. nginx가 요청을 http://proxy-server:80으로 전달 -> http://proxy-server:80/v1/todo/all
4. proxy-server로부터 받은 응답을 브라우저로 전달
# Diagram
# Test
web app을 통해서 요청을 보내는 것도 가능해졌고 브라우저에서 직접 요청을 보내거나 CLI를 통해서 요청을 보내는 것도 가능해졌다. 그런데 이렇게 되면 네트워크 내부에서만 접근해서 사용하려 했던 api가 외부로 완전히 노출되는 문제가 발생한다. 그리고 이에 따른 보안 이슈가 생길 것이라고 예상한다.
네트워크에 대한 이론도 어렵고 직접 구현하는 것도 어렵다. 정말 아무런 계획도 없이 밑바닥에서부터 조금씩 살점을 붙여서 어느정도 모양새는 갖추게 되었는데, 처음에 예상했던 대로 리버스 프록시를 사용하지 않고 web app에서 서버로 직접 요청을 보낼 수 있도록 구성하지 못한 점이 참 아쉽다. 네트워크 구성과 아키텍쳐에 관한 공부가 더 필요하다는 것을 절실하게 느낀다.
web app이 SSR(Server Side Rendering)로 동작한다면 직접 요청을 보내는 것이 가능할까? 다음번에는 SSR로 동작하는 웹 프레임워크를 사용하여 네트워크를 구성해볼 생각이다.
# Source
https://github.com/piatoss3612/go-grpc-todo
# Reference
https://jsramblings.com/dockerizing-a-react-app/
https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/
chat gpt
'개발 부스러기' 카테고리의 다른 글
WSL에서 Go 사용하기 (0) | 2023.12.26 |
---|---|
Chainlink - Data Feeds (0) | 2023.10.31 |
바빌로니아 법 (The Babylonian Method) (0) | 2023.04.10 |
[Trouble Shooting] net::ERR_NAME_NOT_RESOLVED (0) | 2023.04.02 |
[Go] gRPC서버 요청에 담긴 메타데이터 읽기 (0) | 2023.03.31 |