- 이전 포스팅에서 이어집니다.
- 서버에 도커 설치
- docker install, docker run hello-world
- docker hello-world 삭제, 이미지 삭제
- 서버 도커 상태 조회
- 서버 재부팅 시 도커가 알아서 실행되도록 설정
- 도커 컨테이너에 npm 설치, npm 실행
- 설치 디렉터리 생성, docker-compose.yml 생성
- docker compose 실행
- NPM 접속
- 요약(오늘의 작업 내용)
- (부록) 도커 컴포즈로 nginx 포트 매핑 구성, npm 설치
- (부록) NPM은 어찌 81을 관리자 접속 포트로 인식할까?
- (결론)
- 이전 포스팅에서 이어집니다.
- 서버에 도커 설치
- docker install, docker run hello-world
- docker hello-world 삭제, 이미지 삭제
- 서버 도커 상태 조회
- 서버 재부팅 시 도커가 알아서 실행되도록 설정
- 도커 컨테이너에 npm 설치, npm 실행
- 설치 디렉터리 생성, docker-compose.yml 생성
- docker compose 실행
- NPM 접속
- 요약(오늘의 작업 내용)
- (부록) 도커 컴포즈로 nginx 포트 매핑 구성, npm 설치
- (부록) NPM은 어찌 81을 관리자 접속 포트로 인식할까?
- (결론)
이전 포스팅에서 이어집니다.
[NCP, 도커] 서버 생성부터 배포까지 (1 / 4)
NCP 서버 생성, 도메인 레코드 설정 및 IP 할당 NCP 서버 생성 공인 IP 추가 신청 Server > Public IP Q. 서버 접속용 공인 IP를 받았는데 공인 IP를 추가 신청하는 이유? A. 애초에 다른 개념이다. 1. 서버 접
doinitright.tistory.com

서버에 도커 설치
서버 이미지 기반 OS에 맞는 도커를 서버 안에 설치해 준다.
필자는 CentOS 7.3 기반 서버이기 때문에 이에 맞게 찾은 후 진행한다.
docker install, docker run hello-world
[도커 독스]
Home
Home page for Docker's documentation
docs.docker.com
[도커 CentOS 기반 설치]
Install Docker Engine on CentOS
Learn how to install Docker Engine on CentOS. These instructions cover the different installation methods, how to uninstall, and next steps.
docs.docker.com
[명령어]
# uninstall old versions $ sudo yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine # Set up repository sudo yum install -y yum-utils sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo # Install Docker Engine sudo yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin # Start Docker sudo systemctl start docker # hello-world 이미지 run (도커 정상 작동 확인용) sudo docker run hello-world

docker hello-world 삭제, 이미지 삭제
도커에 깔려있는 hello-world 컨테이너와, 이미지를 삭제한다.
tab 키를 누르면 작성 중인 컨테이너 이름이나 이미지 이름을 자동완성 시켜주는 기능을 제공한다.
#도커 현재 실행중인 컨테이너 조회 $ docker ps -a #도커 컨테이너 삭제 $ docker rm <컨테이너 이름명> #도커에 설치되어 있는 이미지 조회 $ docker images #도커 이미지 삭제 $ docker rmi hello-world

서버 도커 상태 조회
$ systemctl status docker

서버 재부팅 시 도커가 알아서 실행되도록 설정
$ systemctl enable docker

도커 컨테이너에 npm 설치, npm 실행
설치 디렉터리 생성, docker-compose.yml 생성
docker_projects/nginx_proxy_manager_1이라고 디렉터리를 만들어 준 후 이동했다.
이후 vim 편집기를 열어 docker-compose.yml 파일을 생성한 후 아래와 같이 yml파일 내용을 수정한다.

docker_projects/nginx_proxy_manager_1/docker-compose.yml
version: '3.8' services: app: image: 'jc21/nginx-proxy-manager:latest' # 실행할 이미지 restart: unless-stopped ports: - '80:80' # for http - '81:81' # npm 관리자 콘솔 접속 - '443:443' # for https volumes: # 백업 파일 - ./data:/data - ./letsencrypt:/etc/letsencrypt

작성 후 종료 시에는 Ctrl + C를 통해 Escape(^C), :wq! + Enter를 입력해 내용을 저장하고 exit 한다.
docker compose 실행
이후 아래 명령어를 실행한다.
$ docker compose up -d
docker compose : 도커 실행 명령어를 여러 개를 묶어 실행하는 것으로, 컴포즈를 통해서 실행된 것들은 같은 네트워크 단위로 묶여 실행된다.

NPM 접속
1. 브라우저에서 공인 ip 주소를 검색해서 들어가 보자.
118.67.134.20

2. 이번에는 공인 ip:81(포트번호)로 접속해 보자.
118.67.134.20:81

최초 접속 시 기본 id, pw는 각각 admin@example.com, changeme이다.
이후 로그인해서 비밀번호 및 계정을 변경하면 된다.

요약(오늘의 작업 내용)
- 도커 설치
- 도커 컴포즈를 통한 포트포워딩 구성과 npm 설치
- npm 접속
(부록) 도커 컴포즈로 nginx 포트 매핑 구성, npm 설치
도커 컨테이너 외부 80, 81, 443 포트를 열어 각 포트로 접속되는 네트워크 트래픽을
도커 컨테이너 내부의 80, 81, 443 포트로 포트매핑 해주었다.
version: '3.8' services: app: image: 'jc21/nginx-proxy-manager:latest' # 실행할 이미지 restart: unless-stopped ports: # nginx 도커 컨테이너 외부:내부의 포트포워딩을 나타냄 (현재는 동일하기 때문에 포트 매핑) - '80:80' # for http - '81:81' # npm 관리자 콘솔 접속, - '443:443' # for https volumes: # 백업 파일 - ./data:/data - ./letsencrypt:/etc/letsencrypt
(부록) NPM은 어찌 81을 관리자 접속 포트로 인식할까?
Q. compose.yml에서는 단순히 nginx 도커 컨테이너의 외부:내부에 포트포워딩만 설정했을 뿐인데
어떻게 81 포트로 접속 시 관리자 콘솔로 접속하게끔 설정되는 걸까?
A. 정답은 nginx의 *리버스 프락시에 있다.
nginx 리버스 프락시: 도커 컨테이너의 특정 포트로 들어온 요청을 내부의 서버로 보내주는 것(프락시)이다.
nginx의 리버스 프락시 정책에 의해 nginx 이미지로 인해 nginx를 설치하게 되면, 기본적으로 도커 내부 컨테이너의 81 포트로 접속하게끔 *프락시 패스가 설정되어 있기 때문에 81 포트로 접속한 외부 사용자는 관리자 콘솔로 연결되는 것이다.
자세한 이해를 위해 docker compose 이후의 설치된 nginx의 설정 파일을 직접 확인해 보자.
# NPM의 이름 확인 $ docker ps -a # 도커 NPM의 bash를 직접 실행한다. $ docker exec -it <NPM 이름명> /bin/bash

일반적으로 npm의 설정 파일인. conf 파일은 etc/nginx 파일 예하에 있으므로 해당 디렉터리를 탐색해 본다.
# /etc/nginx 예하 파일 탐색 $ ls /etc/nginx # conf.d 확인 # 디렉토리로 이동 $ cd /etc/nginx/conf.d # 예하 디렉토리의 파일 탐색 $ ls # default.conf, production.conf 두개의 파일 확인
default.conf와 production.conf 파일을 찾았다. 두 개 다 열어본다.
# cat 편집기로 연다. (vim이 설치되어 있지 않았다) $ cat /etc/nginx/conf.d/production.conf $ cat /etc/nginx/conf.d/default.conf
production.conf
server { listen 81 default; listen [::]:81 default; # 여기서 server_name은 도메인명이다. server_name nginxproxymanager; root /app/frontend; access_log /dev/null; location /api { return 302 /api/; } location /api/ { add_header X-Served-By $host; proxy_set_header Host $host; proxy_set_header X-Forwarded-Scheme $scheme; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $remote_addr; # 프록시 패스가 127.0.0.1:3000 으로 연결되도록 설정되어 있다. proxy_pass http://127.0.0.1:3000/; # ... 생략 }
production.conf에는 81 포트로 연결 시 127.0.0.1의 3000 포트로 `프록시 패스`되는 리버스 프록시가 설정되어 있음을 알 수 있었다.
따라서, nginx 이미지를 설치만 하면 기본적으로 외부의 공인 IP의 81포트로 접속 시, 아래와 같은 2단계를 거쳐 자동적으로 관리자 콘솔에 연결될 수 있던 것이다.
- 컨테이너 외부 / 내부 포트 매핑 : 도커 외부의 81포트 → nginx 도커 내부의 81 포트
- 컨테이너 내부 nginx 리버스 프록시 : nginx 내부의 81 포트 → nginx 내부의 127.0.0.1의 3000번 포트
- 127.0.0.1 = localhost이다. 즉 nginx 내부 로컬호스트의 3000포트로 연결되는 것
- 이후 npm에서 제공하는 포트 번호와 접속할 도메인의 매핑 기능 또한 이런 conf파일 설정에 기반한다.
- npm에서 변경하면 conf파일이 수정되는 구조
이번에는 default.conf를 열어보자.
default.conf
# "You are not configured" page, which is the default if another default doesn't exist server { listen 80; listen [::]:80; set $forward_scheme "http"; set $server "127.0.0.1"; set $port "80"; server_name localhost-nginx-proxy-manager; access_log /data/logs/fallback_access.log standard; error_log /data/logs/fallback_error.log warn; include conf.d/include/assets.conf; include conf.d/include/block-exploits.conf; include conf.d/include/letsencrypt-acme-challenge.conf; location / { index index.html; root /var/www/html; } } # First 443 Host, which is the default if another default doesn't exist server { listen 443 ssl; listen [::]:443 ssl; set $forward_scheme "https"; set $server "127.0.0.1"; set $port "443"; server_name localhost; access_log /data/logs/fallback_access.log standard; error_log /dev/null crit; include conf.d/include/ssl-ciphers.conf; ssl_reject_handshake on; return 444; }
default.conf에도 역시, 내부의 80, 443 포트로 들어오는 요청에 대해 localhost로의 설정이 되어 있었다.
443 포트는 https 요청을 매핑하기 때문에 ssl 설정이 되어있음을 확인할 수 있다.
(결론)
- npm 관리자 콘솔 이용을 위한 공인 IP:81 포트로의 접속 행위는 도커 외부 포트 -> 도커 내부 포트 -> 도커 내부 포트로 요청이 이동하며, 이 과정에서는 포트 매핑과 nginx의 리버스 프락시가 동작한다.
- 사실 docker-compose.yml에서 명시해 준 80, 81, 443 포트의 내 / 외부 매핑은 nginx image 설치 시 자동으로 설정되는 디폴트 값이다. → 즉, 명시적으로 작성한 것이지 생략해도 동일하게 설정된다.
- 포트 포워딩, 리버스 프락시, 프록시 패스의 개념을 잘 이해하자.
- 포트 포워딩 : 외부(도커는 컨테이너)의 특정 포트로 접속하면 내부(도커는 컨테이너)의 특정 포트로 요청을 전달하는 것이다. (외부 -> 내부)
- 만약 80:80, 81:81 이런 식으로 설정되어 있다면 이는 포트포워딩이 아닌, `포트 매핑`이라고 한다. (포트 매핑은 명시적인 설정이며, 별도 기재하지 않아도 디폴트 값으로 이렇게 설정된다)
- 리버스 프락시 : nginx의 설정에서 외부에서 내부의 특정 포트로 들어온 요청을 내부의 서버의 특정 포트로 이동시키는 역할이자 정책이다. (내부 -> 내부)
- 해당 기능은 여러 도메인을 내부 nginx 컨테이너에 연결되어 있는 각각의 다른 포트와 연결시킬 수 있다.
- 한 개의 nginx에서 여러 개의 도메인을 운영할 수 있는 장점이 있다.
- 프락시 패스 : 리버스 프락시의 설정에 의해 해당 요청에 대한 트래픽을 내부의 다른 포트로 전달하는 행위이다.
- 즉, 리버스 프락시가 정책이면 프록시 패스는 행위이다.
- 포트 포워딩 : 외부(도커는 컨테이너)의 특정 포트로 접속하면 내부(도커는 컨테이너)의 특정 포트로 요청을 전달하는 것이다. (외부 -> 내부)
다음 포스팅에서는 NPM을 이용한 프록시 호스트 설정(도메인과 연결 포트, SSL)부터 다루었다.
[NCP, 도커] 서버 생성부터 배포까지 (야매판, 3 / 4)
이전 포스팅에서 이어집니다. [NCP, 도커] 서버 생성부터 배포까지 (야매판, 2 / 4) 이전 포스팅에서 이어집니다. [NCP, 도커] 서버 생성부터 배포까지 (야매판, 1 / 3) NCP 서버 생성, 도메인 레코드 설
doinitright.tistory.com
'DEV > Infrastructure' 카테고리의 다른 글
[NCP, 도커] 서버 생성부터 배포까지 (4 / 4) (1) | 2024.01.08 |
---|---|
[NCP, 도커] 서버 생성부터 배포까지 (3 / 4) (0) | 2024.01.07 |
[NCP, 도커] 서버 생성부터 배포까지 (1 / 4) (1) | 2024.01.02 |
[트러블슈팅][Github Actions] ghcr.io 활용 도커파일 빌드 시 unexpected status from POST request : 403 error 해결 (1) | 2023.12.27 |
[트러블슈팅][Docker] 프로젝트 빌드 시 error code 137 해결 방법 (0) | 2023.12.26 |