이전 포스팅에서 이어집니다.
[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 |