Docker Compose로 localhost Nginx 리버스 프록시 구성

Jeongkuk Seo
sjk5766
Published in
9 min readJun 8, 2019

이 포스팅에서 docker compose를 이용하여 위와 같은 구조를 만들겠습니다. 내부에 Docker로 3개의 컨테이너를 올립니다. 각각 Nginx(reverse proxy)와 Nginx(서버) 그리고 php-fpm 컨테이너를 올립니다.

reverse proxy 서버는 80번 포트를 open하고 뒷 단의 Nginx 서버는 8080 포트를 오픈합니다. 크롬에서 localhost를 입력하면 Reverse Proxy 서버가 뒷 단의 Nginx의 phpinfo() 결과를 보여주는 것이 목표입니다.

혹시 docker compose를 잘 모르시는 분은 아래 포스트를 읽고 봐주세요.

1. 디렉토리 구조

docker-compose.yml 파일 설명하기 전에 위와 같이 디렉토리 구조를 잡았습니다. nginx 디렉토리의 default.conf는 php 설정을 위해, proxy 디렉토리의 nginx.conf는 proxy 설정 때문에 준비하였습니다. source 디렉토리의 index.html과 index.php는 최종 결과를 위해 작성했습니다. 이 내용들은 뒤에서 살펴보겠습니다.

2. docker-compose.yml 소개

우선 docker-compose.yml 내용 먼저 작성합니다.

version: '3'
services:
proxy:
image: nginx:latest
ports:
- "80:80"
volumes:
- ./proxy/nginx.conf:/etc/nginx/nginx.conf
web:
image: nginx:latest
expose:
- "8080"
volumes:
- ./source:/source
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
php:
image: php:7.3-fpm
expose:
- "9000"
volumes:
- ./source:/source

Proxy: Reverse Proxy 서버 역할을 할 Nginx Container 입니다. 80 포트를 host와 공유하고 있습니다. volumes 에서는 host pc의 proxy/nginx.conf 파일을 container의 /etc/nginx/nginx.conf로 공유하고 있습니다.

web: 실제 phpinfo()의 결과를 해석해서 돌려줄 웹 서버입니다. expose 8080 옵션으로 다른 container와 8080포트를 통해 통신할 수 있습니다. volumes에서는 source 디렉토리를 공유하고 있고, php 설정을 위해 default.conf를 공유하고 있습니다.

php: php container 입니다. Nginx에서 구동되기 때문에 php-fpm을 설치했습니다. 9000번 포트를 다른 container에게 open 하고 있으며 source 디렉토리를 공유합니다.

3. nginx.conf 소개

Reverse Proxy 서버 역할을 할 Nginx의 nginx.conf 인데요.. medium 블로그에서 오른쪽으로 길어지면 줄바꿈되서 좀 보기 불편하네요. 그대로 복사해서 notepad++, editplus, IDE에 붙이시면 정상적으로 보일겁니다.

user  nginx;
worker_processes 1;
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;
upstream docker-nginx {
server web:8080;
}
server {
listen 80;
server_name localhost;
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_for;
}

}
log_format 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;
include /etc/nginx/conf.d/*.conf;
}

위 에서 굵게 표신된 부분만 변경한 부분이고 나머지는 container 올린 시점부터 이미 존재하던 설정들입니다. 따라서 proxy 설정을 위해 굵게 표시한 부분만 살펴보겠습니다.

upstream docker-nginx {
server web:8080;
}

docker-nginx 라는 이름을 가진 upstream을 정의합니다. server web:8080으로 되어있는데 여기서 web은 docker-compose.yml에서 정의한 웹 서버 nginx의 이름입니다. 만약 docker-compose.yml 에서 이름을 web이 아닌 nginx로 줬다면 server nginx:8080; 으로 명시해줘야 합니다.

server {
listen 80;
server_name localhost;
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_for;
}

}

Reverse Proxy 서버는 80번 포트를 listen 하고 server_name은 localhost로 지정하였습니다. proxy_pass 설정을 보면 / 로 들어올 경우 위에서 정의한 upstream docker-nginx(web이라는 이름을 가진 container의 8080 포트) 로 proxy 합니다.

4. default.conf 소개

웹 서버 역할을 할 Nginx의 default.conf 내용입니다.

server {
listen 8080;

server_name example.com www.example.com;
root /source;

location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass php:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}


error_log /var/log/nginx/api_error.log;
access_log /var/log/nginx/api_access.log;
}

주요한 설정만 보면 nginx가 8080 포트에서 listen 하고 있으며 root 디렉토리는 /source 를 사용하고 있습니다. 그리고 php 해석을 위해 fastcgi_pass 부분을 보면, php-fpm이 동작하는 container의 이름 php:9000 으로 설정이 되어있습니다. php-fpm의 이름은 docker-compose.yml 에서 지정 했습니다.

5. source 디렉토리

php-fpm과 nginx에서 아래와 같이 source 디렉토리를 공유했습니다.

volumes:
- ./source:/source

index.php 내용은 간단히 phpinfo() 결과를 출력하고 있습니다.

<?php
echo phpinfo();
?>

6. 실행

이제 위의 내용으로 다 준비가 되어있다고 했을 때 디렉토리로 들어가 docker compose로 실행합니다.

그 다음 host PC에서 크롬을 실행한 뒤 localhost를 입력합니다.

사실 이걸론 확인할 수 없는게 proxy가 제대로 되지 않을 경우 proxy 서버 역할을 하는 nginx의 default 페이지가 출력될 수 있습니다. 정확히 확인을 하기 위해 index.php를 호출합니다.

잘 되네요. 누군가에게 도움이 되길 바랍니다 ^^

--

--