맥(Mac)에서 이해하는 도커(Docker) #2. Hyperledger Sawtooth 연결까지

in #kr7 years ago (edited)

https://steemit.com/kr/@junn/mac-docker-1 에 이은 Mac에서 Docker 이해하기 2탄입니다.

이번 포스팅은 다음 순서로 진행됩니다.

(1) ubuntu만 설치된 image에 python을 설치한 새로운 이미지를 만들어보고, 차이를 확인보는 것.

(2) python 실행이 바로되는 컨테이너 만들기 (이미지를 단일 실행파일 처럼 사용)

(3) Sawtooth-shell에 Django를 설치한 이미지 만들기

(4) Django 서버를 통해 sawtooth blockchain 출력하기 (Sawtooth가 만들어낸 genesis block을 출력한 화면은 아래와 같습니다. 이 부분은 내용이 많아 다음화로 넘기겠습니다ㅡ.)

이번 화에서는 지난 편에 이어, 이해하는 수준까지만 진행합니다.

 

<새로운 파이썬 이미지 생성하기>


목표는 아래와 같습니다. 위의 이미지로 아래의 이미지를 만들어갑니다.



이전 포스팅에서 만든 것과 같은 순서로

1> 새로운 폴더(예: python_docker)를 하나 만들고

2> 그 안에 Dockerfile 이라는 파일을 만듭니다.

==========

FROM ubuntu_junn:latest

RUN apt-get update
RUN apt-get install -y software-properties-common vim
RUN add-apt-repository ppa:jonathonf/python-3.6
RUN apt-get update

RUN apt-get install -y build-essential python3.6 python3.6-dev python3-pip python3.6-venv
RUN apt-get install -y git

RUN python3.6 -m pip install pip --upgrade
RUN python3.6 -m pip install wheel

============

'FROM' 을 통해 우리가 기본(base)로 삼을 이미지를 정하고, RUN apt-get 등의 명령어를 통해 python을 설치합니다.

3> $ docker build -t python_junn:3.6 . #뒤의 . 은 Dockerfile 경로입니다.

4> $ docker images

두 이미지가 보입니다. 아래 그림은 지난 포스팅에 적은 개념입니다. 만들어낸 이미지를 이용해 새로운 것을 올리는..




<이제 두 이미지를 각각 실행시켜 비교해보겠습니다>


1> 이미지를 실행(컨테이너화) 합니다

-t, -d 옵션을 붙임으로서 백그라운드에서도 실행되도록 하는 의미가있습니다.

-d를 실행시키지 않으면 exit를 눌러 컨테이너에서 나올때 컨테이너가 종료됩니다. -t가 거의 항상 따라옵니다. '터(t)미널을 이용한다' 라고 외웠습니다.

--name은 컨테이너 이름입니다. 동일 이미지로 여러 컨테이너를 만들 수 있다는 것을 고려하면, 왜 컨테이너 이름이 필요한지 이해할 수 있습니다.

--name (컨테이너이름) (이미지이름) 이런식이죠.

$ docker run -t -d --name my_ubuntu ubuntu_junn

$ docker run -t -d --name my_python python_junn:3.6

ubuntu_junn의 경우 실제 이미지가 ubuntu:latest 이기 때문에 태그(TAG;docker images 명령어로 확인 가능)를 안붙여줘도 됩니다.

$ docker container ls #실행된 컨테이너 목록



위에서 -t,-d가 안붙으면 실행되는 즉시 exit이 되어버립니다. 컨테이너가 중지되버리죠. 그래서 백그라운드화가 필요합니다.

 

2> 두 이미지를 비교해보겠습니다.

$ docker exec -i -t my_ubuntu /bin/bash - 에러가 나지 않습니다.

$ docker exec -i -t my_python /bin/bash - 에러가 나지 않습니다.

 

$ docker exec -i -t my_ubuntu /usr/bin/python3.6 - 에러가 납니다.

$ docker exec -i -t my_python /usr/bin/python3.6 - 에러가 나지 않습니다.

당연한 이야기겠지만 my_ubuntu 컨테이너(ubuntu_junn 이미지)에는 파이썬이 설치되지 않았기 때문입니다.

 

<이 개념을 이용해서 어떻게 사용할 수 있을 까요?>


이미지를 어떻게 활용하느냐에 따라 다양한 방법이 가능합니다.

예를 들면 ubuntu에 python 과 nginx를 설치한다고 했을때, (bash는 기본입니다)

아래와 같이 python만 올라가있는 image를 만들 수 도 있고, 또는 다른 패키지까지 설치된 이미지를 만들어도 됩니다. 각각은 다 독립적인 이미지가 되는것이죠.

녹색으로 그려진 것과 같은, 여러 패키지가 있는 컨테이너라면, 그 내부에 특정 실행파일만 사용할 필요가 있습니다. 이미 위에서 예제를 보여드렸지만, 아래와 같이 실행을 나눠서 하면 됩니다.

$ docker exec -i -t my_python /bin/bash

$ docker exec -i -t my_python /usr/bin/python3.6

혹은 Dockerfile 맨 아래에 CMD ["python", "example.py"] 처럼 써서 아예 실행이 자동으로 되어버리는 image를 구성할 수 있습니다. (다음편에 django 서버 실행하기 위한 예제로 보여드리겠습니다)

 

< Sawtooth의 shell에 django를 넣은 이미지를 만듭니다 >


1> Sawtooth 설치하기

https://sawtooth.hyperledger.org/docs/core/releases/latest/app_developers_guide/docker.html

위의 예제를 통해 Docker image설치를 진행합니다. 쉽게 Docker compose라는 것을 사용합니다.

https://sawtooth.hyperledger.org/docs/core/releases/latest/app_developers_guide/sawtooth-default.yaml

도커 컨테이너들이 작동하게 되면 $ docker container ls 에서 아래와 같이 작동이 됩니다.

각각 다양한 기능들이 있지만 가장 중요한것은 sawtooth-shell-default라는 이름의 컨테이너입니다. 쉘로 접속하는 방법이

$ docker exec -it sawtooth-shell-default bash

와 같습니다만, python SDK 실행을 위해 (물론 bash로 들어가서 python3 를 실행시켜됩니다만)

$ docker exec -it sawtooth-shell-default python3

이후 SDK를 불러오면 오류없이 진행됩니다.



 

2> 이제 Sawtooth-shell-default에 Django를 포함시킨 이미지를 만들어봅니다

물론 장고 프로젝트 자체는 외부에서 작성할 예정이나, 먼저 sawtooth-shell-default에 django 실행가능한지 봐보면,

검색되지 않습니다. 따라서 이제 여태까지 배운 이미지 만들기를 실행합니다.

폴더를 새로 만들고, Dockerfile을 작성했습니다.

Django 설치를 위한 Dockerfile은 다음 사이트를 참조했습니다. (https://docs.docker.com/compose/django/)

여기서 nginx, vim은 개인적인 필요로 설치한 것으로 꼭 필요하지는 않습니다.


FROM hyperledger/sawtooth-all:1.0

RUN apt-get update
RUN apt-get install -y python3-pip
RUN apt-get install -y nginx
RUN apt-get install -y vim

ENV PYTHONUNBUFFERED 1
RUN mkdir /code
WORKDIR /code
ADD requirements.txt /code/
RUN pip3 install --upgrade pip
RUN pip3 install -r requirements.txt
ADD . /code/


$ docker build -t django_junn:latest . #django_junn이라는 이름의 컨테이너 입니다.

이후

$ docker run -td --name my_django django_junn #백그라운드에서 이미지를 컨테이너화

$ docker exec -it my_django python3 #컨테이너의 python3 실행

기본으로 될 django, sawtooth_sdk가 잘 로딩이 됩니다.

 

< Django를 통해 Sawtooth block들을 확인해보겠습니다 >


여기서 부턴 조금 복잡해져서 다음화에서 다시 설명하겠습니다.

개념만 정리하면,

1> '내 컴퓨터'에 장고 프로젝트를 작성합니다.

2> 그것을 Container 화 할때 특정 폴더로 연결합니다. 이렇게 하면 외부에서 pyCharm으로 파일을 수정하면 컨테이너 내부에서도 알아서 적용됩니다.

3> 그리고 Container 화 할때 Sawtooth의 rest-api 컨테이너랑도 연결해줘야합니다.

이때는 Sawtooth compose로 실행된 녀석들이 하나의 네트워크를 이루고 있기 때문에 직접 만든 컨테이너를 이 네트워크에 붙여줘야 합니다.(네트워크 확인은 docker inspect <컨테이너이름> 에서 확인합니다)

4> Django의 포트를 8000으로 열텐데, container 만들때 외부에서 이 포트와 연결할 포트(-_-)를 또 열어줘야합니다.

그래서 나온 실행 명령어는 아래와 같습니다.

docker run -dt -p 8000:8000 -v /Users/junn/django_docker/helloworld/:/webserver --name my_django --link sawtooth-rest-api-default:rest-api --network=django_default django_junn

5> bash로 들어가 django를 실행합니다.

이런게 매우 복잡하기 때문에 나온 개념이 docker compose 인 것 같습니다. 나중에 제작해봐야겠습니다.

다음편에 해설하겠습니다..

이렇게 하면 이제 VM으로 돌리고있는 boot2docker의 IP:8000 의 주소로 접속이 가능하고,

python source는 아래와 같으며, 출력은

from django.http import HttpResponse
import sawtooth_sdk
import urllib.request
from urllib.request import HTTPError

def index(request):

    try:
        request = urllib.request.Request(
            'http://rest-api:8008/blocks',
            method='GET')
        response = urllib.request.urlopen(request)

    except HTTPError as e:
        response = e.file

    return HttpResponse(response)



로 다행히 정상적으로 나왔습니다.
이 예제에서는 sawtooth_sdk는 사용하지 않았습니다. block 쓰기 할 때 사용할 것 같습니다.

머리가 너무 아픕니다.

 
References
https://docs.docker.com/compose/django/#create-a-django-project
https://docs.docker.com/compose/django/#define-the-project-components
https://sawtooth.hyperledger.org/docs/core/releases/latest/app_developers_guide/ubuntu.html#starting-the-rest-api
https://semaphoreci.com/community/tutorials/dockerizing-a-python-django-web-application
http://bluese05.tistory.com/36
http://goinbigdata.com/docker-run-vs-cmd-vs-entrypoint/

Sort:  

저는 도커를 메뉴얼대로만 써봐서 개념이 잘 와닿지가 않던데 그래도 자세한 사용기가 있으니 좋네요

설명은 많은데 실제적으로 '내가 필요한' 예제를 찾기가 어려웠습니다. 다행히 많이 헤매지 않고 원하는 부분까지 도달한 것 같네요.

잘봤습니다. 저도 천천히 보며서 따라해봐야겠네요 ^^

네 감사합니다. 언제든지 피드백 부탁드립니다ㅎ