ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Docker 2부 앱 빌드 및 실행
    programing 2017. 12. 8. 08:23


      시작하기 전 


    Docker 방식으로 앱을 제작할 차례입니다. 응용 프로그램의 계층 구조의 맨 아래부터 시작할 것입니다. 응용 프로그램은 페이지에서 다루는 컨테이너입니다. 다음 시간에서 다루는 컨테이너가 프로덕션 환경에서 작동하는 방식을 정의하는 서비스가 있습니다. 마지막으로 최상위 단계는 스택이며 5부 에서 다루는 모든 서비스의 상호 작용을 정의합니다.


      개발 환경


    과거에는 Python 응용 프로그램을 작성했을 경우 첫 번째 순서는 Python 런타임을 시스템에 설치하는 방법이었습니다. 하지만, 이는 앱이 예상대로 실행되기 위해서는 컴퓨터 환경이 있어야 하는 상황을 만듭니다.


    Docker를 사용하면 응용 가능한 Python 런타임을 이미지로 가져올 수 있으며 설치가 필요 없습니다. 그런 다음 빌드는 앱 코드와 함께 기본 Python 이미지를 포함 할 수 있으므로 앱의 종속성 및 런타임과 함께 실행 할 수 있습니다.


    이 이미지는 a라는 이름으로 정의됩니다 Dockerfile.


      컨테이너를 정의하려면 Dockerfile을 작성하세요. 


    Dockerfile은 컨테이너 내부 환경을 정의합니다. 네트워킹 인터페이스 및 디스크 드라이브와 같은 리소스에 대한 액세스는 시스템의 나머지 부분과 격리되어 있는 이 환경에서 가상화 되므로 포트를 외부 인터넷에 매핑하고, "복사"할 파일의 환경을 작성합니다. 그러나 이렇게 하면 정의 된 앱 빌드가 Dockerfile이 어디서나 똑같이 작동합니다.


      Dockerfile


    빈 디렉토리를 만듭니다. 디렉토리 (cd)를 이용해서 새 디렉토리로 변경하고 Dockerfile을 생성합니다. 다음 내용을 해당 파일에 복사하여 붙여 넣은 파일을 작성하고 저장하세요. 새로운 Dockerfile의 각 문장을 설명하는 주석을 기록할 수도 있습니다.


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    # 상위 이미지로서 공식 파이썬 런타임을 사용합니다.
    FROM python:2.7-slim
     
    # 작업 디렉토리를/app으로 설정합니다.
    WORKDIR /app
     
    # 현재 디렉터리 내용을 /app의 컨테이너에 복사합니다.
    ADD . /app
     
    # requirements.txt에 지정된 필수 패키지를 설치합니다.
    RUN pip install --trusted-host pypi.python.org -r requirements.txt
     
    # 이 컨테이너 외부에서 포트 80을 사용할 수 있도록 설정합니다.
    EXPOSE 80
     
    # 환경 변수 정의
    ENV NAME World
     
    # 컨테이너가 시작될 때 app.py을 실행합니다.
    CMD ["python""app.py"]
    cs


    프록시 서버를 사용하고 있나요?

    프록시 서버는 일단 실행되면 웹 응용 프로그램에 대한 연결을 차단할 수 있습니다. 프록시 서버를 사용하는 경우 다음 ENV명령을 Dockerfile에 추가하여 명령을 사용하여 프록시 서버의 호스트 및 포트를 지정하세요.


    1
    2
    3
    # 프록시 서버를 설정하고 host:port를 서버에 대한 값으로 바꿉니다.
    ENV http_proxy host:port
    ENV https_proxy host:port
    cs


    Dockerfile은 아직 만들지 않은 몇 가지 파일이 있습니다. 즉 app.py이 requirements.txt를 참조 합니다. 다음 단계를 만들어 보겠습니다.


      앱 내용 만들기


    Dockerfile과 두 개의 파일 requirements.txt와 app.py과 함께 같은 폴더에 넣으세요. 이것은 앱을 완성 시켰을 때 볼 수 있는 것처럼 그것은 아주 간단합니다. app.py은 Dockerfile이미지에 내장되어 있습니다. 그리고 모듈은requirements.txt를 참조해서 설치하기 때문에 실행될 수 있습니다. Dockerfile의 ADD명령과 출력은 app.py과 EXPOSE 명령에서 받는 HTTP를 통해 액세스 할 수 있습니다.


    app.py

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    from flask import Flask
    from redis import Redis, RedisError
    import os
    import socket
     
    # Connect to Redis
    redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2)
     
    app = Flask(__name__)
     
    @app.route("/")
    def hello():
        try:
            visits = redis.incr("counter")
        except RedisError:
            visits = "<i>cannot connect to Redis, counter disabled</i>"
     
        html = "<h3>Hello {name}!</h3>" \
               "<b>Hostname:</b> {hostname}<br/>" \
               "<b>Visits:</b> {visits}"
        return html.format(name=os.getenv("NAME""world"), hostname=socket.gethostname(), visits=visits)
     
    if __name__ == "__main__":
        app.run(host='0.0.0.0', port=80)
    cs


    이제 pip install -r requirements.txt는 Python을위한 Flask와 Redis 라이브러리를 설치하고, app은 환경 변수 NAME 호출 결과를 socket.gethostname()로 출력합니다.  마지막으로, Redis가 실행되지 않기 때문에 (우리는 Redis 자체가 아닌 Python 라이브러리 만 설치했기 때문에) 여기에서 사용하려는 시도가 실패하고 오류 메시지가 생성 될 것으로 예상해야 합니다.


    참고 : 컨테이너 내부에서 호스트 이름에 액세스하면 실행중인 실행 파일의 프로세스 ID와 같은 컨테이너 ID가 검색됩니다.


    requirements.txt시스템에 Python이나 다른 것이 필요하지 않으며 이 이미지를 빌드 하거나 실행하면 시스템에 설치되지 않습니다. 파이썬과 플라스크로 환경을 설정 한 것처럼 보이지는 않습니다.


      앱 만들기


    앱을 만들 준비가 되었습니다. 새 디렉토리의 최상위에 위치해 있는지 확인하세요. ls가 표시해야 할 내용 은 다음과 같습니다 .

    1
    2
    $ ls
    Dockerfile        app.py            requirements.txt

    cs


    이제 빌드 명령을 실행하세요.. 이렇게 하면 Docker 이미지가 생성됩니다. Docker 이미지 -t는 friendly 이름으로 태그를 지정합니다.


    1
    $ docker build -t friendlyhello
    cs


    내장 된 이미지는 컴퓨터의 로컬 Docker 이미지 레지스트리에 있습니다.

    1
    2
    3
    4
    $ docker images
     
    REPOSITORY            TAG                 IMAGE ID
    friendlyhello         latest              326387cea398
    cs


    팁 : command docker images또는 최신 docker image ls목록 이미지를 사용할 수 있습니다.


      앱 실행


    -p을 사용하여 기기의 포트 4000을 컨테이너에서 실행된 포트 80에 매핑하여 앱을 실행합니다.

    1
    $ docker run -p 4000:80 friendlyhello
    cs

    http://0.0.0.0:80에서 파이썬이 앱을 제공한다는 메시지가 나타납니다 . 하지만 이 메시지는 컨테이너 내부에서 접속해 오는데요. http://localhost:4000에서는 컨테이너의 포트 80을 4000으로 매핑하여 올바른 URL을 작성했는지 알지 못합니다. 


    웹 브라우저에서 해당 URL로 이동하여 "Hello World"텍스트, 컨테이너 ID 및 Redis 오류 메시지를 포함하여 웹 페이지에 표시되는 디스플레이를 확인해보세요.

    참고 : localhost Windows 7에서 Docker Toolbox를 사용하는 경우 대신 Docker Machine IP를 사용하세요. 

    ex: http://192.168.99.100:4000/의 IP 주소를 찾으려면 이 명령을 사용하세요. docker-machine ip.


    쉘에서 curl 명령을 사용 하여 동일한 내용을 볼 수도 있습니다.

    1
    2
    $ curl http://localhost:4000
    <h3>Hello World!</h3><b>Hostname:</b> 8fc990912a14<br/><b>Visits:</b> <i>cannot connect to Redis, counter disabled</i>
    cs

    매핑이 포트는 4000:80 차이를 설명하는 것입니다. EXPOSE내에서 Dockerfile은 publish사용 docker run -p을 사용할 수 있습니다. 나중 단계에서 호스트의 포트 80을 컨테이너의 포트 80에 매핑하고 http://localhost 사용합니다.


    팁: 종료는 CTRL+C 단축키를 이용할 수 있습니다.


    Windows에서는 명시 적으로 컨테이너를 중지합니다.


    Windows 시스템에서는 CTRL+C컨테이너를 중지하지 않습니다. 따라서 먼저 CTRL+C프롬프트를 다시 가져 오거나 (또는 ​​다른 쉘을 여는) 입력 한 다음 docker container ls 실행중인 컨테이너 목록을 입력 한 다음 컨테이너 docker container stop <Container NAME or ID>을 중지하세요. 그렇지 않으면 다음 단계에서 컨테이너를 다시 실행하려고 시도 할 때 데몬에서 오류 응답을 받습니다.


    이제 백그라운드에서 분리 모드로 앱을 실행 해 봅니다.

    1
    $ docker run -d -p 4000:80 friendlyhello
    cs


    앱에 대한 긴 컨테이너 ID를 얻은 다음 터미널로 다시 가져옵니다. 컨테이너가 백그라운드에서 실행 중입니다. 다음과 같이 축약 된 컨테이너 ID를 볼 수도 있습니다 docker container ls(및 명령을 실행할 때 둘 다 교환 가능하게 작동 함).

    1
    2
    3
    $ docker container ls
    CONTAINER ID        IMAGE               COMMAND             CREATED
    1fa4ab2cf395        friendlyhello       "python app.py"     28 seconds ago
    cs


    현재 CONTAINER ID와 일치하는 것을 http://localhost:4000에서 볼 수 있습니다.

    이제 docker container stop다음 CONTAINER ID를 사용해서 프로세스를 종료하세요.


    1
    $ docker container stop 1fa4ab2cf395
    cs


      이미지 공유


    방금 만든 이미지의 호환성을 보여주기 위해 빌드 된 이미지를 업로드하고 다른 곳으로 옮겨보겠습니다. 프로덕션에 컨테이너를 배포하려는 경우 레지스트리로 푸시하는 방법을 배워야 합니다.


    레지스트리는 저장소의 모음이며 저장소는 이미 만들어진 코드를 제외하고는 GitHub 저장소와 같은 종류의 이미지 모음입니다. 레지스트리의 계정은 많은 리포지토리를 생성 할 수 있습니다. dockerCLI는 기본적으로 container worker의 공개 레지스트리를 사용합니다.


    참고 : Docker의 공개 레지스트리는 무료이며 미리 구성되어 있기 때문에 여기에서 사용 하겠지만, 선택할 수 있는 공용 레지스트리가 많으며 Docker Trusted Registry를 사용하여 개인 레지스트리를 설정할 수도 있습니다.


      Docker ID로 로그인하세요.


    Docker 계정이 없는 경우 cloud.docker.com 에서 가입하세요. 로컬 시스템의 Docker 공용 레지스트리에 로그인하세요.


    1
    $ docker login
    cs


    이미지에 태그 달기

    로컬 이미지를 레지스트리의 저장소와 연관시키는 표기법은 다음과 같습니다 username/repository:tag. 이 태그는 선택 사항이지만 Docker 이미지에 버전을 제공하는데 사용하는 메커니즘이기 때문에 권장됩니다. 저장소와 같은 문맥에 의미 있는 이름을 붙이세요. get-started:part2. 이것은 이미지를 get-started저장소에 넣고 태그를 저장합니다.


    이제 이미지를 모두 태그에 추가하세요. docker tag image의 사용자 이름, 저장소 및 태그 이름을 사용하여 실행 하면 이미지가 원하는 대상에 업로드 됩니다. 명령 구문은 다음과 같습니다.


    1
    2
    $ docker tag image username/repository:tag
    $ docker tag friendlyhello john/get-started:part2
    cs


    docker images를 실행해서 새로 태그가 추가 된 이미지를 확인할 수 있습니다. (docker image ls)

    1
    2
    3
    4
    5
    6
    $ docker images
    REPOSITORY               TAG                 IMAGE ID            CREATED             SIZE
    friendlyhello            latest              d9e555c53008        3 minutes ago       195MB
    john/get-started         part2               d9e555c53008        3 minutes ago       195MB
    python                   2.7-slim            1c7128a655f6        5 days ago          183MB
    ...
    cs


    이미지 업로드

    태그가 지정된 이미지를 저장소에 업로드하십시오.

    1
    $ docker push username/repository:tag
    cs

      repository에서 이미지를 불러와서 실행하세요.


    이제부터는 docker run을 사용하여 모든 컴퓨터에서 앱을 사용 하고 실행할 수 있습니다.

    1
    $ docker run -p 4000:80 username/repository:tag
    cs


    이미지가 컴퓨터에서 로컬로 사용할 수 없는 경우 Docker는 리포지토리에서 이미지를 가져옵니다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    $ docker run -p 4000:80 username/repository:tag$ docker run -p 4000:80 john/get-started:part2
    Unable to find image 'john/get-started:part2' locally
    part2: Pulling from john/get-started
    10a267c67f42: Already exists
    f68a39a6a5e4: Already exists
    9beaffc0cf19: Already exists
    3c1fe835fb6b: Already exists
    4c9f1fa8fcb8: Already exists
    ee7d8f576a14: Already exists
    fbccdcced46e: Already exists
    Digest: sha256:0601c866aab2adcc6498200efd0f754037e909e5fd42069adeff72d1e2439068
    Status: Downloaded newer image for john/get-started:part2
     * Running on http://0.0.0.0:80/ (Press CTRL+C to quit)
    cs

    참고 : :tag 명령의 일부를 지정하지 않으면 :latest 빌드 할 때와 이미지를 실행할 때 모두 의 태그가 사용 됩니다. Docker는 지정된 태그 없이 실행 된 이미지의 마지막 버전을 사용합니다 (최신 이미지 일 필요는 없습니다).


    어디에서 docker run실행 되든 Python 및 모든 종속성과 함께 이미지를 가져 와서 requirements.txt코드를 실행합니다. 모든 것이 깔끔한 작은 패키지로 함께 진행되며, 호스트 시스템은 Docker를 실행하기 위해 아무것도 설치하지 않아도됩니다.


      정리내용


    사용된 모든 명령어 정리

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    $ docker build -t friendlyname .  # 이 디렉토리의 Dockerfile을 사용하여 이미지를 생성합니다.
    $ docker run -4000:80 friendlyname  # friendlyname매핑 포트 4000~80
    $ docker run --4000:80 friendlyname         # Same thing, but in detached mode
    $ docker container ls                                # 컨테이너 조회
    $ docker container ls -a             # 실행되지 않는 모든 컨테이너 목록 나열
    $ docker container stop <hash>           # 실행중인 컨테이너를 정지시킵니다.
    $ docker container kill <hash>         # 지정된 컨테이너의 강제 종료
    $ docker container rm <hash>        # 이 시스템에서 지정된 컨테이너 제거
    $ docker container rm $(docker container ls --q)         # 모든 컨테이너 제거
    $ docker image ls -a                             # 모든 이미지 리스트 조회
    $ docker image rm <image id>            # 이 시스템에서 지정된 이미지를 제거합니다.
    $ docker image rm $(docker image ls --q)   # 이 시스템에서 모든 이미지를 제거합니다.
    $ docker login             # Docker자격 증명을 사용하여 이 CLI세션에 로그인합니다.
    $ docker tag <image> username/repository:tag  # 이미지 레지스트리에 업로드
    $ docker push username/repository:tag            # 태그가 지정된 이미지를 레지스트리로 업로드
    $ docker run username/repository:tag                   # 레지스트리에서 이미지 실행
    cs

    참조: https://docs.docker.com/get-started/part2/docker docs의 번역본입니다.

    'programing' 카테고리의 다른 글

    Xshell 소개 및 다운로드  (0) 2017.12.12
    Docker 3부 서비스  (0) 2017.12.09
    Docker 시작하기 1부  (0) 2017.12.07
    Docker 설치 링크  (0) 2017.12.06
    컨테이너 기술 'Docker'  (0) 2017.12.05
Designed by Tistory.