Docker - 웹서버와 NginX
22 Oct 2021 | devOpsDocker - 웹서버와 NginX
1. 웹서버란?
- 웹서버는 HTTP 요청을 읽어서 응답해주는 프로그램
- 웹서버 프로그램을 서버상에 설치하여, 특정 HTTP 요청에 따라, 서비스를 제공해주는 방식으로 웹서비스를 구현
- 상용으로 많이 쓰이는 웹서버 프로그램은 크게 apache, nginX가 있다
2. Apache와 NginX
- Apache는 오픈 소스 프로젝트
- Apache의 구동 방식
- Prefork MPM(Multi Processing Module) 방식
- HTTP 요청이 올 때마다, 프로세스를 복제하여, 각각 별도 프로세스에서 해당 HTTP 요청 처리
- Worker MPM(Multi Processing Module) 방식
- 하나의 HTTP 연결 후, 여러 요청 처리를 위해, 복제된 프로세스 내에서 쓰레드를 생성하여 여러 HTTP 요청을 처리하는 방식
-
NginX의 구동 방식
-
Event Driven 방식
- 하나의 프로세스로 동작하며, HTTP 요청을 event로 비동기식으로 처리
- 대부분의 HTTP 응답은 결국 html 파일을 서빙하므로 IO작업이다
- 따라서, IO 작업으로 event를 포워딩하고 요청순이 아닌 요청이 끝난 순으로 처리
- HTTP 요청마다 프로세스, 쓰레드 생성이 필요없으므로 리소스 관리에 장점이 있다
- 하나의 프로세스로 동작하며, HTTP 요청을 event로 비동기식으로 처리
-
NginX 기본 사용법
-
AWS EC2 ubuntu 20.04, nginx 1.18.0 기준
-
먼저 리눅스에 우분투 도커 컨테이너 생성
docker run -dit -p 80:8080 --name {이름} ubuntu:20.04
-
해당 컨테이너로 접속
docker exec -it {이름} /bin/bash
-
리소스 업데이트
apt-get update
-
컨테이너에 nginx 설치 (버전 확인 필요)
apt-get install nginx=1.18.0-0ubuntu1.2
-
컨테이너 내에 설치된 nginx의 conf 파일을 찾는다 (컨테이너 접속 상태에서)
find -name nginx.conf
-
vi 에디터로 실행 (vi가 없다면 vim 설치 필요)
vi /etc/nginx/nginx.conf
<— 경로 확인 필요-
user
: niginx를 돌리는 사람이 누구냐 (보통 www-data) -
worker_process
: 프로세스를 몇 개 만들꺼냐 (보통 auto) -
pid
: 시스템과 niginx 프로세스와의 연결고리 (기본으로 놔둠) -
include
: 설정이 여러 파일로 쪼개져있을 경우, 플러그인들 import시 -
events
: worker_connections 이벤트를 몇 개까지 처리할꺼냐 -
http
: 주로 여기 설정을 만힝 바꿈-
include /etc/nginx/conf.d/*.conf; conf.d 폴더에 내 사이트에 대한 conf 파일을 넣어서 넣는다
-
include /etc/nginx/sites-enabled/*; 기본으로 default 파일이 있는데 server 설정이 잡혀있다 sites-available의 default가 실제 파일 (심볼릭 링크가 걸려있는것)
-
default 파일의 server 설정 시 (sites-available의 default)
-
listen 8080 default_server
-
연결할 포트 설정
-
default_server는 모든 웹서버 요청을 받겠다는 의미
-
server_name {도메인}
도메인이 없을 경우_
(언더바) -
index {index.html}
해당 웹서버 주소 요청 시, 디폴트로 응답할 index 파일명 설정 -
location / { try_files $uri $uri/ =404; }
-
ex)
root /var/www/html; location /blog { root /var/www } # 123.0.0.1/blog/aaa.html로 접속시 root를 /var/www로 해서 # /var/www/blog/aaa.html 파일을 찾으라는 소리 location / { try_files $uri $uri/ =404; } # 123.0.0.1/bbb/aaa.html로 접속시 /blog에 매칭이 안되므로 # root인 /var/www/html/bbb/aaa.html을 찾는다
-
-
설정을 바꿨다면
service nginx restart
명령어로 재시작
-
3. NginX Reverse Proxy
- Proxy Server란 : 클라가 자신을 통해, 다른 네트워크 서비스에 접속하게 해줄 수 있는 서버
- Forward Proxy란 : 클라가 외부 인터넷에 직접 접근하는 것이 아닌, 프록시 서버에 외부 인터넷 접근 요청을 하고, 요청에 대한 응답을 프록시 서버가 받은 후, 클라에게 전달
- 클라가 자주 접속하는 외부 인터넷 서비가 있다면, 캐싱을 해서 성능 향상이 가능
- Reverse Proxy란 : 클라가 리버스 프록시에 요청을 하면 관련 요청에 따라 적절한 내부 서버에 접속하여 결과를 받은 후, 클라에게 전달
- 내부 DB 등에 직접 접속을 허용하지 않을 수 있으므로 보안에 유리
- 요청 트래픽을 관리할 수 있는 로드 밸런싱 등에 유리
* NginX Reverse Proxy : 포트로 구분하기 예제
# docker-compose.yml
version: "3"
services:
nginxproxy:
image: nginx:1.18.0
ports:
- "8080:8080"
- "8081:8081"
restart: always
volumes:
- "./nginx/nginx.conf:/etc/nginx/nginx.conf"
nginx:
depends_on:
- nginxproxy
image: nginx:1.18.0
restart: always
apache:
depends_on:
-nginxproxy
image: httpd:2.4.46
restart: always
docker-compose로 프록시 서버와 2개의 웹서버를 준비
호스트 PC에 ./nginx/nginx.conf
파일을 준비
user nignx;
worker_processes auto;
# 에러 로그를 저장
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
# 데이터에 대한 타입들을 기재
include /etc/nginx/mime.types;
# 없는 타입에 대해 디폴트 타입 설정
default_type application/octet-stream;
# 로그파일에 대한 포맷 설정
log_foramt main '$remote_addr - $remote_user [$time_local] "$request"'
'$status $body_bytes_sent "$http_referer"'
'"$http_user_agent" "$http_x_forwarded_for"';
# 접속 기록에 대한 로그 저장
access_log /var/log/nginx/access.log main;
# 운영체제에서 커널영역의 작업내용을 유저영역으로 보내지 않고 바로 전송
sendfile on;
# 클라의 요청에 대한 응답 제한시간 설정
keepalive_timeout 65;
upstream docker-nginx {
server nginx:80;
}
upstream docker-apache {
server apache:80;
}
server {
listen 8080;
location / {
proxy_pass http://docker-nginx;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_fpr;
proxy_set_header X-Forwarded_Host $server_name;
}
}
server {
listen 8081;
location / {
proxy_pass http://docker-apache;
# 서버 응답 헤더의 주소 변경
proxy_redirect off;
# 어느 프록시에서 요청했는지
proxy_set_header Host $host;
# 클라이언트 IP 주소
proxy_set_header X-Real-IP $remote_addr;
# 어떤 프록시들을 거쳐서 왔는지
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_fpr;
# 클라이언트의 호스트 이름
proxy_set_header X-Forwarded_Host $server_name;
}
}
}
다른 설정은 기본 설정과 유사하게 따라가나, upstream, server 설정이 중요
upstream의 docker-nginx
, docker-apache
는 임의로 지은 이름
위 docker-compose로 만든 nginx 컨테이너의 80 포트를 사용하겠다는 의미
default.conf 설정과 겹치지 않도록 include /etc/nginx/conf.d/*.conf
는 제거
외부 PC의 8080 접속에 대한 요청을 proxy_pass
로 docker-nginx로 보내고 nginx의 80으로 연결한다. apache도 마찬가지.
* NginX Reverse Proxy : 경로로 구분하기 예제
위 포트로 구분하기
예제의 설정에서 다음 부분을 변경
# docker-compose.yml
services:
nginxproxy:
ports:
- "80:80"
포트를 80포트만 열어준다 (나머지 동일)
nginx/nginx.conf 파일을 수정한다 (나머지 동일)
# /nginx/nginx.conf
server {
listen 80;
location /nginx/ {
proxy_pass http://docker-nginx;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_fpr;
proxy_set_header X-Forwarded_Host $server_name;
}
location /apache/ {
proxy_pass http://docker-apache;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_fpr;
proxy_set_header X-Forwarded_Host $server_name;
}
}
/nginx
에 대한 접속은 docker-nginx
가 처리한다
이를 위해서 docker-compose를 실행하고 실행된 nginx에 접속하여 location root에 nginx
폴더를 추가해준다. (/etc/nginx/conf.d/default.conf에서 location root 확인)
테스트를 위해 index.html을 만든다
{EC2인스턴스 IP}/nginx/index.html
로 접속하여 잘 나오는지 테스트 !
아파치도 비슷하게 기본 루트에 apache
폴더를 만들고 테스트 가능
* NginX Reverse Proxy : 경로로 구분하기 예제2 (내부 서버에 요청하는 경로 변경)
{IP}/nginx/index.html
로 프록시에 요청했을 때, 내부 nginx에서 {IP}/index.html
로 요청한것처럼 변경하기
이를 위해서는 nginx.conf의 server 설정에서 location 안에 rewrite
옵션을 추가해야함
rewrite regex URL [flag]
- regex : 정규표현식으로 매칭되는 URL 패턴 설정 (Perl의 정규표현식)
- URL : 변경할 URL 설정
- flag : 여러 location이 설정되어 있을 때, 변경된 URL이 다시 다른 location에 매칭될 수 있으므로 이를 어떻게 처리할지 설정
- break : 변경된 URL이 다시 다른 location에 매칭되지 않도록 끝냄
server {
location /nginx/ {
# /nginx/ 다음에 오는 문자를 $1이라 하고, $1로 바꿈
rewrite ^/nginx(.*)$ $1 break;
proxy_pass http://docker-nginx;
# ...
}
}
참고자료
인프런 - 풀스택을 위한 도커와 최신 서버 기술(리눅스, nginx, AWS, HTTPS, flask 배포) [풀스택 Part3]