docker image 란 어플리케이션과 해당 환경을 패키지화한 것
docker file은 자신의 docker image를 만드는데 필요한 개발환경과 패키지등을 DSL(Domain Specific Language)화 한 것
[1] cd ~/[your_path]/docker-app/api/
[2] virtualenv venv
[3] . venv/bin/actiavte
[4] python -m pip install --upgrade pip
[5] pip install flask gunicorn
[6] pip freeze > requirements.txt
[1] directory 변경(api path)
[2] python 가상환경 생성
[3] 가상환경 활성화
[4] pip 업그레이드
[5] flask 및 gunicorn 설치
[6] pip list를 requirements.txt 로 작성
[1] vi app.py
# ~/docker-app/api/app.py
from flask import Flask, make_response, jsonify, request
app = Flask(__name__)
@app.route('/')
def hello():
return jsonify({
'code': 200,
'msg': 'Hello World!'
})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=80)
else:
gunicorn_app = app
gunicorn_app.debug = True
[1] python app.py
* Serving Flask app 'app' (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on all addresses.
WARNING: This is a development server. Do not use it in a production deployment.
* Running on http://172.30.82.223:80/ (Press CTRL+C to quit)
[1] curl -v localhost
* Trying ::1...
* TCP_NODELAY set
* Connection failed
* connect to ::1 port 80 failed: Connection refused
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET / HTTP/1.1
> Host: localhost
> User-Agent: curl/7.64.1
> Accept: */*
>
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Content-Type: application/json
< Content-Length: 34
< Server: Werkzeug/2.0.1 Python/3.9.2
< Date: Sun, 23 May 2021 04:16:33 GMT
<
{"code":200,"msg":"Hello World!"}
* Closing connection 0
vi Dockerfile
# api/Dockerfile
[1] FROM ubuntu:20.04
[2] WORKDIR /home/docker-app/api
[3] RUN apt update && apt-get install python3 python3-pip -y
[4] ADD . .
[5] RUN pip3 install -r requirements.txt
[6] EXPOSE 8080
[7] CMD gunicorn -b 0:8080 --access-logfile log/access.log --error-logfile log/error.log --threads 4 app:gunicorn_app
[1] FROM
은 docker container의 운영체제를 지정함
또는 빌드환경을 지정함
[2] WORKDIR
docker container 내 해당 application project main directory를 지정하여 만들고 이동함
[3] RUN
docker container 내에서 실행하는 명령어로 container의 OS가 ubuntu로 지정하였음으로 apt
명령어로 업데이트 및 python3를 설치
(정확하게 위 api 와 같이 python v3.9.2 버전을 설치하고자 한다면, wget으로 별도로 설치해야함.)
[4] ADD
현재 host(내 PC)의 directory의 파일들을 container의 directory로 추가 (현재 ~/api/ 디렉토리에 api의 파일들(app.py, requirements.txt 등)을 container의 workdir로 이동 또는 directory를 지정가능 ex) ADD . /home/docker-app/api)
[5] (ubuntu에는 기본 python2가 설치 되어 있음으로..) pip3 로 requirements.txt 파일을 읽어서 application에 필요한 패키지 설치
[6] EXPOSE
는 container의 service port를 설정하는 것으로 8080
포트를 열어줌
[7] CMD
는 container 초기 구동 시 실행되는 명령어로 gunicorn
명령어로 프로젝트를 실행할 수 있는 명령어를 작성
docker build --tag docker-app/api:1.0.0 .
[+] Building 283.9s (10/10) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 765B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/ubuntu:20.04 1.2s
=> [1/5] FROM docker.io/library/ubuntu:20.04@sha256:cf31af331f38d1d7158470e095b132acd126a7180a54f263d386da88eb681d93 0.0s
=> [internal] load build context 0.1s
=> => transferring context: 134.83kB 0.1s
=> CACHED [2/5] WORKDIR /home/docker-app/api 0.0s
=> [3/5] RUN apt update && apt-get install -y build-essential zlib1g-dev libncurses5-dev libgdbm-dev libnss3-dev libssl-dev libreadline-dev libffi-dev libsqlite3-dev wget libbz2-dev && wget https://www.python.org/ftp/ 268.6s
=> [4/5] ADD . . 0.4s
=> [5/5] RUN pip3 install -r requirements.txt 10.1s
=> exporting to image 3.5s
=> => exporting layers 3.5s
=> => writing image sha256:902f310dd3ccf93901bd9398f964f46d1fe7ecde67eab676468517ea8a79cc17 0.0s
=> => naming to docker.io/docker-app/api:1.0.0
작성한 dockerfile 기준으로 docker image를 만듬
build
: docker image를 만들때 사용하는 옵션
- --tag
: tag를 달아서 이미지를 만들수 있음
ex) [project이름]/[어플리케이션이름]:[버전]
.
: Dockerfile의 위치를 옵션으로 넣어줌(현재는 ~/api/ 에 Dockerfile를 작성하고 docker build 명령어를 실행하기에 현재 디렉토리(.
)로 옵션을 넣음)
docker images
(venv) ➜ api docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker-app/api 1.0.0 902f310dd3cc 12 minutes ago 1.06GB
docker images
명령어를 통해 현재 만들어진 docker image를 확인docker run -d -p 8080:8080 --name test-api docker-app/api:1.0.0
423b00d6a09f7b8f626b6054cf53dcb73ed2c57ee0c6e0fb85dc6aab026d9198
docker run
명령어로 실행-d
: daemon processor로 구동-p
: local에서 docker-container로 port forwarding 하는 옵션으로, local포트(8080)을 container포트(8080)으로 매핑하는 것-p 80:8080
이면 local포트(80)을 container포트(8080)으로 매핑--name
: container의 이름(별칭)을 지어줌[image_name]
: 마지막으로 local에 해당되는 이미지가 있으면 가져와서 실행. 또는 docker-hub(또는 docker registry가 될수도 있음) 에서 image이름에 맞는 image를 pull 받아서 실행.docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
423b00d6a09f docker-app/api:1.0.0 "/bin/sh -c 'gunicor…" 24 minutes ago Up 24 minutes 0.0.0.0:8080->8080/tcp test-api
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
423b00d6a09f docker-app/api:1.0.0 "/bin/sh -c 'gunicor…" 24 minutes ago Up 24 minutes 0.0.0.0:8080->8080/tcp test-api
9e3012c16905 xxx.xxx.xxx/test_api:1.0.0 "gunicorn -b 0:8080 …" 11 days ago Exited (0) 40 minutes ago api
docker ps
: 현재 구동중인 docker container의 process 이름, 상태, CMD등 정보를 출력docker ps -a
: -a
를 추가 옵션을 넣을 경우, 구동중이거나 멈춰있거나 모든 상태의 docker container 정보를 출력curl -v localhost:8080
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: gunicorn
< Date: Sun, 23 May 2021 06:01:16 GMT
< Connection: keep-alive
< Content-Type: application/json
< Content-Length: 44
<
{
"code": 200,
"msg": "Hello World!"
}
* Connection #0 to host localhost left intact
* Closing connection 0
# dockerfile
FROM ubuntu:20.04
WORKDIR /home/docker-app/api
[1]RUN apt update \
&& apt-get install -y \
build-essential \
zlib1g-dev \
libncurses5-dev \
libgdbm-dev \
libnss3-dev \
libssl-dev \
libreadline-dev \
libffi-dev \
libsqlite3-dev \
wget \
libbz2-dev \
[2]&& wget https://www.python.org/ftp/python/3.9.2/Python-3.9.2.tgz \
[3]&& tar -xf Python-3.9.2.tgz \
[4]&& cd Python-3.9.2 \
[5]&& ./configure --enable-optimizations \
[6]&& make -j 12 && make altinstall \
[7] update-alternatives --install /usr/bin/python3 python3 /usr/local/bin/python3.9 1
[8]&& apt-get install -y python3-pip
ADD . .
RUN pip3 install -r requirements.txt
EXPOSE 8080
CMD gunicorn -b 0:8080 --access-logfile log/access.log --error-logfile log/error.log --threads 4 app:gunicorn_app
[1] python 설치관련 필요한 패키지를 apt-get
으로 설치
[2] wget
으로 공식 python v3.9.2 repository의 파일들을 다운로드
[3] Python-3.9.2.tgz
압축해제
[4] Python-3.9.2
디렉토리 이동
[5] 설치 config 설정
[6] make
명령어로 컴파일 및 설치
[7] python3.9
를 python3
링크로 업데이트
[8] python3-pip
설치
[1]FROM python:3.9.2-slim
WORKDIR /home/docker-app/api
ADD . .
[2]RUN pip install -r requirements.txt
EXPOSE 8080
CMD gunicorn -b 0:8080 --access-logfile log/access.log --error-logfile log/error.log --threads 4 app:gunicorn_app
[1] python-docker hub에서 원하는 버전의 slim
태그 버전을 선택하여 설치
[2] 기존에는 python3를 별도로 설치했어야했지만, pip가 버전에 맞게 설치되어 있음