본문 바로가기
Backend MLOps/개인 환경 구축 기록

[ 자취방 워크스테이션 ] #18 도커에서 주피터 열어서 외부접속 해보기

by SteadyForDeep 2021. 3. 19.
반응형

//1

도커를 깔았다.

그런데 뭐 하는 건지 아직 감이 안 잡힌다. (정상이다)

백문이 불여일타라고 한번 해보자.

 

 

 

 

//2

우선 도커는

UNIX소캣에 물린 서로 다른 가상의 작은 컴퓨터들로 이해한다고 했었다.

그러면 지금 그 컴퓨터가 몇 대가 생겼는지

어떠한 상태로 있는지 보는 방법이 있다.

$ docker --help

그래도 도커와 첫 만남인 만큼 help정도는 들여다 봐주자.

 

 

 

팁 아닌 팁인데 | grep 을 이용해서 원하는 키워드를 검색하면

쉽게 어떤 명령어가 있는지 찾는 경우가 있다.

대신 첫글자가 대문자일 경우가 있으니 둘 다 해봐야 한다.

list 를 보여주는 명령어가 나온다.

 

ps를 하면 현재 컨테이너를 보여준다고 한다.

$ docker ps

 

 

에잉

아무것도 나오지 않는다.

나에게 거짓말을 한 것인가?

도커 놈들은 정말 믿을게 못된다.

 

라고 생각하면 안 된다.

 

 

--help는 이렇게

커멘드 뒤에도 옵션을 붙이는 것이 가능한데

-a 옵션을 보면

이 옵션을 붙이면 모든 컨테이너가 보이고

default의 경우 즉 붙이지 않으면

running중인 것들만 보여준다고 한다.

 

 

 

-a 혹은 --all을 붙이니까 running 중이지 않은 녀석들도 다 보인다.

hello-world라던지 뭔가 테스트하기 위해서 실행한 모든 녀석들이다.

어떤 이미지를 썼는지,

어떤 커멘드를 입력했는지,

언제 만들어졌는지,

상태는 어떤지,

물려있는 포트는 몇 번인지

그리고 가장 중요한 이름이 뭔지 이런 게 뜬다.

도커 컨테이너를 생성할 때 이름을 따로 지정하지 않으면

도커가 아무 이름이나 막 갖다 붙여버리는데

저기 있는 고무로된_몸(?)을 없애보자.

 

$ docker rm elastic_body

"ela"까지만 하고 탭을 눌러주면 자동완성이 된다.

 

 

무심하게 "신축성있는_몸" 이라고 알려준다.

확인해보면? 사라져있다.

 

이런 식으로 다른 것들도 모두 지워준다.

 

 

rm 이하 띄어쓰기를 구분자로 이름들을 여러 개 붙여서

한 번에 지울 수 있다. 탭탭탭 해서 다 지우자.

 

 

 

 

이젠 우리가 정말 원하는 컨테이너를 올릴 차례인데

텐서플로우에서 공식적으로 지원하는 컨테이너 이미지들은

아래의 페이지에서 확인할 수 있다.

www.tensorflow.org/install/docker

 

Docker  |  TensorFlow

Docker는 컨테이너를 사용하여 TensorFlow 설치를 나머지 시스템에서 격리하는 가상 환경을 만듭니다. TensorFlow 프로그램은 호스트 머신과 리소스를 공유(디렉터리 액세스, GPU 사용, 인터넷 연결 등)

www.tensorflow.org

지피유를 지원하면서 주피터를 기본 에디터로 사용하는 이미지를 받아오자.

$ docker pull tensorflow/tensorflow:latest-gpu-jupyter

docker pull [OPTIONS] NAME[:TAG|@DIGEST]

pull 은 도커 저장소에 있는 이미지를 불러 오는 커멘드이다.

옵션은 사용하는 경우를 거의 못 봤다. (필요할 때 추가로 공부하면 될 것 같다.)

NAME은 저장소에 위치한 이미지 이름이다.

이 이름 뒤에 tag를 계속해서 달아서 원하는 이미지를 받을 수 있다.

-는 태그 간의 구분자로

여러 개의 태그를 동시에 달아서 작업을 수행할 수 있다.

 

 

 

진행단계를 볼 수 있다.

역시 이미지 이름은 자동완성 기능이 된다.

노파심에 이야기하지만

sudo를 안쳐도 되게 설정해 둔 것이니

이 설정을 하지 않은 유저는 sudo를 붙여줘야 한다.

 

//3

이미지를 받았으니 본격적으로 컨테이너를 생성할 수 있다.

그런데 중요한 것은

컨테이너를 어떤 방식으로 사용할지 설계하는 것이다.

사실은 우분투로 딥러닝을 좀 돌려본 내공이 있는 사람들이라면

뚝딱뚝딱 해낼 일이지만

이 부분이 어려운 분들은 내가 추천하는 방식을 따라보길 바란다.

 

나는 목표하는 바가

1. 컨테이너를 통해서 독립적인 텐서 플로우 개발환경을 생성한다.

2. 컨테이너 내부에서 주피터 서버를 열어서 코딩 및 개발환경 컨트롤을 한다.

3. 컨테이너 내부의 주피터로 외부에서 접근할 수 있도록 한다.

 

이 세 가지 임을 미리 말하고 출발하겠다.

 

//4

 

 

한눈에 살펴보자.

언제나 개념적인 설계도를 그리고 출발하는 습관은 좋은 습관에 해당한다.

2020.12.15 - [딥러닝/개인 환경 구축 기록] - [ 자취방 워크스테이션 ] #4 포트포워딩 및 네트워크 설정

 

[ 자취방 워크스테이션 ] #4 포트포워딩 및 네트워크 설정

//인트로 이번 주제는 내용이 길어서 2번에 나누어 설명할지도 모르겠다. 일단 들어가 보자. 원격 접속이 가능하도록 우분투 서버를 세팅 하는 작업을 시작 하겠다. 나스 (NAS) 나 개인 서버를 만

davi06000.tistory.com

용어들의 이해는 본 블로그의 포트포워딩 3부작을 보면 알 수 있다!

댓글도 환영한다. (정말이다)

 

소켓 연결은 계층 생성의 역순으로 생각하면 편하다.

예를 들어서 설명해보자.

 

1. 주피터를 열 때 도커 컨테이너 A의 내부에서 8888 포트로 노트북을 연다.

->이때 8888 포트는 UNIX소캣이다.

 

2. 도커 컨테이너를 만들 때 TCP 포트 7777과 컨테이너 A의 내부의 8888을 연결한다.

->이때 TCP 포트는 192.X.X.X : 7777로 DHCP로 할당받은 IP에 딸려있는 포트다.

 

3. 이 192.X.X.X : 7777 은 123.X.X.X : 6666으로 포트포워딩 되어있다.

->공유기의 IP는 123.X.X.X 이다.

 

4. 외부 접속자는 123.X.X.X : 6666 을 통해서 도커 컨테이너 A의 내부의 주피터로 도달한다.

 

이 과정이 머릿속에 그려지는 것이 굉장히 중요하다!

이것을 반드시 이해해야만 진정한 도커 사용이라고 할 수 있다.

이해가 되지 않으면 여러 번 읽고 저 위의 이미지에 대입시켜보길 바란다.

분명히 사람이 이해할 수 있는 내용이다.

 

대부분의 경우 포트를 헷갈리지 않기 위해서 8888:8888:8888:8888... 이딴 식으로 쓰는데..

이게 여간 헷갈리는 작업이 아니다.

 

//5

머릿속에 그림이 그려졌다면 컨테이너를 만들 차례다.

이전 글들을 따라왔다면 이미 3과 4는 완성된 상태이다.

 

도커 이미지를 이용해서 컨테이너를 만드는 방법은 아래와 같다

$ docker run [OPTIONS] IMAGE[:TAG|@DIGEST] [COMMAND]

맨 끝에 있는 [COMMAND]는 도커를 만들고 그 안에서 실행할 커멘드를 입력하는 것이다.

 

이 부분을 잘 알아보자.

docker run : create 와 start 가 합쳐진 명령어다. 이미지를 이용해서 컨테이너를 만들고 실행까지 같이 한다.

[OPTIONS] : run 뒤에 붙을 수 있는 옵션들을 이야기한다. 포트를 연결한다던지 커멘드 창을 연다 던 지 하는 것이다.

IMAGE[:TAG|@DIGEST] : 컨테이너를 만들 때 사용할 이미지와 태그를 입력하는 부분이다.

[COMMAND] : 컨테이너를 생성할 때 기본적으로 입력해주는 커멘드로 커멘드가 시작함과 동시에 실행된다.

 

사실은 start의 경우 컨테이너 이름만 알고 있으면 되기 때문에 이 모든 명령은 create과 관련이 있다.

아래의 사진을 참고하여 create과 run이 얼마나 유사한지 확인해보라.

 

 

여기서 중요한, 아주 아주 아주 중요한 개념이 등장한다.

 

도커에서 컨테이너를 만들 때 기본 수행 명령이 반드시 존재한다!

 

이게 이해가 처음엔 잘 안 갈 수 있다.

컴퓨터가 한 대 더 생기는 거라면서 그냥 컴퓨터를 켜고 명령어를 치고 실행하면 되는 것 아닌가?

물론 맞는 말이다. 하지만 그건 개인이 작업을 수행하는 컴퓨터에 국한되는 말이다.

 

우리가 처음에 우분투 서버를 설치했을 때, 그리고 그래픽카드 드라이버를 깔았을 때

그 편한 GUI 기능을 애써 꺼버린 사실을 기억할 것이다.

 

이렇듯 컴퓨터는 우리가 깔지 않아도 OS라는 이름으로 정말 수많은 기능이 함께 탑재되어있다.

그런데 이게 모든 상황에 꼭 필요할까?

당연히 그렇지 않다. 우리가 알지도 못하는 기능들

(예를 들면 "접근성"으로 불리는 기능들이 있겠다.)

은 정말 꼭 필요한 사람에게는 유용하지만 컴퓨터의 자원을 최대한으로 끌어올려야 하는 상황에서는 없는 게 낫다.

 

도커는 애초에 취지가 앱의 개발이 아닌 완성된 앱의 배포와 관리에 있기 때문에

대부분의 도커 이미지는 당황스러울 만큼 최소한의 기능들만을 제공한다.

 

그래서 대부분의 컨테이너는 컨테이너를 생성할 때

범용적인 환경이 아닌 어떤 앱에 특화된 최소한의 기능만(즉 최적의 환경)을 제공하고

그 앱의 실행을 커맨드로 입력해주게 된다.

 

한마디로, 도커 컨테이너는 내부에서 무언가 돌아가고 있어야만 running 상태가 유지된다.

 

이 부분이 직관적인 가상 환경과 VM보다 컨테이너를 이해하기 어려운 이유가 된다.

이 부분은 나중에 도커를 사용하지 않고 리눅스와 아나콘다만으로 서버를 꾸리는 방식을 설명할 때

더욱 자세하게 다루도록 하겠다.

 

지금 중요한 건 도커로 주피터를 열어보는 것이다.

 

 

 

 

//6

주피터를 열고 외부에서 접속하기 위해서 가장 필요한 옵션은

포트를 내외로 연결하여 컨테이너를 생성하는 것으로 그러한 기능이 있는지 확인한다.

 

 

어마 무시하게 나온다. 한 번쯤은 훑어보기 바란다.

 

 

포트에 관한 내용인데 이 중에서 우리는 -p(소문자!)를 사용하여 컨테이너의 일부 포트만을 호스트에게 publish 해보자.

처음엔 잘 모르겠어도 자꾸 이런 헬프를 보는 게 나중엔 도움이 된다.

하이픈 하나짜리는 약칭으로 쓸 수 있을 경우 함께 적히게 된다.

이것 말고도 나중에 구분이 쉽게 하기 위해서 ("집중된_잭슨", "솜씨가_좋은_모제르" 같은 이름을 피하려면;;)

-name 옵션을 넣어주자.

이외에 마음에 드는 기능을 추가해줘도 무방하다.

 

이렇게 하나하나 옵션을 추가하다 보면 커맨드가 길어진다.

CLI에서는 오타를 하나 내면 수정하기가 여간 힘든 게 아니다.

깔끔하게 해결하는 방법이 있다. 베쉬스크립트를 써서 작성해보자.

베쉬스크립트는 CLI 커맨드 라인에 입력하는 내용을 미리 텍스트로 작성한 후

불러와서 실행하는 방법을 말한다.

 

아래와 같이 입력해준다.

vim tensorflow_container_run.sh

 

까만 화면이 뜰 텐데 여기는 vim이라는 에디터이다.

이 화면에서 키보드 i를 누르면 아래가 insert로 바뀐다.

 

 

insert가 아닌 다른 게 되었다면 상태 표시가 없어질 때까지 esc를 누르면 된다.

이 insert 상태에서

 

docker run \
        -d \
        --gpus all \
        -p 8888:8888 \
        -p 6006:6006 \
        --name tensorflow_gpu \
        tensorflow/tensorflow:latest-gpu-jupyter \
        jupyter notebook \
        --allow-root \
        --ip 0.0.0.0 \
        --NotebookApp.token='' \
        --no-browser

이렇게 입력한다.

-p를 두 번 쓴 이유는 두 개 이상의 포트를 연결해 줄 필요가 있는 경우에

이런 식으로 처리해 줄 수 있다는 것을 보여주기 위해서 넣었다.

실제로 6006은 tensorboard의 default 포트로 나중에 유용하게 쓸 것이다.

(사실은 안 쓰는 방법을 더 좋아한다. 그것도 알려줄 것이다.)

머리가 복잡해진다. Line-by-line 설명은 다음 챕터에서 다루겠다.

 

이제 esc를 눌러서 insert모드에서 나간 후 :wq + Enter 를 눌러서 저장 후 종료를 하자.

자세한 것은 vim명령어를 키워드로 검색하면 된다.

 

 

화면의 좌 하단이 요상태에서 엔터.

 

 

그러면 우리가 입력한 베쉬스크립트가 생겼다. 이걸 나중에 아주 다양하게 활용할 수 있으므로 꼭 숙지하자.

 

bash tensorflow_container_run.sh

이걸 하면 스크립트의 내용을 자동으로 배쉬가 읽고 동작해준다.

 

뭐가 엄청 난잡한 게 뜨고 아무 일도 일어나지 않은 것처럼 보인다.

 

 

하지만 이렇게 running 중인 컨테이너가 하나 생겼다!

 

 

 

 

이제 외부망에서 이 컨테이너 내부의 주피터에 접속해보자.

가장 손쉬운 방법은 휴대폰의 와이파이를 끄고 데이터를 쓰면서

크롬을 열고 주소창에 이렇게 입력하는 것이다.

 

[IP]:PORT

ex) 123.X.X.X:28888 요런 식

 

이게 끝이다.

이때는 우리가

2020.12.15 - [딥러닝/개인 환경 구축 기록] - [ 자취방 워크스테이션 ] #4 포트포워딩 및 네트워크 설정

 

[ 자취방 워크스테이션 ] #4 포트포워딩 및 네트워크 설정

//인트로 이번 주제는 내용이 길어서 2번에 나누어 설명할지도 모르겠다. 일단 들어가 보자. 원격 접속이 가능하도록 우분투 서버를 세팅 하는 작업을 시작 하겠다. 나스 (NAS) 나 개인 서버를 만

davi06000.tistory.com

여기서 설정해주었던 공유기의 IP 즉 네이버에서 검색했던 고정 IP를 입력하고

내부의 8888번 포트를 포트포워딩한 그 포트를 입력해 주어야 한다.

 

나는 내 서버 컴퓨터의 포트 8888을 외부 포트 28888로 포트포워딩 해주었기 때문에 28888로 접속하면 된다. 

 

 

성공이다!

 

튜토리얼 파일들이 있는데 실행해서 잘 돌아가는지 확인해보기 바란다.

 

 

 

 

반응형

댓글