지난 글에서 엔드포인트를 생성해서 EC2 컨테이너에서 S3버킷에 접근하는데 성공했었다. 이제 EC2 인스턴스에서 nginx를 프록시 서버로 사용해 S3를 서빙해보려고 한다. 말이 많이 복잡한데... 구현하려는 구조는 아래와 같다.
VPC와 endpoint에 대한 이해는 아직 약간은 부족해서 자세히 그리지 않았다.
물론 S3 자체도 파일 서버의 역할을 수행할 수 있지만, 굳이 EC2에서 접근하려는 이유는
1. S3를 퍼블릭으로 여는 것은 보안적으로 좋은 선택이 아니다.
2. nginx의 캐싱 기능을 사용해서 요청 수를 줄일 수 있다.
3. 이미 nginx를 사용하고 있다...
사실 3번이 아니라면 cloudfront 등의 다른 서비스의 도입을 고려해봤을 것 같다. 그러나 이미 웹서버로 nginx를 쓰고 있고, 당분간은 요청이 많지 않기 때문에 우선 nginx를 프록시 서버로 쓰기로 했다.
nginx/Dockerfile
# 사용할 이미지
FROM nginx:1.21.6-alpine
# 기본 설정 삭제
RUN rm -rf /etc/nginx/conf.d
docker-compose.yml
version: "3"
services:
nginx:
container_name: nginx
restart: unless-stopped
stdin_open: true
build: ./nginx
volumes:
- ./nginx:/etc/nginx/conf.d
- ./client/build:/usr/share/nginx/html # 프론트엔드 빌드 파일
ports:
- 80:80
command: '/bin/sh -c ''while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g "daemon off;"'''
server {
listen 80;
server_name "www.example.com";
server_tokens off;
set $bucket "<bucket-name>.s3.ap-northeast-2.amazonaws.com";
# 파일 서빙 - S3
location /file/ {
rewrite /file/(.*) /$1 break;
proxy_pass https://$bucket;
}
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
...
}
이제 nginx가 www.example.com/file/~~~~~
로 들어오는 요청에 대해 <bucket-name>.s3.ap-northeast-2.amazonaws.com/~~~~~
의 응답을 대신 받아준다.
S3에서 오는 응답을 그대로 전달하게 되면, 헤더에 여러가지 정보가 같이 들어온다. 클라이언트에 그대로 전달할 필요는 없기 때문에 몇가지 설정을 통해 지워주려고 한다.
# 파일 서빙 - S3
location /file/ {
...
resolver 8.8.8.8;
proxy_http_version 1.1;
proxy_redirect off;
proxy_set_header Connection "";
proxy_set_header Authorization '';
proxy_set_header Host $bucket;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_hide_header x-amz-id-2;
proxy_hide_header x-amz-request-id;
proxy_hide_header x-amz-meta-server-side-encryption;
proxy_hide_header x-amz-server-side-encryption;
proxy_hide_header Set-Cookie;
proxy_ignore_headers Set-Cookie;
proxy_intercept_errors on;
add_header Cache-Control max-age=31536000;
proxy_pass https://$bucket;
}
command: '/bin/sh -c ''while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g "daemon off;"'''
창의적인 방법이네요