Network & Dockerfile

Network & Dockerfile

  1. 컨테이너 와 이미지 모두 삭제
  • 모든 컨테이너 중지: docker stop $(docker ps -a -q)

  • 모든 컨테이너 삭제: docker rm $(docker ps -a -q)

  • 모든 이미지 삭제: docker rmi $(docker images -q)

Docker Network

  • 도커 컨테이너 및 서비스는 도커 네트워크를 통해 격리된 컨테이너 간의 네트워크 연결 뿐 아니라 도커 외의 다른 애플리케이션 워크로드 와도 연결이 가능
  • 도커 네트워크의 하위 시스템 연결을 위해 도커 네트워크 드라이버를 이용해서 상호 간 통신이 가능
  • 도커 컨테이너는 별도의 설정을 하지 않는 한 docker0 이라는 브릿지에 연결되어 172.17.0.0/16의 CIDR 범위로 IP 주소가 할당됨
  • 컨테이너를 생성하면 eth0 인터페이스 카드에 172.17.0.2 형태로 IP주소를 할당해서 생성됨
  • 확인: ifconfig docker0(ifconfig 명령이 없으면 apt install net-tools)

컨테이너를 생성하고 네트워크 설정을 확인

  • ubuntu:14:04 이미지를 가지고 컨테이너 2개 생성
docker run --name container1 -dit ubuntu:14.04
docker run --name container2 -dit ubuntu:14.04
  • 컨테이너 상세보기에서 IPAddress(MAC, route 정보)라는 항목을 확인하면 IP할당을 확인
  • 컨테이너 상세보기에서 .NetworkSettings.IPAddress 그룹을 확인하면 네트워크 설정을 확인할 수 있음
  • 리눅스 명령어에서 ifconfig(route, ip addr 등)를 확인하면 네트워크 정보를 확인할 수 있음
    • docker exec container1 ifconfig
  • 호스트 컴퓨터에서 ifconfig를 확인해보면 컨테이너 개수 만큼 인터페이스가 추가된 것을 확인할 수 있음

도커 네트워크 드라이버

  • 도커 네트워크 드라이버를 사용할 때는 --net이나 --network 명령을 이용해서 선택할 수 있고 docker network 명령을 통해서 호출해서 사용
    • bridge: 기본 네트워크 드라이버로 컨테이너로 실행 시 별도의 네트워크 지정없이 독립적으로 실행되는 애플리케이션 컨테이너를 실행하는 경우 사용하는데 브릿지 모드는 동일 호스트 상의 도커 컨테이너에만 적용
    • host: 컨테이너 와 호스트 간의 네트워크 격리를 제거하고 호스트의 네트워킹을 직접 사용할 수 있는데 이렇게 하면 컨테이너 애플리케이션에 별도의 포트 연결 없이 호스트의 포트를 바로 연결할 수 있음
    • overlay: 도커 클러스터인 도커 스웜 구축시 호스트 와 호스트 간의 컨테이너 연결에 사용
    • none: 네트워크 사용 안 함
    • container:공유받을컨테이너이름: 다른 컨테이너의 정보를 공유
    • 사용자정의네트워크
  • host 모드 와 bridge 모드의 차이
    • nginx를 포트 설정없이 컨테이너로 실행
Host Computer
    NIC - ifconfig
        IPTable - iptables
            Docker Bridge Network - bctl show
                Container - ifconfig / route / ip addr
PAT(NAT Overload) - 포트1개를 IP1개처럼 사용
NAT - 보안을 위해서 사용
  • host 모드 와 bridge 모드의 차이
    • nginx를 포트 설정없이 컨테이너로 실행
      • docker run -d --name=noport nginx
      • 이 경우 컨테이너에서 서비스 하는 내용을 외부에서 사용할 수 없음
    • nginx를 브릿지 모드로 외부에서 접근할 수 있도록 컨테이너로 실행
      • docker run -d --name=bridgeport -p 8001:80 nginx
      • http://localhost:8001 로 서비스 받을 수 있습니다.
    • nginx를 호스트 모드로 외부에서 접근할 수 있도록 컨테이너로 실행
      • docker run -d --name=host --net=host nginx
      • http://localhost:80 로 서비스 받을 수 있습니다.

네트워크 생성 및 할당

  • 네트워크 생성
    • docker network create [–driver=네트워크드라이버종류] 네트워크이름
  • 컨테이너에 네트워크 설정을 할 때는 컨테이너를 만들 때 –net 옵션에 네트워크 이름을 설정해주면 됨
  • 실습
    • 네트워크 생성(webapp-vnet, mobileapp-vnet)
    docker network create webapp-vnet
    docker network create --driver=bridge mobileapp-vnet
    • 네트워크 확인 docker network ls
    • 네트워크를 설정해서 컨테이너 생성
    docker run -dit --name=webapp --net=webapp-vnet ubuntu:14.04
    docker run -dit --name=mobileapp --net=mobileapp-vnet ubuntu:14.04
    • IP 확인 - 서브넷 마스크가 기본적으로 /16 이므로 위 2개의 컨테이너는 서로 다른 네트워크가 됨
      dh@dh:~$ docker inspect webapp | grep -i ipaddress
                  "SecondaryIPAddresses": null,
                  "IPAddress": "",
                          "IPAddress": "172.18.0.2",
      dh@dh:~$ docker inspect mobileapp | grep -i ipaddress
                  "SecondaryIPAddresses": null,
                  "IPAddress": "",
                          "IPAddress": "172.19.0.2",
    • 네트워크 정보를 상세히 출력(할당된 컨테이너 확인 가능): docker network inspect webapp-vnet
  • 브릿지네트워크의 IP 대역은 순차적으로 할당되는데 이를 원하는 대역으로 설정하는 것이 가능한데 이 경우는 네트워크를 생성할 때 --subnet 그리고 --ip-range--gateway를 설정해주면 됨
    • 네트워크 생성
      docker network create --ip-range 172.100.1.0/24 --subnet 172.100.1.0/24 --gateway 172.100.1.1 custom-net
    • 네트워크 확인 docker network inspect custom-net
    • 컨테이너 생성
      docker run -dit --net=custom-net --name=cust-net1 ubuntu:14.04
      docker run -dit --net=custom-net --name=cust-net2 --ip 172.100.1.100 ubuntu:14.04
    • 하나의 컨테이너에 접속해서 ping 명령을 수행
      dh@dh:~$ docker exec -it cust-net1 /bin/bash
      root@b35f06aaf319:/# ping -c 3 cust-net2
      PING cust-net2 (172.100.1.100) 56(84) bytes of data.
      64 bytes from cust-net2.custom-net (172.100.1.100): icmp_seq=1 ttl=64 time=12.2 ms
      64 bytes from cust-net2.custom-net (172.100.1.100): icmp_seq=2 ttl=64 time=0.179 ms
      64 bytes from cust-net2.custom-net (172.100.1.100): icmp_seq=3 ttl=64 time=0.080 ms

사용자 정의 네트워크를 이용해서 Load Balancing

  • 네트워크 생성(172.200.1.0/24)
docker network create --subnet 172.200.1.0/24 --ip-range 172.200.1.0/24 --gateway 172.200.1.1 netlb
  • 네트워크 확인 docker network ls
  • docker run 수행 시 --net-alias 또는 --link 옵션으로 묶인 컨테이너에는 기본적으로 서비스를 검색할 수 있는 내장 DNS 서버가 제공되는데 이를 자동화 DNS라고 한는데 이 DNS 때문에 사용자 정의 네트워크 안에서 컨테이너 이름과 IP주소가 매칭이 되는 것
  • ubuntu:14.04 이미지를 이용해서 netlb 네트워크에 속한 3개의 컨테이너를 생성하는데 net-alias를 inner-dns-net으로 설정
docker run -dit --name=nettest1 --net=netlb --net-alias inner-dns-net ubuntu:14.04

docker run -dit --name=nettest2 --net=netlb --net-alias inner-dns-net ubuntu:14.04

docker run -dit --name=nettest3 --net=netlb --net-alias inner-dns-net ubuntu:14.04
  • ping을 전송할 새로운 컨테이너를 생성하는데 네트워크는 netlb
docker run -it --name=frontend --net=netlb ubuntu:14.04 /bin/bash
  • 컨테이너가 생성되면 안에서 아래 명령을 여러 번 수행하면서 IP를 확인
    • ping -c 2 inner-dns-net
    • ip가 변하는 것을 확인
  • frontend에서 DNS 정보를 확인
    • dnsutils 패키지를 설치
      sudo apt-get update
      sudo apt-get -y install dnsutils
    • 확인 dig inner-dns-net
  • 다른 터미널을 실행시켜서 컨테이너를 하나 추가
docker run -dit --name=nettest4 --net=netlb --net-alias inner-dns-net ubuntu:14.04
  • 이전 터미널에서 DNS 정보를 확인 dig inner-dns-net

Docker kill 명령과 초기화

kill 명령

  • 강제 종료를 위한 명령
  • docker stop은 컨테이너 내에 메인 프로세스에 SIGTERM으로 종료를 전달하고 10초 후까지 종료되지 않으면 SIGKILL을 전송
  • docker kill은 바로 SIGKILL을 전송해서 강제로 종료

초기화

  • 모든 컨테이너 중지: docker stop $(docker ps -a -q), docker kill $(docker ps -a -q)
  • 모든 컨테이너 삭제: docker rm $(docker ps -a -q)
  • 모든 이미지 삭제: docker rmi $(docker images -q)

Dockerfile

IaC & Dockerfile

  • IaC가 필요한 이유
    • 명령어 기반의 인프라 구성 시 사용자 실수와 같은 인적 오류 가능성이 높음
    • 이런 인적 오류 가능성을 낮추기 위해서 인프라 구성을 코드로 수행

최적의 Dockerfile

  • 경량의 컨테이너 서비스를 제공
  • 레이어를 최소화
  • 하나의 애플리케이션은 하나의 컨테이너로 실행
  • 캐시 기능을 활용
  • 디렉터리 단위로 작업
  • 서버리스 환경으로 개발: 별도의 서버를 이용하지 않도록 작성

Dockerfile 명령어

  • FROM
    • 필수 항목
    • 이미지의 베이스 이미지를 지정하는데 hub.docker.com에서 제공하는 이미지를 권장
    • 이미지를 선택할 때 slim(작은 크기의 이미지) 이나 Alpine(리눅스 배포판) 이미지를 권장
  • MAINTAINER
    • 이미지를 빌드한 작성자 이름 과 이메일을 작성
    • MAINTAINER adam itstudy@kakao.com
  • LABEL
    • 이미지를 작성하는 목적으로 버전이나 타이틀 등을 작성
  • RUN
    • 설정된 기본 이미지에 패키지 업데이트, 각종 패키지 설치, 명령 실행 등을 작성
    • 여러 개 작성 가능
    • RUN 명령어의 개수를 최소화하는 것을 권장
    • RUN 명령 하나의 하나의 레이어가 됨
    • 2가지 방법으로 작성하는데 하나는 shell 방식이고 다른 하나는 exec 방식
    • Shell 방식
      • RUN apt update && apt install -y nginx
    • exec 방식
    RUN ["/bin/bash", "-c", "apt update"]
    RUN ["/bin/bash", "-c", "apt install -y nginx"]
  • CMD
    • 생성한 이미지를 컨테이너로 실행할 때 실행되는 명령이고 ENTRYPOINT 명령으로 지정된 커맨드에 디폴트로 넘길 파라미터를 지정할 때 사용
    • 여러 개의 CMD를 작성해도 마지막 하나만 처리
    • 일반적으로 이미지의 컨테이너 실행 시 애플리케이션 데몬이 실행되도록 하는 경우 유용
      CMD ["python", "app.py"]
  • ENTRYPOINT
    • CMD와 마찬가지로 생성된 이미지가 컨테이너로 실행될 때 사용되지만 컨테이너가 실행될 때 명령어 및 인자 값을 전달받아 실행된다는 것이 다름
    • CMD 컨테이너 실행 시 다양한 명령어를 지정하는 경우에 유용하고 ENTRYPOINT는 컨테이너를 실행할 때 반드시 수행해야 하는 명령어를 지정
  • COPY
    • 호스트 환경의 파일이나 디렉터리를 복사할 때 사용
  • ADD
    • 파일 과 디렉토리를 이미지 안에 복사할 뿐 아니라 URL 주소에서 직접 다운로드 받아서 이미지 안에 넣을 수 있고 tar 나 tar.gz의 경우는 지정한 경로에 압축을 풀어서 추가
    • 빌드 작업 디렉토리 외부의 파일을 ADD 할 수 없고 디렉토리는 /로 끝나야 함
  • ENV
    • 환경변수 설정에 이용
  • EXPOSE
    • 포트나 프로토콜을 외부로 개방하기 위해서 사용
  • VOLUME
    • 볼륨 지정을 위해서 사용
  • USER
    • 기본 사용자인 root 이외의 사용자를 지정할 때 사용
  • WORKDIR
    • 컨테이너 상에서 작업할 경로를 전환하기 위해서 사용하는데 이 디렉토리를 설정하면 RUN, CMD, ENTRYPOINT, COPY, ADD 명령문이 전부 이 디렉토리를 기준으로 수행됨
  • ARG
    • build 시점에서 변수값을 전달하기 위해서 사용
    • build 할 때 --build-arg 변수명=값의 형태로 전달
  • HEALTHCHECK
    • 프로세스의 상태를 체크하고자 하는 경우 사용
    • 하나의 명령만이 유효하고 여러 개가 지정된 경우 마지막에 선언된 HEALTHCHEK 만 적용
    • 옵션으로 interval 이 있는데 헬스 체크 간격으로 기본값은 30초이며 timeout은 기다리는 시간으로 기본값은 30초이며 retries는 타임 아웃 횟수로 기본값은 3
    • 상태코드는 0, 1, 2 세가지가 있는데 0은 성공이고 1은 올바르게 작동하지 않는 상태이며 2는 예약된 코드 HEALTHCHECK --interval=1m --timeout=3s --retries=5 CMD curl -f http://localhost || exit 1
  • 시작은 FROM 부터 이지만 나머지는 순서가 없는데 명령 순서는 빌드 캐시의 무효화 와 연관되므로 변경 빈도 수가 적은 명령을 먼저 배치하는 것을 권장

이미지 빌드

  • docker build [옵션] 이미지이름[:태그] 경로 | URL | 압축파일
  • 옵션
    • -t: 태그를 지정하는 경우
    • -f: Dockerfile이 아닌 다른 파일명을 사용하는 경우
  • 경로: 디렉토리 단위 개발을 권장하고 현재 경로에 Dockerfile 이 있으면 .을 사용하고 Dockerfile이 있는 경로를 설정해도 됨
  • URL: 경로 대신에 Dockerfile이 포함된 URL을 제공하고자 하는 경우 사용
  • 압축 파일을 사용하는 경우는 압축된 파일 안에 Dockerfile이 있는 경우 사용

Dockerfile이 필요한 이유

  • 도커 파일이 없는 경우
    • 우분투 위에 아파치 웹 서버 위에 PHP를 이용해서 웹 애플리케이션을 구현하는 경우에 우분투 이미지를 이용해서 컨테이너를 생성하고 컨테이너 안에 접속을 해서 아파치 웹 서버를 설치하고 아파치 웹 서버를 구동한 후 php를 설치하고 그 위에 코드를 작성해야 함
  • 동일한 작업을 Dockerfile을 이용
    • Dockerfile에 모든 명령어를 작성해두고 한 번의 명령어로 수행

Dockerfile 작성 및 실행

  • 디렉터리를 생성해서 프롬프트를 이동
mkdir phpapp
cd phpapp
  • 도커 파일을 생성하고 작성(vi Dockerfile)
FROM ubuntu:14.04

MAINTAINER "dh"

LABEL title "IaC PHP application"

RUN apt-get update && apt-get -y install apache2 php5 git curl ssh wget

#Environment Variable
ENV APACHE2_RUN_USER www-data APACHE2_RUN_USER www-data APACHE2_LOG_DIR /var/log/apache2 APACHE2_WEB_DIR /var/www/html APACHE2_PID_FILE /var/run/apache2/apache2.pid

#basic web page
RUN echo 'Hello Docker Application' ? /var/www/html/index.html

#php 파일
RUN echo '<?php phpinfo(); ?>' > /var/www/html/index.php

EXPOSE 80

WORKDIR /var/www/html

CMD ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]
  • Dockerfile 빌드 - 현재 디렉터리에 Dockerfile로 존재
    • docker build -t myphpapp:1.0 .
  • 컨테이너로 생성
    • docker run -dit -p 8101:80 --name phpapp1 myphpapp:1.0

이미지 빌드 과정

  • 이미지 빌드는 사용자와의 대화식 처리가 아닌 자동화된 빌드
    • ubuntu 기반의 이미지를 생성하는 경우 패키지를 설치하고자 하면 반드시 apt-get update를 포함시켜야 하며 -y 옵션을 추가해서 자동으로 설치하도록 해주어야 함
  • 이미지 빌드를 할 때는 현재 디렉터리에 있는 모든 파일 과 디렉터리의 컨텐츠는 도커 데몬에 빌드 컨텍스트로 전달되는데 이 때 제외하고 싶은 파일이나 디렉터리가 있으면 .dockerignore 파일에 기재하면 됨
  • python 개발 환경을 만들기 위해서 ubuntu에 python 패키지를 설치
- 디렉토리를 생성하고 프롬프트 이동
mkdir python_lab
cd python_lab

- nano Dockerfile 명령으로 파일을 생성하고 작성
FROM ubuntu:18.04

RUN apt-get install python

- 이미지 빌드: 실패(apt-get update를 하지 않아서 실패)
docker build -t mypyapp:1.0 .

- nano Dockerfile 명령으로 파일을 생성하고 수정
FROM ubuntu:18.04

RUN apt-get update
RUN apt-get install python

이미지 빌드: 실패(대화식으로 작업하도록 해서 실패: 패키지를 설치할 때는 -y 옵션을 추가해서 자동으로 설치되도록 해주어야 합니다.)
docker build -t mypyapp:1.0 .

- nano Dockerfile 명령으로 파일을 생성하고 수정
FROM ubuntu:18.04

RUN apt-get update
RUN apt-get install python -y

- 이미지 빌드: 성공
docker build -t mypyapp:1.0 .
  • 빌드 캐시 사용을 위한 실습
- Dockerfile을 생성
FROM ubuntu:latest

RUN apt-get update && apt-get install -y nginx curl vim

RUN echo 'Docker Container Application.' > /var/www/html/index.html

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]

- 이미지 빌드
docker build -f Dockerfile -t webapp:1.0 .

- 이미지 빌드
docker build -f Dockerfile -t webapp:2.0 .

- 동일한 내용을 가지고 두번째 빌드를 하게 되면 cached 라고 하는 문장이 보이게 되는데 빌드 속도 향상을 위해서 실행 중간에 있는 이미지 캐시를 사용하게 되는데 이를 빌드 캐시라고 함
- 빌드 캐시를 할 때는 동일한 명령어의 연속된 부분까지 빌드 캐시를 이용함 
  • Dockerfile 최적화
    • Ubuntu에 python을 설치하고 app.py 파일을 복사해서 실행하는 Dockerfile을 작성
      FROM ubuntu:20.04
      COPY app.py /app
      RUN apt-get update && apt-get -y install python python-pip
      RUN pip install -r requirements.txt
      CMD python /app/app.py
    • Dockerfile을 빌드할 때 RUN, ADD, COPY 이 명령어들은 각각의 레이어를 생성하고 CMD, LABEL, ENV, EXPOSE는 레이어를 생성하지 않음
    • 빌드하면 시간이 오래 걸림
    • RUN 명령어들은 하나로 합칠 수 있다면 하나로 합치는게 좋음
    • 기반 이미지를 사용할 때 alpine 버전을 사용하면 용량이 작기 때문에 성능 향상에 도움이 됨
      FROM python:3.9.2-alpine
      COPY app.py /app
      RUN apt-get update && apt-get -y install python-pip
      RUN pip install -r requirements.txt
      CMD python /app/app.py 
    • 기반 이미지에 개발 환경이 설치된 이미지를 활용하면 빌드 성능 향상에 도움이 됨
    • 빌드 캐시는 수정된 코드 이전까지만 적용되므로 변경될 가능성이 낮은 옵션을 상단에 배치해야 함

다양한 방법의 Dockerfile 작성

  • 쉘 스크립트를 이용한 환경 구성: 환경 변수들을 sh 파일에 작성하고 이 파일을 실행시켜서 환경 구성을 수행
    • 디렉터리를 생성하고 프롬프트 이동
    • Dockerfile 생성 및 작성
FROM ubuntu:latest

RUN apt-get update && apt-get -y install apache2

RUN echo 'Docker Container Application' > /var/www/html/index.html

RUN mkdir /webapp

RUN echo './etc/apache2/envvars' > /webapp/run_http.sh && echo 'mkdir -p /var/run/apache2' >> '/webapp/ru>

EXPOSE 80

CMD /webapp/run_http.sh
  • ADD 명령어의 자동 합축 해제 기능 활용
- 압축 파일 가져오기
sudo apt install git

git clone https://github.com/brayanlee/webapp.git

- 압축 파일이 있는 곳으로 프롬프트를 이동
cd webapp 

ls 명령으로 압축 파일이 있는지 확인

- Dockerfile이 저장될 디렉터리를 생성
mkdir dockerfiles

- Dockerfile 생성하고 작성: nano dockerfiles/Dockerfile
FROM ubuntu:latest

RUN apt-get update && apt-get -y install apache2 vim curl

ADD webapp.tar.gz /var/www/html

WORKDIR /var/www/html

EXPOSE 80

CMD /usr/sbin/apachectl -D FOREGROUND

- 이미지 빌드
docker build -t webapp:8.0 -f ./dockerfiles/Dockerfile .

- 컨테이너 생성
docker run -dit -p 8201:80 --name webapp8 webapp:8.0

- 압축된 파일이 해제되었는지 확인
docker exec -it webapp8 /bin/bash

ls

- 소스 파일을 이미지에 복사하고자 하는 경우 파일 단위로 복사하는 것은 자원의 낭비이므로 디렉토리 전체를 복사하던가 압축된 파일의 형태로 복사하는 것이 효율적
- Dockerfile의 경로가 현재 디렉터리가 아니거나 현재 디렉터리에 있더라도 Dockerfile이라는 이름이 아닌 경우는 -f 옵션을 이용해서 파일 경로를 설정해 주어야 함
  • Ubuntu Linux를 기본 이미지로 해서 패키지를 설치한 경우 용량을 축소하고자 하는 경우에는 RUN 명령에서 apt-get clean(설치에 사용한 패키지 라이브러리, 임시 파일, 오래된 파일을 삭제), apt-get autoremove(다른 패키지들의 종속성을 충족시키기 위해 자동으로 설치된 패키지를 삭제), rm -rfv(apt와 관련된 캐시를 삭제) 명령을 수행해서 불필요한 패키지를 제거해주면 됨
    • 이전에 사용한 도커 파일을 수정(nano dockerfiles/Dockerfile)
      FROM ubuntu:latest
      
      RUN apt-get update && apt-get -y install apache2 vim curl && apt-get clean -y && apt-get autoremove -y && rm -rfv /var/lib/apt/lists/* /tmp/* /var/tmp/*
      
      ADD webapp.tar.gz /var/www/html
      
      WORKDIR /var/www/html
      
      EXPOSE 80
      
      CMD /usr/sbin/apachectl -D FOREGROUND
      
      
      - 이미지 빌드
      docker build -t webapp:9.0 -f ./dockerfiles/Dockerfile .
      
      - 이미지 크기 확인
      docker images   

Python Flask 애플리케이션 빌드

  • ENV부분을 제외하고 ENTRYPOINT와 마지막 CMD 부분을 수정하면 모든 Python 애플리케이션을 빌드하는 방법은 비슷(Flask 는 python 파일명으로 실행)
  • 디렉터리를 생성 mkdir py_flask && cd py_flask
  • 소스 코드 작성(app/py_app.py)
=>디렉토리를 생성
mkdir py_flask && cd py_flask

=>소스 코드 작성(app/py_app.py)
mkdir app && nano app/py_app.py
from flask import Flask

py_app = Flask(__name__)

@py_app.route('/')
def python_flask():
        return "<h1>Hello Flask</h1>"

if __name__ == "__main__":
        py_app.run(host="0.0.0.0", port=9000, debug=True)
  • 패키지 의존성을 위한 app/requirements.txt 생성
Flask==1.12
  • 현재 디렉터리에 Dockerfile을 만들고 작성
FROM python:3.8-alpine

RUN apk update && apk add --no-cache bash

RUN apk add --update build-base python3-dev py-pip

ENV LIBRARY_PATH=lib:/usr/lib
ENV FLASK_APP=py_app
ENV FLASK_ENV=development

EXPOSE 9000

WORKDIR /py_app
COPY ./app/ .

RUN pip install -r requirements.txt

ENTRYPOINT ["python"]
CMD ["py_app.py"]
  • 이미지 빌드 docker build -t py_flask:1.0 .