DEV/Infrastructure

[NCP, 도커] 서버 생성부터 배포까지 (2 / 4)

Bi3a 2024. 1. 2. 22:52

반응형

이전 포스팅에서 이어집니다.

 

[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

도커 인스톨 성공
Hello from Docker가 우리를 맞이하면 인스톨에 성공한 것이다.

 

docker hello-world 삭제, 이미지 삭제

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

#도커 컨테이너 삭제
$ docker rm <컨테이너 이름명>

#도커에 설치되어 있는 이미지 조회
$ docker images

#도커 이미지 삭제
$ docker rmi hello-world

도커 이미지 제거
제거 완료

 

서버 도커 상태 조회

$ systemctl status docker

도커 구동 여부 확인
잘 돌아가고 있다.

 

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

$ systemctl enable docker

systemctl로 데몬에 올린다.

 

도커 컨테이너에 npm 설치, npm 실행

설치 디렉터리 생성, docker-compose.yml 생성

docker_projects/nginx_proxy_manager_1이라고 디렉터리를 만들어 준 후 이동했다.
이후 vim 편집기를 열어 docker-compose.yml 파일을 생성한 후 아래와 같이 yml파일 내용을 수정한다.

npm 설치 및 설정

 

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

docker-compose에서 도커 기본 설정

작성 후 종료 시에는 Ctrl + C를 통해 Escape(^C), :wq! + Enter를 입력해 내용을 저장하고 exit 한다.

 

docker compose 실행

이후 아래 명령어를 실행한다.

$ docker compose up -d
docker compose : 도커 실행 명령어를 여러 개를 묶어 실행하는 것으로, 컴포즈를 통해서 실행된 것들은 같은 네트워크 단위로 묶여 실행된다.

 

docker compose 실행 시 화면

 

NPM 접속

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

118.67.134.20

npm 접속 확인
축하한다. 거의 다 끝났다.

 

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

118.67.134.20:81

81번 포트로 접속한다.
얼렐레?

 

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

 

npm 접속 확인!
NPM 접속 성공! 오늘은 여기까지

 

요약(오늘의 작업 내용)

  1. 도커 설치
  2. 도커 컴포즈를 통한 포트포워딩 구성과 npm 설치
  3. 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

nginx 설정 파일 확인 시 구동 화면

 

일반적으로 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단계를 거쳐 자동적으로 관리자 콘솔에 연결될 수 있던 것이다.

  1. 컨테이너 외부 / 내부 포트 매핑 : 도커 외부의 81포트 → nginx 도커 내부의 81 포트
  2. 컨테이너 내부 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 설정이 되어있음을 확인할 수 있다.

 

(결론)

  1. npm 관리자 콘솔 이용을 위한 공인 IP:81 포트로의 접속 행위는 도커 외부 포트 -> 도커 내부 포트 ->  도커 내부 포트로 요청이 이동하며, 이 과정에서는 포트 매핑과 nginx의 리버스 프락시가 동작한다.
  2. 사실 docker-compose.yml에서 명시해 준 80, 81, 443 포트의 내 / 외부 매핑은 nginx image 설치 시 자동으로 설정되는 디폴트 값이다. → 즉, 명시적으로 작성한 것이지 생략해도 동일하게 설정된다.
  3. 포트 포워딩, 리버스 프락시, 프록시 패스의 개념을 잘 이해하자.
    • 포트 포워딩 : 외부(도커는 컨테이너)의 특정 포트로 접속하면 내부(도커는 컨테이너)의 특정 포트로 요청을 전달하는 것이다. (외부 -> 내부)
      • 만약 80:80, 81:81 이런 식으로 설정되어 있다면 이는 포트포워딩이 아닌, `포트 매핑`이라고 한다. (포트 매핑은 명시적인 설정이며, 별도 기재하지 않아도 디폴트 값으로 이렇게 설정된다)
    • 리버스 프락시 : nginx의 설정에서 외부에서 내부의 특정 포트로 들어온 요청을 내부의 서버의 특정 포트로 이동시키는 역할이자 정책이다. (내부 -> 내부)
      • 해당 기능은 여러 도메인을 내부 nginx 컨테이너에 연결되어 있는 각각의 다른 포트와 연결시킬 수 있다.
      • 한 개의 nginx에서 여러 개의 도메인을 운영할 수 있는 장점이 있다.
    • 프락시 패스 : 리버스 프락시의 설정에 의해 해당 요청에 대한 트래픽을 내부의 다른 포트로 전달하는 행위이다.
      • 즉, 리버스 프락시가 정책이면 프록시 패스는 행위이다.

 

다음 포스팅에서는 NPM을 이용한 프록시 호스트 설정(도메인과 연결 포트, SSL)부터 다루었다.

 

[NCP, 도커] 서버 생성부터 배포까지 (야매판, 3 / 4)

이전 포스팅에서 이어집니다. [NCP, 도커] 서버 생성부터 배포까지 (야매판, 2 / 4) 이전 포스팅에서 이어집니다. [NCP, 도커] 서버 생성부터 배포까지 (야매판, 1 / 3) NCP 서버 생성, 도메인 레코드 설

doinitright.tistory.com


 

반응형