//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 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 포트포워딩 및 네트워크 설정
용어들의 이해는 본 블로그의 포트포워딩 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 포트포워딩 및 네트워크 설정
여기서 설정해주었던 공유기의 IP 즉 네이버에서 검색했던 고정 IP를 입력하고
내부의 8888번 포트를 포트포워딩한 그 포트를 입력해 주어야 한다.
나는 내 서버 컴퓨터의 포트 8888을 외부 포트 28888로 포트포워딩 해주었기 때문에 28888로 접속하면 된다.
성공이다!
튜토리얼 파일들이 있는데 실행해서 잘 돌아가는지 확인해보기 바란다.
'Backend MLOps > 개인 환경 구축 기록' 카테고리의 다른 글
[ 자취방 워크스테이션 ] #20 도커 컨테이너의 GPU사용 확인하기 (0) | 2021.03.20 |
---|---|
[ 자취방 워크스테이션 ] # 19 주피터 노트북 기본 설정 (0) | 2021.03.20 |
[ 자취방 워크스테이션 ] #16 우분투에서 sudo없이 도커 사용하기 (0) | 2021.03.13 |
[ 자취방 워크스테이션 ] #17 우분투 서버에 NVIDIA Docker 설치하기 (0) | 2021.03.13 |
[ 자취방 워크스테이션 ] #15 우분투 서버에 NVIDA 드라이버 설치하기 (16) | 2021.03.13 |
댓글