본문 바로가기
kubenetes

Dockerfile로 flask web docker image build 하는 방법

by kyeongseo.oh 2022. 3. 23.

대충 이렇게 작업할 예정

1. python flask web page를 하나 만들고

2. Dockerfile 작성

3. docker build

4. harbor (private registry)에 image push

5. kubernetes에서 pod 생성 (harbor에서 이미지 pull 받기)

6. web ui 접속 테스트

 

1. 개발환경 셋업

python3 install하고 flask 설치

디렉토리를 하나 생성. 모든 파일을 이 디렉토리에서 만들 예정

yum install -y python3-pip
pip3 install flask

mkdir ~/flaskImage
cd ~/flaskImage

 

2. python flask code 작성

ip:port로 접속하면 `kyeongseo's flask web page`라는 텍스트가 출력되고,

ip:port/index로 접속하면 index.html 화면이 보이게 코드를 작성하였음

파일이름은 `ksFlask.py`로 하였음

from flask import Flask, render_template, url_for

app = Flask(__name__)

@app.route('/')
def web():
   return "kyeongseo's flask web page"

@app.route('/index')
def image():
   return render_template("index.html")

if __name__ == "__main__":
   app.run(host="0.0.0.0")

 

3. index.html 작성

사실 간단하게 테스트할거면 필요없는 데 그냥 이미지를 하나 올리고 싶었음

static 디렉토리에 있는 img.jpg라는 이미지 파일을 web에서 보여줌

참고로 html파일은 반드시 templates 디렉토리 안에 있어야함

<!doctype html>
<html>
  <head>
  </head>
  <body>
    <img src="{{ url_for('static', filename='./img.jpg') }}">
  </div>
  </body>
</html>

 

전체적인 구조는 아래와 같음

[root@kw1 flaskImage]# tree
.
├── ksFlask.py
├── static
│   └── img.jpg
└── templates
    └── index.html

 

4. Docker image에 포함되어야 할 python package를 정리한 requirement.txt 생성

pip3 freeze명령으로 현재 환경에 설치된 python package와 version 정보를 볼 수 있음

[root@kw1 flaskImage]# pip3 freeze > requirements.txt

[root@kw1 flaskImage]# cat requirements.txt
click==8.0.4
dataclasses==0.8
Flask==2.0.3
importlib-metadata==4.8.3
itsdangerous==2.0.1
Jinja2==3.0.3
MarkupSafe==2.0.1
typing-extensions==4.1.1
Werkzeug==2.0.3
zipp==3.6.0

 

5. Dockerfile 작성

python 3.6 image를 사용하고, python package를 설치해주었음

FROM python:3.6

# 현재 디렉토리의 모든 파일들을 컨테이너의 /app 디렉토리에 복사한다.
COPY . /app

# flask의 작업 위치가 /app이라는 뜻
WORKDIR /app

RUN pip install -r requirements.txt
EXPOSE 8282
CMD ["python", "/app/ksFlask.py"]

 

처음 테스트할 때 다음과 같은 에러가 났었음. 

/bin/sh: 1: [python,: not found

 

CMD LINE에서 홑 따옴표를 사용해서 발생한 문제였음.

# 이렇게 홑따옴표로 쓰던 걸
CMD ['python', '/app/ksFlask.py'] 

# 쌍따옴표로 바꾸고 해결했음
CMD ["python", "/app/ksFlask.py"]

 

Dockerfile 문법 정리 (dockfile docs)

FROM : docker base image

COPY : 파일을 해당 위치에 복사

WORKDIR : "RUN", "CMD", "ENTRYPOINT" 등의 명령이 실행되는 디렉토리 위치

ENV : 환경변수 설정

RUN : 컨테이너 만들 때 shell 명령이 필요한 경우 사용할 수 있음

CMD : 컨테이너가 실행될 때 해당 명령을 실행한다.

EXPOSE : 호스트와 연결할 포트 번호를 설정한다.

6. docker build

[root@kw1 flaskImage]# docker build -t harbor.ks.io/ksflask:v1 .
Successfully built edd4429bca17
Successfully tagged harbor.ks.io/ksflask:v1

[root@kw1 flaskImage]# docker images
REPOSITORY                     TAG       IMAGE ID       CREATED         SIZE
harbor.ks.io/ksflask           v1        edd4429bca17   2 minutes ago   419MB

 

7. 이미지가 잘 만들어졌는지 확인

flask default port가 5000이라서 5000:5000으로 해줌

[root@kw1 flaskImage]# docker run -d -p 0.0.0.0:5000:5000 harbor.ks.io/ksflask:v1
8a778e5b2f88ed2b55367f75fa94233f2bd73dff9a91d5cda7a2fff33d55b9cd

 

WEB에서 IP:5000에 접속해봄

일단 첫 번째 page는 정상적으로 접근된다. 2번째 image page도 접근해본다.

ip:5000/index 페이지도 정상적으로 접근된다.

 

잘 올라온 게 확인되었으니 docker process를 지워준다.

[root@kw1 flaskImage]# docker ps
CONTAINER ID   IMAGE                     COMMAND                  CREATED          STATUS          PORTS                              NAMES
8a778e5b2f88   harbor.ks.io/ksflask:v1   "python /app/ksFlask…"   10 minutes ago   Up 10 minutes   0.0.0.0:5000->5000/tcp, 8282/tcp   affectionate_satoshi
ede37c3bf9f7   kubernetesui/dashboard    "/dashboard --insecu…"   5 days ago       Up 5 days                                          k8s_kubernetes-dashboard_kubernetes-dashboard-6857959dd6-h5lm4_kubernetes-dashboard_30be962f-e090-4374-bbc1-a7a492ca83a4_0
bdf9a1143491   k8s.gcr.io/pause:3.6      "/pause"                 5 days ago       Up 5 days                                          k8s_POD_kubernetes-dashboard-6857959dd6-h5lm4_kubernetes-dashboard_30be962f-e090-4374-bbc1-a7a492ca83a4_0
2d7befea386e   7801cfc6d5c0              "/metrics-sidecar"       5 days ago       Up 5 days                                          k8s_dashboard-metrics-scraper_dashboard-metrics-scraper-799d786dbf-4tm9r_kubernetes-dashboard_586bf9d2-92c1-4c5d-bd0f-30d4e5233501_0
8e52b32784e5   k8s.gcr.io/pause:3.6      "/pause"                 5 days ago       Up 5 days                                          k8s_POD_dashboard-metrics-scraper-799d786dbf-4tm9r_kubernetes-dashboard_586bf9d2-92c1-4c5d-bd0f-30d4e5233501_0
2bac828bdacd   calico/node               "start_runit"            6 days ago       Up 6 days                                          k8s_calico-node_calico-node-vpzhx_calico-system_61606a50-22da-4c22-b6a9-c2c30474782f_0
90889b808814   k8s.gcr.io/kube-proxy     "/usr/local/bin/kube…"   6 days ago       Up 6 days                                          k8s_kube-proxy_kube-proxy-sq298_kube-system_fc972596-775f-40a3-887f-e93a9402536e_0
24923d9cf1ea   k8s.gcr.io/pause:3.6      "/pause"                 6 days ago       Up 6 days                                          k8s_POD_calico-node-vpzhx_calico-system_61606a50-22da-4c22-b6a9-c2c30474782f_0
b23a24b8465d   k8s.gcr.io/pause:3.6      "/pause"                 6 days ago       Up 6 days                                          k8s_POD_kube-proxy-sq298_kube-system_fc972596-775f-40a3-887f-e93a9402536e_0

[root@kw1 flaskImage]# docker kill 8a778e5b2f88
8a778e5b2f88

 

8. k8s deployment를 생성해준다.

[root@kw1 flaskImage]# kubectl create deploy ksflask --image=harbor.ks.io/ksflask:v1
deployment.apps/ksflask created

# 확인
[root@kw1 flaskImage]# kubectl get deploy
NAME      READY   UP-TO-DATE   AVAILABLE   AGE
ksflask   1/1     1            1           9s

 

9. 외부에서 접근하기 위해 k8s service를 생성해준다.

ip:31099로 접속하면 web page가 보여야 함.

[root@kw1 flaskImage]# kubectl expose deploy ksflask --type=NodePort --port=5000 --name=ksflask
service/ksflask exposed

[root@kw1 flaskImage]# kubectl get svc
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
ksflask      NodePort    10.108.187.236   <none>        5000:31099/TCP   6s
kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP          6d12h

 

10. web 접속 테스트

기본 페이지 잘 접속됌

이미지 페이지도 잘 접속됌

 

11. harbor에 이미지 push

나중에 올릴 일은 없겠지만 일단 harbor에 이미지를 올려둔다.

[root@kw1 ~]# docker tag harbor.ks.io/ksflask:v1 harbor.ks.io/privatetest/ksflask:v1                                                                                                                                                         

[root@kw1 ~]# docker push harbor.ks.io/privatetest/ksflask:v1
The push refers to repository [harbor.ks.io/privatetest/ksflask]
69476dd827fb: Pushed
a010e738c6b1: Pushed
aa4c808c19f6: Pushed
8ba9f690e8ba: Pushed
3e607d59ef9f: Pushed
1e18e7e1fcc2: Pushed
c3a0d593ed24: Pushed
26a504e63be4: Pushed
8bf42db0de72: Pushed
31892cc314cb: Pushed
11936051f93b: Pushed
v1: digest: sha256:ad391fea2a664a08195528ca8a4d6cae105680fb726543e27810116ce6c5edb7 size: 2639

 

good!

댓글