본문 바로가기

AWS

AWS EC2와 Docker container로 웹서버 구축하기

AWS EC2 Instance 내의 Docker container 를 통해 Python Flask module로 웹서버 구축하기

요약 순서 

1. AWS EC2 instance의 port를 열어준다.

2. server을 run하는 python file을 만들어준다.

0.0.0.0:{CONTAINER_PORT}에 container 내의 server가 run되도록 설정한다.

3. Dockerfile 작성

4. docker build {options...}

5. docker run -p {HOST_PORT}:{CONTAINER_PORT} {IMAGE_NAME}

6. 외부에서 Instance의 Public IP를 통해 접속해본다.

상세 설명

1. AWS EC2 instance의 port를 열어준다.

EC2 Dashboard에서 자기가 port를 binding하고 싶은 instance의 Security groups란을 보고 어떤 Security group 을 이용하는 지 확인하고 그것을 눌러준다.

이후 Dashboard가 Security Groups란으로 넘어가고 하단 창에서 Inbound란을 클릭, EC2 instance 외부에서 접근 가능하도록 해줄 포트를 추가로 열어주자.

예를 들어 내 instance의 IP가 12.123.456.789인데 외부에서

http://12.123.456.789로 접속하게 하려면 HTTP 선택

Public IP는 instance dashboard의 IPv4로 확인가능

2. server을 run하는 python file을 만들어준다. 

컨테이너에서는 0.0.0.0:{CONTAINER_PORT}에 server가 run되도록 설정한다.



기본적으로 컨테이너에서의 0.0.0.0은 해당 컨테이너가 가질 수 있는 모든 IP이고, 기본적으로 이는 예를 들어 172.17.0.4처럼 172.17.0.x의 꼴인 것으로 알고 있다. 혹은 가질 수 있는 모든 IP이므로 127.0.0.1이 될 수도 있다.

만약 localhost127.0.0.1로 서버를 run한다면 도커 컨테이너의 외부에서는 컨테이너의 로컬호스트에 접근할 수 없다. 따라서 172.17.0.2 라는 컨테이너의 IP를 이용하면 호스트도 172.17.0.2를 통해 접속이 가능하다.

하지만 매번 그 컨테이너의 아이피가 172.17.0.2인지 172.17.0.3 인지 확인한 뒤 코드를 적는 것은 매우 비효율적이다. 따라서 0.0.0.0을 이용하는 것이다.

다시 한 번 얘기하지만 host에서 컨테이너의 localhost 혹은 127.0.0.1 로는 접근 불가이다.

# server.py running server
from flask import Flask

app=Flask(__name__)

@app.route("/")
def index():
    return "Hello\nThis is on Docker"

app.run(port=8080, host="0.0.0.0")
# app.run(port=8080, host="localhost")

3. Dockerfile에 EXPOSE <컨테이너의 가상 PORT

Dockerfile에 server.py 등등 컨테이너에서 사용할 Port 를 적어준다.

FROM python

COPY . /app
WORKDIR /app

RUN echo server will be running on 8080
RUN pip install flask

CMD ["python", "server.py"]

python 환경으로 컨테이너 가상화

현재 폴더의 모든 내용을 컨테이너의 /app에 복사

cd /app

컨테이너의 포트 8080번을 이용함.

flask module을 install.

docker run 을 통해 이 이미지를 바탕으로 컨테이너를 생성할 때 python server.py 실행.

4. docker build ...

docker build . -t=tutorial

tutorial이라는 tag를 이용해 image를 만들었다.

tag는 쉽게 말하면 image의 이름이다.

5. docker run -it -p <열어둔 PORT>:<컨테이너의 가상 PORT> <ImageName>

-i interactive mode -t virtual tty mode인 거으로 기억한다.

어쨌든 -it 옵션을 통해 해당 컨테이너 터미널을 이용할 수는 있는데, 여기선 현재 그냥 flask app을 돌리고 있으니 별 상관없음.

주의! container은 자기가 CMD등을 통해 image에서 부여된 업무를 마치면 종료되게 되어있다는 점....

6. 외부에서 Instance의 외부 IP를 통해 접속해본다.

외부(나의 노트북 로컬 등등)에서 아까 EC2 Dashboard에서 봤던 내 instance의 IPv4 를 통해 접속해보자

curl {Public IP}:{컨테이너의 포트와 바인딩 시킨 Instance의 PORT}

혹은 그냥 웹브라우저에서 접근 가능

원인은 잘 모르지만 container 내에서 host 에 "0.0.0.0" 을 인자로 줌으로써 서버를 열 때,

인식하는 IP랑 실제로 외부에서 접속하는 IP는 다르다.

아마 우리가 실제로 접속하는 IP는 Public IP, 컨테이너 내부에서 "0.0.0.0"을 통해 이용하는 IP는 Private IP인 것 같다.


(참고 : https://docs.aws.amazon.com/ko_kr/AWSEC2/latest/UserGuide/using-instance-addressing.html)


Questions???

container에서 "0.0.0.0"에서 돌릴 때와 "localhost"에서 돌릴 때의 차이는?

-> container에서 0.0.0.0은 자신이 나타낼 수 있는 모든 IP, "localhost"나 "127.0.0.1"은 자기 자신만의 네트워크 안에서 사용하는 IP이다.