# git 은 ubuntu 에는 기본으로 설치되어있다. 설치 루트를 확인하자. whichgit# java 설치하기 sudoaptupdate&&upgradesudoaptinstalldefault-jdk
1-2. 소스코드 배포, 빌드 및 실행
# git repository 를 clone gitclonehttps://github.com/next-step/infra-subway-deploy.git# 특정 브랜치만 클론하기 gitclone-bminiminis--single-branchhttps://github.com/next-step/infra-subway-deploy.git# 가져온 프로젝트 빌드$./gradlewcleanbuild# 테스트 없이 빌드$./gradlewcleanbuild-xtest# 빌드된 jar파일을 찾아보기$find./*-name"*jar"# jar file 실행하기$java-jar [jar파일명] &# 어플리케이션이 정상적으로 실행되었는지 확인하기 $curlhttp://localhost:8080
일반적으로 Proxy 서버는 LAN -> WAN 으로의 요청을 대리하여 처리해준다. 예를 들어 내가 집에서 와이파이로 특정 국가의 서비스를 이용하려고 하는데, 해당 서비스에서 한국의 IP를 막아두었다면, 나는 VPN 등의 서비스를 통해서 다른 국가의 IP로 우회하여 해당 서비스에 접근하게 된다.
Reverse Proxy의 경우는 그 반대라고 할 수 있다. WAN -> LAN 으로의 요청을 대리하여 처리해준다. 클라이언트로부터 어플리케이션 서버로 요청이 들어올 때, 중간에서 reverse proxy server 가 개입하여 다양한 전후처리를 해준다. 요청을 처리한 뒤, 어플리케이션 서버 역시 응답을 클라이언트로 바로 전달하지 않고, reverse proxy server 로 전달한다. 요청을 받은 reverse proxy server 는 서버 대신 클라이언트에게 응답을 전달한다.
Reverse Proxy 를 사용하면 결국 클라이언트와 어플리케이션 서버 사이에서 필요한 다양한 전후처리를 할 수 있다. 어플리케이션 서버는 정말 비즈니스 로직, 그 자체에만 집중하면 된다.
Reverse Proxy vs. Load Balancer
reverse proxy 는
TLS 암호화 등을 맡아 보안성을 향상시키거나,
확장성을 향상시키거나,
압축, SSL 처리로 인한 백엔드 리소스 확보, 캐싱처리 등을 통해 웹의 속도를 향상시키는 역할을 한다.
# 1. 우선 도커를 설치한다. $sudoapt-getupdate&& \sudoapt-getinstall-yapt-transport-httpsca-certificatescurlsoftware-properties-common&& \curl-fsSLhttps://download.docker.com/linux/ubuntu/gpg|sudoapt-keyadd-&& \sudoapt-keyfingerprint0EBFCD88&& \sudoadd-apt-repository"deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release-cs) stable"&& \sudoapt-getupdate&& \sudoapt-getinstall-ydocker-ce&& \sudousermod-aGdockerubuntu&& \sudo curl -L "https://github.com/docker/compose/releases/download/1.23.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose && \
sudochmod+x/usr/local/bin/docker-compose&& \sudoln-s/usr/local/bin/docker-compose/usr/bin/docker-compose# 2. 아래와 같은 내용으로 Dockerfile 을 생성한다. FROMnginxCOPYnginx.conf/etc/nginx/nginx.conf# 3. nginx.conf 파일을 아래와 같이 작성한다. events{}http{upstreamapp{server172.17.0.1:8080; }server{listen80;location/{proxy_passhttp://app; } }}# 4. nextstep/reverse-proxy 라는 이름으로 도커 이미지를 빌드한 뒤, 80포트로 실행한다. $dockerbuild-tnextstep/reverse-proxy.$dockerrun-d-p80:80nextstep/reverse-proxy
4. Reverse Proxy에 TLS 설정
클라이언트 - 서버 간의 통신은 언제나 해킹의 위험에 노출되어있다. 그냥 평문으로 통신할 경우, 패킷이 가로채질 수 있으므로, 반드시 TLS 암호화를 하여 통신하도록 한다.
4-1. letsencrypt 를 활용하여 무료로 TLS 인증서 받기
# 1. docker 명령어를 통해서 내 도메인인 "subway-mhson.kro.kr"에 대한 인증서를 요청한다. dockerrun-it--rm--namecertbot \-v'/etc/letsencrypt:/etc/letsencrypt' \-v'/var/lib/letsencrypt:/var/lib/letsencrypt' \ certbot/certbot certonly -d 'subway-mhson.kro.kr' --manual --preferred-challenges dns --server https://acme-v02.api.letsencrypt.org/directory
# 2. 위의 명령어를 실행하면, 아래와 같은 결과가 나온다. # 도메인 구입한 사이트에서 DNS TXT 레코드에 안내된 값을 추가해준다. Savingdebuglogto/var/log/letsencrypt/letsencrypt.logRequestingacertificateforsubway-mhson.kro.kr----------------------------------------PleasedeployaDNSTXTrecordunderthename:_acme-challenge.infra.subway-mhson.kro.kr.withthefollowingvalue:jiRlP5PscTZ9f_kh1GfNbmBl6YiSt4i3MKo2irIHmgQBeforecontinuing,verifytheTXTrecordhasbeendeployed.DependingontheDNSprovider,thismaytakesometime,fromafewsecondstomultipleminutes.Youcancheckifithasfinisheddeployingwithaidofonlinetools,suchastheGoogleAdminToolbox:https://toolbox.googleapps.com/apps/dig/#TXT/_acme-challenge.subway-mhson.kro.kr.Lookforoneormoreboldedline(s) belowtheline';ANSWER'.Itshouldshowthevalue(s) you've just added.- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Press Enter to Continue
# 3. 아래와 같은 결과가 나오면 성공! Successfullyreceivedcertificate.Certificateissavedat:/etc/letsencrypt/live/subway-mhson.kro.kr/fullchain.pemKeyissavedat:/etc/letsencrypt/live/subway-mhson.kro.kr/privkey.pemThiscertificateexpireson2023-06-03.Thesefileswillbeupdatedwhenthecertificaterenews.NEXTSTEPS:- This certificate will not be renewed automatically. Autorenewal of --manual certificates requires the use of an authentication hook script (--manual-auth-hook) but one was not provided. To renew this certificate, repeat this same certbot command before the certificate's expiry date.
----------------------------------------IfyoulikeCertbot,pleaseconsidersupportingourworkby:*DonatingtoISRG/Let's Encrypt: https://letsencrypt.org/donate * Donating to EFF: https://eff.org/donate-le- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
DNS를 설정하는 사이트에서 DNS TXT 레코드를 추가한 후, 제대로 반영되었는지 dig 명령어로 확인한 후에 인증서 설정 진행을 계속한다.
$dig-ttxt_acme-challenge.example.com+short
4-2. 생성된 인증서를 활용하여 Reverse Proxy 에 TLS 설정하기
# 1. 우선 인증서 현재 경로로 옮기기 $cp/etc/letsencrypt/live/[도메인주소]/fullchain.pem./$cp/etc/letsencrypt/live/[도메인주소]/privkey.pem./# 2. 위에서 생성했던 Dockerfile 을 아래와 같이 수정한다. FROMnginxCOPYnginx.conf/etc/nginx/nginx.confCOPYfullchain.pem/etc/letsencrypt/live/[도메인주소]/fullchain.pemCOPYprivkey.pem/etc/letsencrypt/live/[도메인주소]/privkey.pem# 3. nginx.conf 도 아래와 같이 수정한다. events{}http{upstreamapp{server172.17.0.1:8080; }# Redirect all traffic to HTTPSserver{listen80;return301https://$host$request_uri; }server{listen443ssl; ssl_certificate/etc/letsencrypt/live/[도메인주소]/fullchain.pem;ssl_certificate_key/etc/letsencrypt/live/[도메인주소]/privkey.pem;# Disable SSLssl_protocolsTLSv1TLSv1.1TLSv1.2;# 통신과정에서 사용할 암호화 알고리즘ssl_prefer_server_cipherson;ssl_ciphersECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;# Enable HSTS# client의 browser에게 http로 어떠한 것도 load 하지 말라고 규제합니다.# 이를 통해 http에서 https로 redirect 되는 request를 minimize 할 수 있습니다.add_headerStrict-Transport-Security"max-age=31536000"always;# SSL sessionsssl_session_cacheshared:SSL:10m;ssl_session_timeout10m; location/{proxy_passhttp://app; } }}# 4. 방금 전에 띄웠던 도커 컨테이너를 중지 + 삭제하고, 새로운 설정을 반영하여 다시 띄운다. $dockerstopproxy&&dockerrmproxy$dockerbuild-tnextstep/reverse-proxy:0.0.2.$dockerrun-d-p80:80-p443:443--nameproxynextstep/reverse-proxy:0.0.2
5. 운영 데이터베이스 구성하기
일반적으로 데이터베이스를 컨테이너로 다루지는 않는다. 컨테이너는 사라지면 그만이니, 데이터베이스처럼 영속성을 가진 데이터를 다루기에는 적절하지 않은 면이 있다. 하지만, 지금은 데이터베이스가 중요한 것이 아니라 인프라 구축에 대한 실습을 하고 있는 것이므로, 도커를 이용해 빠르게 데이터베이스를 구축해보자.
# 1. 데이터베이스 실행하기 $dockerrun-d-p3306:3306brainbackdoor/data-subway:0.0.1# 2. 데이터베이스 내부 접속하기 $dockerps-al$dockerexec-it [container id]/bin/bash# 3. mysql 실행하여 데이터 확인하기 mysql-u [id] -p (password입력)showdatabases;usesubway;showtables;select*fromline;
6. 로컬/운영 설정 파일 나누기
지금까지의 실습에서는 데이터베이스의 데이터를 조회하지는 않았다. 이제 로컬 개발환경과 운영 환경이 구분되었으므로 application.properties 설정파일을 통해 운영 환경별로 데이터베이스 설정을 분리해본다.
# privkey.pem 의 권한 확인 결과 -rw-rw-r--1ubuntuubuntu54Sep2722:09Dockerfile-rw-r--r--1rootroot5599Sep2722:27fullchain.pem-rw-rw-r--1ubuntuubuntu155Sep2722:10nginx.conf-rw-------1rootroot1704Sep2722:28privkey.pem# 권한을 부여한다.
결과는? 정상적으로 동작된다.
PUBLIC-2a:~$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bc1885093f7d nextstep/reverse-proxy:0.0.2 "/docker-entrypoint.…" 5 seconds ago Up 4 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp proxy
비록 나는 시간이 없어서 적용해보지 못했지만, 아래와 같은 설정들을 추가해보면 개발시나 운영시에 편리해진다.
9-1. [추가] 데이터베이스 테이블 스키마 버전관리
보통 운영 데이터베이스는 JPA등과 같은 ORM 을 사용하여 기존의 테이블을 변경하지 않는다. 데이터가 유실되거나 참조 무결성 제약 등으로 인해 어려움이 있기 때문이다. 그래서 보통은 로컬에서는 H2 와 같은 in-memory 데이터베이스를 이용하여 빠르게 개발을 하고, 운영 데이터베이스는 점진적으로 migration 을 해나간다.
이때, 운영 데이터베이스의 테이블 스키마에 대해서도 버전관리를 하는 것이 필요한데, 이때 사용하는 것이 바로 Flyway 이다.