[Aws cloud school 40일차]_포트포워딩의 기능 이해하기

miniPig·2024년 7월 10일

AWS cloud school

목록 보기
23/31

[실습 1] 아래 상황 구현하기

→ docker vm위에 올린 app과 docker2 vm위에 올린 mydb를 연결하는 것이다.

→ docker vm의 app은 도커 파일로 이미지 빌드할 수 있다.

→ 이미지 빌드하면서 mydb를 바라보도록 설정해주면 mydb와 연동할 수 있다.

[실습1-1] 첫번째 도커에는 app

포트 포워딩!

첫번째 vm에 80포트로 들어오면 myapp의 5000포트로 들어갈 수 있도록 포트포워딩!

(포트포워딩 테이블 존재)

sudo docker run -d -p 80:5000 \
--name myapp \
--add-host db-svc:DB의IP \
ekchoi3912/myapp:v1

# 여기에서 DB의 IP 주소는 docker2에서 ip a 명령어를 통해 알수 있다.
# DB는 같은 리전의 인스턴스 위에서 동작하고 있으므로 내부 ip 주소로 통신 가능하다!
# DB 컨테이너를 포함하고 있는 docker2 vm 인스턴스 내부 ip 주소를 (DB의IP)에 입력해준다.

[실습1-2]두번째 도커에는 db (이미지 다운받아서)

포트 포워딩!

도커 host 안에 있는 컨테이너는 외부에서 접근 불가능함

따라서 외부에서 접근하기 위해서는 포트포워딩을 통해 외부에 노출시켜줘야 함

chohyeon1208@docker2:~$ docker run -d --name mydb -p 3306:3306 ekchoi3912/mydb:v1

[실습1-3] app.py를 Dockerfile을 이용해서 이미지 빌드하고 프로세스화!

베이스 이미지는..!

# 베이스 이미지 설정
FROM python:3.8
docker run -d -p 80:5000 --name myapp --add-host db-svc:10.128.15.213 app

코드 파일

파이썬을 image pull해오면 밑 os로 데비안이 자동으로 따라옴

1) docker vm 내부 컨테이너 중 myapp 컨테이너 app.py 안에 mysql db 관련한 설정이 변수인 db-svc로 들어 이있음.

2) myapp 컨테이너를 docker run 즉 프로세스로 실행시켜줄 때 —add-host db-svc=db ip 라는 옵션을 추가해주면 변수에 value를 넣어주는 것과 같다!

3) ip주소는 가변성이 크기 때문에 코드는 되도록이면 변수로 작성해주는 것이 좋다!

4) myapp 컨테이너는 도커 파일을 토대로 빌드했고, 빌드한 내용 중 app.py가 있기 때문에 이 파일 안의 내용으로 빌드되었다.


[실습 1] 환경 구현

  • GCP에서 vm 인스턴스를 2개 만들고,
  • 각각 도커를 설치한 뒤
  • docker vm에는 app 컨테이너를 docker run하여 프로세스화 해주고
  • docker2 vm에는 mydb 컨테이너를 docker run하여 프로세스화 해주었다.
  • 그리고 둘을 연결시켰다.

→ docker vm에 build 해놓은 app 이미지를 도커 허브 - 나의 레파지토리에 push 해놓아야 두번째 실습의 환경 구축이 쉽다.

[실습 2] 환경 구현

  • docker2 vm의 환경은 첫번째 실습과 똑같다.
  • docker vm의 환경은 변화할 필요가 있다.

→ docker vm에 실행되고 있던 프로세스와 빌드되어 있던 이미지를 모두 삭제한다.

(첫번째 실습에서 프로세스화 했던 myapp이 포트포워딩으로 80:5000에서 실행되고 있기 때문이다.)

  • docker vm 위에 2개의 myapp 컨테이너를 띄우고 (도커 허브 레지스트리 이용)
  • 각각 mydb와 연동할 수 있도록 프로세스화(docker run)해준다.

→ 반드시 haproxy를 프로세스화 하기 전에 myapp이 db와 연동될 수 있게 만들어줘야 한다.

(myapp은 flask로 만들어졌으므로 5000번 포트에서 동작한다.)

  • myapp1과 myapp2가 외부에서 haproxy를 통해 접근이 될 수 있도록, 그리고 라운드 로빈이 될 수 있도록 haproxy를 포트포워딩 + 프로세스화(docker run) 해준다.

→ 이 haproxy 또한 도커 파일로 image build 해준다.

💡 ⚡ 주의할 점 - IP 주소
**IP주소는 가변적이기 때문에 IP주소 대신 변수로 코드를 작성한 다음,
**
이미지 빌드하거나 프로세스화(docker run) 시켜줄 때 변수에 value 값을 넣어주자!


실습 목표

포트포워딩의 기능 살펴보기!

포트포워딩은 어느 상황에서 사용해야 하는지!

여기에서 우리가 이 실습을 진행하는 이유는 vm 인스턴스 외부 네트워크의 host가 vm 인스턴스 내부 네트워크의 vm의 컨테이너!!에 진입할 수 있는지 보기 위함이다.

즉, 외부에서 vm 인스턴스 위에 올라가 있는 컨테이너에 접근하는 방법을 보기 위함이다

→ 포트포워딩 사용

(동일 vm 내에 app 컨테이너와 db 컨테이너를 모두 프로세스화 시켜주면, 내부 네트워크로 통신 가능하다!! → 포트포워딩 필요 없음)


[실습 2] 실습 진행

1. 실행되고 있는 모든 컨테이너와 build된 이미지들을 지운다.

**docker rm -f $(docker ps -a -q)**    # 컨테이너 모두 삭제
**docker rmi -f $(docker images -q)**  # 로컬 이미지 모두 삭제

→ 컨테이너와 이미지 아무 것도 남아 있지 않은 것을 볼 수 있다.

docker ps -a   # 모든 컨테이너 확인
docker images  # 로컬에 저장되어 있는 이미지 확인

2. 도커 허브 - 나의 레파지토리로부터 app 이미지를 불러와 2개를 프로세스화 시킨다.

이때, db와 연동시켜 프로세스화 시킨다.

(myapp1, myapp2)

docker run -d --name myapp1 --add-host db-svc:10.128.15.213 chohyeon1208/test:app
docker run -d --name myapp2 --add-host db-svc:10.128.15.213 chohyeon1208/test:app

3. haproxy의 Dockerfile과 haproxy.cfg을 만든다.

Dockerfile

## Dockerfile
# 베이스 이미지로 HAProxy 공식 이미지를 사용
FROM haproxy:latest

# HAProxy 설정 파일을 컨테이너로 복사
COPY haproxy.cfg /usr/local/etc/haproxy/haproxy.cfg

# HAProxy 포트 (기본: 80, 443)을 노출
EXPOSE 80 443

# HAProxy를 포어그라운드 모드로 실행
CMD ["haproxy", "-f", "/usr/local/etc/haproxy/haproxy.cfg"]

haproxy.cfg → 맨 마지막 줄은 무조건 빈 행으로 두기!

(cfg 파일은 개행으로 명령이 끝남을 정함,,이라고 하는데 확실하지 않음)

## haproxy.cfg
global
    log /dev/log    local0
    log /dev/log    local1 notice
    daemon
    maxconn 256

defaults
    log     global
    mode    http
    option  httplog
    option  dontlognull
    retries 3
    option redispatch
    timeout connect 5000ms
    timeout client  50000ms
    timeout server  50000ms

frontend http-in
    bind *:80
    default_backend servers

backend servers
    balance roundrobin
    server server1 web1:5000 check
    server server2 web2:5000 check

4. haproxy 를 Dockerfile로 image build 해준다.

💡 Dockerfile로 이미지 빌드는 반드시 Dockerfile이 존재하는 디렉토리에서 실행!!

→ Dockerfile image build는 반드시 Dockerfile이 존재하는 디렉토리에서 실행해야하기 때문에

해당 경로로 가서 Dockerfile이 있는지 확인하고 이미지 빌드하자!

docker build -t haproxy .
## 주의 해야하는 것!! 마지막 점!!
## 이미지 빌드 경로 주의하기!!

→ haproxy image build가 완료된 것을 볼 수 있다.

5. myapp1, myapp2 컨테이너 IP를 확인한다.

docker inspect bridge        

6. myapp1과 myapp2가 외부에서 haproxy를 통해 접근이 될 수 있도록, 그리고 라운드 로빈이 될 수 있도록 haproxy를 포트포워딩 + 프로세스화(docker run) 해준다.

docker run -d -p 80:80 --name proxy --add-host web1:172.17.0.2 --add-host web2:172.17.0.3 haproxy

7. 외부에서 haproxy 컨테이너로 접근 가능한지, 즉 포트포워딩으로 인해 haproxy 컨테이너가 외부로 노출되어 있는지 확인한다.

docker vm의 외부 IP 주소를 url 창에 입력한다.

http의 기본 포트는 80이므로 따로 포트를 입력할 필요는 없다.

→ haproxy 컨테이너를 통해

→ myapp1으로 연결되는 것을 볼 수 있다.

→ haproxy 컨테이너를 통해

→ myapp2로 연결되는 것을 볼 수 있다.


[깨달은 점]

#1 포트포워딩의 기능

컨테이너를 외부에 노출시키기

= 외부에서 vm 인스턴스 내부에 있는 컨테이너에 접근 가능하게 만들어준다.

💡 도커 host 안에 있는 컨테이너는 외부에서 접근 불가능하다.
→ 따라서 외부에서 접근하기 위해서는 포트포워딩을 통해 외부에 노출시켜줘야 한다.

#2 포트라는 문?

포트는 문을 열어둔 채로 기다리고 있다고 생각하면 된다.

예를 들어 myapp이라는 컨테이너가 5000번 포트에서 동작한다는 뜻은, 5000번 포트를 열고 기다리고 있다는 뜻이다.

#3 포트포워딩 테이블의 존재

#4 Dockerfile과 작업 디렉토리

Dockerfile build = image build

다른 사람이 내가 만든 dockerfile로 image build해도 올바른 경로에 이미지가 build 되도록 하기 위해서 작업 디렉토리를 설정

#5 브릿지 = 스위치(L2)

→ 도커 네트워크 ????????

#6 Haproxy가 LB 기능을 제공하는가

제공한다.

웹 애플리케이션의 부하 분산과 TCP/HTTP 기반의 로드 밸런싱 기능을 제공한다.

haproxy.cfg 파일의 backend server 부분을 보면 알 수 있다.

내가 진행한 실습에서는 round robin으로 부하 분산 기능을 만들어줬다.

#7 docker commit과 Dockerfile을 이용한 이미지 빌드 차이

docker commit은 원래 있던 이미지로만 새로운 이미지를 build할 수 있고,

→ Dockerfile을 이용한 image build는 완전히 새로운 이미지도 build할 수 있다.

💡 단, 여기에서 주의할 점은 docker commit 으로 이미지를 build할 경우, 기존의 컨테이너가 실행 중이어야 한다.
실행 중인 컨테이너의 상태가 캡쳐되어 새로운 이미지가 만들어지기 때문이다.

#8 haproxy.cfg의 개행 오류

haproxy.cfg 파일의 마지막 줄은 비어있는 줄로 둬야 한다.

haproxy.cfg 파일의 옵션(?)은 개행을 기준으로 실행되기 때문이다.

→ 따라서 haproxy.cfg 파일의 마지막 문단을 실행하기 위해서는 맨 마지막 줄을 비워둬야 한다.

#9 --add-host 옵션 사용 이유

프로세스화(docker run) 해주는 컨테이너 내에서 호스트 명과 IP 주소의 매핑을 위해 사용한다.

IP주소는 가변적이기 때문에 IP주소 대신 변수로 코드를 작성한 다음,
**이미지 빌드하거나 프로세스화(docker run) 시켜줄 때 변수에 value 값을 넣어준다.**

0개의 댓글