Docker


< 목차 >


Basic

Virtual Enviroments & Virtual Machine

딥러닝, 머신러닝을 하는 데 있어 version control은 굉장히 중요한 이슈 중 하나이다. 왜냐면 오픈소스를 구현한 사람들 마다 사용한 환경이 다르기 때문인데, 쉽게말해서 어떤 Open Source 코드가 저 환경에선 돌아가고 이 환경에선 안돌아가는 경우가 많다는 것이다. 그래서 이 문제를 해결하기 위해서, 각 코드나 프로젝트마다 이에 맞는 개발 환경을 구성해주기 위해 가상 환경을 잘 만드는건 굉장히 중요하다. 그리고 이를 위해 가장 많이 쓰이는 방법들이 바로 virtualenv, pyenv, conda 그리고 오늘 중점적으로 다루게 될 Docker 같은 가상 환경 (Virtual Environments)를 사용하는 것이다.

한편 이렇게 파이썬 패키지?의 여러 버전을 관리하기 위한 방법 말고 아예 하드웨어만 같고 그 내부의 Operating System (OS)를 포함해 전혀 다른 세팅에서 개발을 하고 싶을 수도 있는데 이럴 때 가상 머신 (Virtual Machine; VM)을 사용할 수 있다.

Why Docker?

어쨌든, 그럼 여러 프로젝트를 관리하기 위해서 각 프로젝트에 맞는 환경 변수 컨트롤을 위해서, 위에서 언급한 몇 가지 가상 환경 툴 중에 하나만 골라서 쓰면 될까? 그렇지 않다. 각각이 장단점이 있겠지만 Docker를 써야 하는 이유가 몇 가지 있다.

먼저 아래의 예시를 보자.

aws2 Fig. Version Control using Conda

예를 들어 딥러닝 모델을 짜서 실험하는 환경이 그림에서와 같이 linux os (ubuntu), python3.6, pytorch1.7, CUDA 10, cudnn 7.1 등 이었다. 누군가는 “conda로 그냥 새로운 가상환경 만들고 거기에 torch같은거 깔면 되는거 아니에요?” 라고 할 수 있지만 conda가 해결해줄 수 있는 것은 일부분이라고 한다. 왜냐면 conda는 hardware library같은 non-python dependency들은 가상 환경의 범주를 벗어나기 때문에 이런 부분이 문제를 일으킬 수 있기 때문이라고 한다.

어쨌든 이런 문제점들로 인해서 하드웨어 라이브러리 같은 스택까지 다 커버하는 방법이 바로 docker를 쓰는 방법이라고 한다. (자세한건 더 찾아보시길 바랍니다.)

aws3 Fig. Version Control using Container

그럼 이번에는 가상 머신 (VM) 과 docker를 비교해보도록 하자.

docker_vs_vm3 Fig. VM vs Docker

핵심적인 비교는 바로 위의 그림에서 확인할 수 있는데, 요약하자면 바로 VM은 Infrastructure 위에 Linux, Window, MacOS 등을 다 깔아서 관리할 수 있지만 느리고 Docker는 예를들어 Host OS가 Linux라면 그 공유된 OS 위에 여러 환경을 매우 빠르게 만들어서 관리할 수 있다는 것이다. 물론 앞서 설명했듯 conda같은 가상 환경보다 더 우월하게 하드웨어까지 따로 세팅해서 편하게 관리할 수 있다니 기존에 사용되던 방법들의 장점들만 취했다고 생각할 수 있을 것 같다.

(물론 이 내용의 레퍼런스인 Blog에서는 VM과 docker를 같이 쓰는게 더 효율적이라고 하지만 지금은 관심이 없으므로 패스하겠다.)


둘의 차이는 관심있는 분들을 위해 아래에 추가적으로 첨부했다. 

docker_vs_vm1 Fig. VM vs Docker 1

docker_vs_vm2 Fig. VM vs Docker 2


1. Docker installation

Docker를 설치하는 방법은 간, 공식 홈페이지의 가이드를 쭉 따라가면 되는데 저의 경우는 Mac OS를 쓰기 때문에 Install Docker Desktop on Mac를 따라했다. (리눅스면 리눅스를 따라하면 되겠죠?)

2. Docker ID Sign Up

Docker를 쓰려면 github처럼 본인 계정이 있어야 하므로 마찬가지로 docker 홈페이지에서 가입을 한다.

(\(\rightarrow\) Get Started Today for Free)


추가적으로 도커 contrainer 내에서 gpu를 정삭적으로 잘 사용하려면 nvidia-container-toolkit을 따로 설치해줘야 한다고 한다. (출처)

distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list

sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit
sudo systemctl restart docker

아마 딥러닝 모델을 학습하기 위해 gpu가 필요한데 그냥으로는 안되고 Host OS의 nvidia driver가 필요하기 때문에 아래처럼 를 mount해서 쓰는 것 같다. (그 위에 cuda toolkit 깔고)

nvidia_docker Fig.

자세한 문서는 공식 nvidia-docker에서 확인할 수 있다. (+nvidia-docker github)


3. Start Docker

이제 본격적으로 도커를 시작해보자. 잘 설치됐다면 아래의 커맨드가 먹힐거다.

docker

docker1 Fig.

이제 아까 생성한 id와 password로 로그인해보자.

docker login

docker2 Fig.

4. pull image

이제 이미지를 pull 해보자. 이따 최종적으로는 우리가 만든 개발 환경을 빌드하는 것 까지 할거지만 지금은 남이 만든걸 땡겨올 것이다. 일단 아래의 커맨드를 입력해 현재 랩탑? (local machine)에 어떤 image가 있는지 살펴보자.

docker images

#같은 의미이다.
docker image ls 

정상적이라면 아무것도 없어야 하지만, 물려받은 서버라면 전임자들이 쓰던게 있을 수 있다.

docker3 Fig.

이제 남들이 올려둔 이미지를 땡겨보자.

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

하면 되는데, 필자는 머신러닝 연구자 이기 때문에 facebook이 공식적으로 올린 머신러닝 프레임워크 pytorch의 이미지를 땡겨보겠다.

docker pull pytorch/pytorch:latest

# 사실 default가 latest라고 한다.
docker pull pytorch/pytorch

잘 땡겨졌으면 image list에 추가돼야 한다.

docker4 Fig.

만약 내가 개발하고 싶은 버전이 최신 버전이 아니라 좀 구버전이라면 (최신 pytorch가 1.9.0이던가?), Docker Hub 에서 구 버전을 찾아서 pull할 수도 있다.

docker_hub Fig.

나는 torch1.6.0, cuda10.1, cudnn7 의 이미지를 골랐다.

docker pull pytorch/pytorch:1.6.0-cuda10.1-cudnn7-devel

이미지의 이름은 <Repository> : <Tag> 의 형식을 갖는 다고 한다. 그러니까 위의 예시에서는 pytorch/pytorch가 repository 이름이고 그 이하가 tag (버전) 인 것이므로 잘 찾으면 된다.

docker5 Fig.

5. run and stop image

잘 설치됐으니 이제 다운받은 image를 run 해 볼 것이다.

docker run -it --gpus all --name test pytorch/pytorch:1.6.0-cuda10.1-cudnn7-devel

docker run을 할 때는 많은 옵션을 추가할 수 있는데 docker run 에서 확인할 수 있다.

docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

예시)

Options 의미 -
–gpus GPU devices to add to the container  
–gpus all    
–name Assign a name to the container  
–pull Pull image before running  
–rm Automatically remove the container when it exits  
–restart Restart policy to apply when a container exits  
-it -i와 -t를 동시에 사용한 것으로 터미널 입력을 위한 옵션이라고 한다. The -it instructs Docker to allocate a pseudo-TTY connected to the container’s stdin; creating an interactive bash shell in the container. In the example, the bash shell is quit by entering exit 13.
–volume , -v mount folder  

어쨌든, 이제 띄운 container 안에 들어가지는데 우리는 torch가 깔린 linux 기반 os의 가상 머신을 띄웠다고 볼 수 있으므로 torch가 돼야한다. 확인해보자.

docker_run1 Fig.

확인했으니 컨테이너 안에서 아래의 커맨드를 입력해 나와보자.

exit

docker_run2 Fig.

나왔으니 밖에서 한번 docker container들의 상태를 체크해보자.

# 실행중인 컨테이너를 보여준다.
docker ps

# 종료된 컨테이너까지 다 보여준다.
docker ps -a

당연히 우리는 1개의 컨테이너를 실행했고, exit로 종료했기 때문에 docker ps만 타이핑 했을 때는 아무것도 없어야 정상이다.

docker_run3 Fig. 남들이 이전에 실행하고 종료했던 컨테이너들이 남아있다.

이 상태에서 종료된 컨테이너를 아예 제거까지 하고싶다면 아래의 커맨드로 remove를 하면 된다.

docker rm test

#추가적으로 rmi를 쓰면 이미지를 지운다.
docker rmi {이미지 이름}

docker_run4 Fig. 컨테이너가 제거됐다.

여태까지의 일련의 과정을 다시 반복해보면 아래와 같다.

docker_run5 Fig.


Docker Image에 따라 다르지만 기본적으로 wget, git, vim 같은 advanged packaging tool (apt)이 없으니 아래처럼 깔아줘야 한다고 하니 주의하자.

apt-get update &&
apt-get install wget && 
apt-get install git &&
apt-get install vim

  • 아 추가를 안했는데 만약 현재 로컬 (서버긴 하지만 로컬이라고 하겠다)의 폴더를 공유해서 쓰고싶으면 run 할 때 --volume 옵션을 넣어주면 된다.

how to mount local directory

docker run -it --name test --volume {마운트하고싶은 로컬 디렉토리}:/root/workspace --gpus all pytorch/pytorch:1.6.0-cuda10.1-cudnn7-devel 

docker_volume Fig. 새로 만든 컨테이너에 임시로 만들어둔 txt file이 생겼다(공유됐다).

6. tag image

docker tag는 원본 이미지를 참조한 이미지를 tag하는 건데, 사용법은 아래와 같다.

docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]

예를 들면 아래와 같이 쓸 수 있다.

docker tag pytorch/pytorch:latest seosh7039/test:1.0

위에는 필자의 docker hub id가 들어가있다. 즉 내 hub에 pytorch/pytorch:latest와 강튼 새로운 repo를 만들겠다는 것이 된다.

7. push image

다음은 아까 pull 한 이미지에 이것저것 추가한 컨테이너를 push 해서 확장?하는 것이다. (바닥부터 만들어도 될듯)

create-image Fig.

즉 내가 개발한 환경의 이미지를 그대로 docker hub에 올려서 남이 쓸 수 있게 하는것이다. 명령어는 아래와 같다.

docker push [OPTIONS] NAME[:TAG]

처음부터 해보자. 일단 원래 pytorch 최신 버전을 내 tag했다.

docker image tag pytorch/pytorch:latest seosh7039/test_push:0.1

docker_push1 docker_push2 Fig. tag했더니 같은 내용을 담고있는 image가 내 이름으로 생겼다.

그리고 run하자.

docker run -it --name test_push --gpus all seosh7039/test_push:0.1

그리고 pip list를 확인해보면,

pip list

docker_push3

별게 없는걸 알 수 있는데, 여기에 tensorboard를 임의로 설치하자.

pip install tensorboard

docker_push4

그리고 나가면 자동으로 컨테이너가 stop 되는데 (stop상태여야 push 가능) 이제 push를 할거다.

git 명령어랑 비슷하게 생각하면 되는데

내가 새로 만든 repo가 되는곳에 commit을 0.2 버전 (tag) 으로 하고, push 하는 것이다.

docker commit test_push seosh7039/test_push:0.2

docker_push5

docker push seosh7039/test_push:0.2

docker_push6

(생각해보니까 tag하고나서 0.1버전은 push를 안해서 내 repo에는 없고 local에 이미지만 카피됐다, 위에처럼 하면 내 hub.docker에는 0.2버전만 달랑 있을 뿐… 뭐 상관없다)

docker_push7

내가 한 process는 다음과 같다.

  • 1.facebook pytorch의 최신 docker image를 pull
  • 2.tag해서 내꺼로 가져옴
  • 3.run한다음에 tensorboard를 설치함.
  • 4.tensorboard가 포함된 pytorch 이미지가 된 걸 푸시함

그럼 분명히 2번에서 단순 tag한 이미지와 4번의 이미지는 달라야한다.

docker_push8

이전꺼는 텐서보드가 없다고 뜬다.

그렇다면 내가 설치하고 푸시한걸 땡겨보면 어떨까? fair하게 하기 위해서 현재 로컬에 깔린 푸시했던 이미지는 삭제하고 다시 pull해서 확인해본다.

docker_push9 docker_push10 docker_push11

잘 올라갔음을 알 수 있다.

8. build image with Dockerfile

마지막으로 알아볼 것은 Dockerfile을 사용해서 새로 이미지를 만드는 것이다.

docker build [OPTIONS] PATH | URL | -

내가 배포하고싶은 도커 이미지를 Dockerfile로부터 빌드할 수 있는데,

dockerfile Fig.

예를 들어, 아래와 같이 파일을 작성하고 docker build 커맨드를 사용하면 된다.

# 1. ubuntu 설치 (패키지 업데이트 + 만든사람 표시)
FROM       ubuntu:16.04
MAINTAINER subicura@subicura.com
RUN        apt-get -y update

# 2. ruby 설치
RUN apt-get -y install ruby
RUN gem install bundler

# 3. 소스 복사
COPY . /usr/src/app

# 4. Gem 패키지 설치 (실행 디렉토리 설정)
WORKDIR /usr/src/app
RUN     bundle install

# 5. Sinatra 서버 실행 (Listen 포트 정의)
EXPOSE 4567
CMD    bundle exec ruby app.rb -o 0.0.0.0

위의 과정은

1.OS 설치 (혹은 OS 포함해서 기본 라이브러리가 깔려있는 image부터 시작)
2.advanced pakage들 설치
3.python pakage들 설치
...

을 함축적으로 담고있다. (위의 예시는 아래 레퍼런스에 담아뒀습니다. 글이 중구난방이라 중간에 레퍼를 못달겠네요…)

Dockerfile을 작성할 때 커맨드는 아래와 같으니 참고하자.

  • FROM : 기본 이미지
    • 베이스 이미지 지정
    • FROM ubuntu:latest
    • FROM node:12
    • FROM python:3
  • RUN : 쉘 명령어 실행
    • RUN apt-get update
    • RUN npm install
  • CMD : 컨테이너 기반 실행 명령어 (Entrypoint의 인자로 사용)
    • CMD node app.js
  • EXPOSE : 오픈되는 포트 정보
    • 어떤 포트를 사용하는지에 대한 정보
  • ENV : 환경변수 설정
  • ADD : 파일 또는 디렉터리 추가, URL/ZIP 사용 가능
  • COPY : 파일 또는 디렉터리 추가
  • ENTRYPOINT : 컨테이너 기본 실행 명령어
  • VOLUME : 외부 마운트 포인터 생성
  • USER : RUN, CMD, ENTRYPOINT를 실행하는 사용자
  • WORKDIR, ARGS, LABEL, ONBUILD 등
    • WORKDIR : 작업 디렉터리 변경

(레퍼런스를 달 수 없지만 kim * ho 님의 git wiki를 참고했습니다.)

이렇게 하는 이유는 뭘까? 간편하게 이미지를 땡겨서 거기서 수정해서 다시 푸쉬해도되지만 아마도 이렇게하면 이미지가 처음부터 어떻게 설치됐는지를 스크립트로 확인할 수 있기 때문에 trouble shooting이 쉽고 이미지를 수정하기 쉬워서 인 것 같다.

이번엔 구글링을 통해 찾은 Dockerfile from loretoparisi 의 예시를 들어보도록 하겠다.

dockerfile_example2 Fig.

일부러 보기좋게 캡쳐해서 주석을 달았는데, 달다보니 이상한걸 느꼈다. 바로 2021년의 pytorch/fairseq library에 대한 Dockerfile이 아니라 2017년…의 Dockerfile이었다는 건데 (오우 쉣…), 삽질은 그냥 기록으로 냅두도록 하겠다.

그냥 간단한 Dockerfile을 쓰자. github.com/floydhub/dockerfiles에서 간단한 Dockerfile을 하나 찾아 똑같이 작성했다.

FROM floydhub/tensorflow:2.4-py3_aws.57
MAINTAINER Floyd Labs "support@floydhub.com"

RUN pip --no-cache-dir install --upgrade \
        http://download.pytorch.org/whl/cpu/torch-1.7.1%2Bcpu-cp37-cp37m-linux_x86_64.whl \
        # Torchvision is now built with CUDA https://github.com/pytorch/vision/issues/946 
        https://download.pytorch.org/whl/cpu/torchvision-0.8.2%2Bcpu-cp37-cp37m-linux_x86_64.whl \
        torchtext==0.8.1 \
        tensorboardX==2.1 \
        fastai \
        transformers \
	tokenizers \
    && rm -rf /tmp/* \
    && rm -rf /root/.cache

# Fix Jupyterlab - see https://github.com/jupyter/jupyter/issues/401
# TODO: move this on dl-base
RUN pip --no-cache-dir install --upgrade notebook \
    && rm -rf /pip_pkg \
    && rm -rf /tmp/* \
    && rm -rf /root/.cache

이제 이렇게 만들어진 달랑 Dockerfile 하나 있는 디렉토리에서 build 명령어를 쓰자.

docker build [OPTIONS] PATH | URL | -

#실제 사용한 커맨드
docker build -t seosh7039/test_build:0.1 .

dockerfile1 dockerfile2 Fig.

4스텝 밖에 없는 build 단계였다.

docker images

도커 이미지가 추가된걸 확인할 수 있다.

dockerfile3 Fig.

이제 이 이미지를 dockerhub에 올리기 위해서 push를 할 것이다. 먼저 로그인을 하자 (되어있겠지만).

dockerfile4 Fig.

이제 push를 하자.

docker push [OPTIONS] NAME[:TAG]

#실제 사용한 커맨드
docker push seosh7039/test_build:0.1

dockerfile5 dockerfile6 Fig.

잘 push가 됐으므로 dockerhub에 repo가 생겼는지 확인해보자.

dockerfile7 Fig.

마지막으로 이 image를 사용해서 run 해보자.

dockerfile8 Fig.

??? 노트북이 실행되는데

dockerfile9 Fig.

그냥 해당 Dockerfile의 디폴트가 쥬피터 노트북을 run하는건가 보다.(이건 생략;)


사실 Dockerfile을 만들고 빌드, 푸시하는 것은 수많은 에러가 나며 쉽지 않은 과정이기 때문에 인내심을 가지고 디버깅 해야 한다고 하니, 다들 화이팅이다 :)


Lifecycle of a Docker

마지막으로 Docker의 Lifecycle을 다시 생각해보며 글을 마무리한다.

  • 1.새로운 도커 이미지를 만든다 : docker build
    • 혹은 hub에서 가져온다 -> docker pull
  • 2.생성된 이미지를 실행한다 : docker run
    • 실행중인 컨테이너 상태 확인 : docker ps
  • 3.실행중인 도커를 중단한다 : docker stop
  • 4.컨테이너 실행 중 (중단된) 에 변경 사항을 저장한다.docker commit

+ Additional (자잘한 것들 계속 추가)

  • 211220

docker 에는 start, run 이외에 exec 라는 명령어도 있는데, 이미 실행된 컨테이너에 대해서 명령어를 수행할 때 사용할 수 있다.

가령 tmux 같은걸 사용하고 docker를 실행시켜서 관리하다가 창을 하나 더 분할해서 쓰고싶을 경우 (docker 내에서 tumx를 또 설치해도 되지만), 창을 분리하고

docker exec -it [해당 도커 컨테이너 이름] bash

같은 명령어를 사용해서 분할된 스크린도 똑같이 docker 내부로 또 접속할 수 있다. (bash를 하필 쓰는 이유는 container 를 start 할 때 처음 실행하는 default 명령어가 bash라고 해서 그렇다.)

Jupyter Notebook in Docker

Installation ufw (Uncomplicated Firewall)

우선 Linux os 에서 포트 방화벽을 해제하기 위해서는 ufw package를 체크해야 합니다.

sudo apt-get install ufw -y # Linux

sudo yum update &&\
sudo yum install epel-release -y &&\
sudo yum install --enablerepo="epel" ufw -y # CentOS

다음의 command들로 잘 설치됐는지 확인해보면 됩니다.

yum repolist yum list installed | grep -i epel yum list installed | grep -i ufw


이제 ufw 명령어를 사용하면되는데 자세한 명령어는 구글링을 해보면 쉽게 찾아볼 수 있습니다.
(check [How To Set Up a Firewall with UFW on Ubuntu 18.04](https://www.digitalocean.com/community/tutorials/how-to-set-up-a-firewall-with-ufw-on-ubuntu-18-04))



### <mark style='background-color: #dcffe4'> ufw setting </mark>

ufw를 `activation`해서 포트를 열건데 아래의 명령어들로 포트를 열고 상태를 확인할 수 있습니다.

sudo ufw enable sudo status


만약 `ufw`나 `sudo ufw` 가 먹지 않아 ufw : command not found 에러가 뜬다던가 하면 일단 다시 잘 설치됐나 확인해보고

yum list installed | grep -i ufw


```python
Repository libnvidia-container is listed more than once in the configuration
Repository nvidia-container-runtime is listed more than once in the configuration
ufw.noarch                             0.35-9.el7                      @epel

bash파일에 추가해주던가

vim ~/.bashrc &&

# .bashrc 파일에 아래 라인 추가
# /usr/sbin 같은 path는 다를 수 있음
export PATH=$PATH:/usr/sbin 

source ~/.bashrc

아니면 ufw가 설치되어있는 파일 경로를 써주고 명령어를 써주면 됩니다. (보통 안될리가 없는데 제가 연구실에서 물려받은 서버는 미리 깔려있던 epel, ufw의 경로가 조금 꼬여있었습니다.)

sudo /usr/sbin/ufw enable
sudo /usr/sbin/ufw status

어쨌든 enable해주고 상태를 현재 외부 접속이 allow된 포트가 리스트로 쭉 나오고 여기에 추가적으로 원하는 포트를 입력해주면 됩니다.

#예시1
sudo /usr/sbin/ufw allow 8888

#예시2
sudo /usr/sbin/ufw allow 192.168.1.200 to any port 80 proto tcp 

Jupyter Notebook Setting

먼저 ipython을 실행시켜서

ipython

파이썬 내에서 아래의 명령어로 노트북의 패스워드를 설정합니다.

from notebook.auth import passwd
passwd()

jupyter1 Fig.

이제 아래의 커맨드를 입력해 쥬피터의 config를 파이썬 경로에 생성하고,

jupyter notebook --generate-config

이 config를 수정하면 되는데 vim같은 editor 를 켜서 수정하시면 됩니다.

vim ~/.jupyter/jupyter_notebook_config.py

그러면 아래와 같이 주석처리된 수많은 옵션을 볼 수 있습니다. (디폴트값들임)

jupyter3 Fig.

여기서 이제 하나하나 바꿔주면 되는데 vim에서 /asd (asd 단어를 찾는 것) 를 통해서 다음의 옵션들을 찾아 i를 눌러 바꿔주면 됩니다.

c.NotebookApp.ip = '*' # 모든 ip에 대해 허용하겠다는 의미임. '0.0.0.0'도 가능
c.NotebookApp.allow_origin = '*' # 모든 laptop의 ip가 접근하는것을 허용하겠다는 것
c.NotebookApp.password = '???' # ???는 아까 획득한 비밀번호임
c.NotebookApp.password_required = True # 접속할때 비밀번호를 요구한다는 것
c.NotebookApp.open_browser = False 
c.NotebookApp.port = 8888 # ufw allow로 열어준 포트를 기입

더 많은 옵션들이 있으나 최소한으로 이렇게 했습니다.

jupyter6 Fig. 바꾼 옵션 예시

이제 notbook을 켜보면

jupyter notebook

아래와 같이 http://주소:포트 형태로 나오는 걸 알 수 있는데,

jupyter7 Fig.

이 링크를 들어가면 끝입니다.

jupyter9 Fig.

Some Troubleshooting

사실 저의 경우 server_name 이 포함된 url 로 접속을 하는게 갑자기 막혀서, 공유기를 초기화 해보기도 하고 포트포워딩을 해보기도 했지만 접속이 되지 않았습니다.

저의 경우 새로운 port 를 열어주고 (저의 경우 50005),

(base) [{server_name} ~]$ jupyter notebook
[W 2023-03-13 17:37:33.183 LabApp] 'allow_origin' has moved from NotebookApp to ServerApp. This config will be passed to ServerApp. Be sure to update your config before our next release.
[W 2023-03-13 17:37:33.183 LabApp] 'ip' has moved from NotebookApp to ServerApp. This config will be passed to ServerApp. Be sure to update your config before our next release.
[W 2023-03-13 17:37:33.184 LabApp] 'ip' has moved from NotebookApp to ServerApp. This config will be passed to ServerApp. Be sure to update your config before our next release.
[W 2023-03-13 17:37:33.184 LabApp] 'password' has moved from NotebookApp to ServerApp. This config will be passed to ServerApp. Be sure to update your config before our next release.
[W 2023-03-13 17:37:33.184 LabApp] 'password_required' has moved from NotebookApp to ServerApp. This config will be passed to ServerApp. Be sure to update your config before our next release.
[W 2023-03-13 17:37:33.184 LabApp] 'port' has moved from NotebookApp to ServerApp. This config will be passed to ServerApp. Be sure to update your config before our next release.
[W 2023-03-13 17:37:33.184 LabApp] 'port' has moved from NotebookApp to ServerApp. This config will be passed to ServerApp. Be sure to update your config before our next release.
[I 2023-03-13 17:37:33.192 LabApp] JupyterLab extension loaded from /???/anaconda3/lib/python3.8/site-packages/jupyterlab
[I 2023-03-13 17:37:33.192 LabApp] JupyterLab application directory is /???/anaconda3/share/jupyter/lab
[I 17:37:33.277 NotebookApp] [Jupytext Server Extension] Deriving a JupytextContentsManager from LargeFileManager
[I 17:37:33.280 NotebookApp] Serving notebooks from local directory: /???
[I 17:37:33.280 NotebookApp] Jupyter Notebook 6.3.0 is running at:
[I 17:37:33.280 NotebookApp] http://{server_name}:50005/
[I 17:37:33.280 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).

http://{server_name}:50005/ 를 사용해 접속하는것이 아닌 server의 ip, 즉 hostname 을 사용해 접속했습니다.

(base) [{server_name} ~]$ hostname -I
???.???.???.??? # server_ip

Jupyter Notebook in Docker

다음은 Docker 에서 Jupyter Notebook 을 실행하는 방법입니다. docker run 을 하실 적에 port 를 지정해주면 간단한데요,

docker run --gpus all -it --name {docker_name} \
-v {dir1}:{mnt1} \ # mount
-v {dir2}:{mnt2} \
-p {host_port}:{docker_port} \
--shm-size=8g --ulimit memlock=-1 --ulimit stack=67108864 \ # memories
--device=/dev/snd flml/flashlight:cuda-latest # fair's flashlight docker

Docker contatiner 에 들어가셔서 jupyter notebook 을 설치하고

pip install jupyter

실행하면 되는데, 저의 경우 root 권한이 필요했어서 아래의 커맨드를 사용했습니다.

jupyter notebook --allow-root

만약 Docker Contatiner 를 실행할 때 port 를 지정해주지 않았다면 아래처럼 port 정보가 안 뜰 수가 있는데요, 이런 경우 다시 실행을 해줘야 하거나 다른 조치를 취해야 합니다.

# define port
(base) [{server_name} ~]$ docker port tmp
50005/tcp -> 0.0.0.0:50005

# not
(base) [{server_name} ~]$ docker port tmp2
(base) [{server_name} ~]$ 

Docker 내에서도 conda 를 설치해 여러 환경을 또 만들어줄 경우 ipykernel을 사용해서 환경을 등록해주면 notebook 에서 자유롭게 쓸 수 있습니다.

pip install ipykernel
python -m ipykernel install --user --name py38 --display py38

Basic References </mark>