データエンジニア日記

データエンジニアの雑記

Docker版のJupyter-notebookとRStudioのdocker-composeの例

(今回はデータエンジニアというより、分析基盤エンジニア的なエントリーです)

自分の担当システムでは解析者用にRStudioとJupyterNotebookをDockerコンテナで提供している。 (原始的にEC2にDockerとdocker-composeをインストールして、その上に都度コンテナを構築している)*1

人ごと(Containerごと)にdocker runしていると、整理がつかなくなったり、管理が大変になったり、一斉起動、停止をしたい時に大変なので、docker-compose.ymlにサービスごとに記述してコンテナを建てている。 命名規則を合わせたり、共通の設定を書けたりするので、個々にdocker runするのに比べて設定漏れが少なくなる。

以下、jupyter/tensorflow-notebookのイメージを使用したコンテナの立ち上げdocker-compose.ymlの例

version: '2.1' #最新バージョンは3だが、リソース制限の指定の表記が対応していないので、2.1にしている。 
services:
  jn_1: #サービス名
    build: 
      context: ./jn_1/ docker-composeの下にdockerfileを置くディレクトリ「jn_1」を配置 
      dockerfile: dockerfile #dockerfile名を指定
    image: jn_common_1_image:1.0 #イメージを指定(既に同じイメージができていたらそこからコンテナが作られる)
    container_name: jn_1 #コンテナ名をつける。(ここではサービス名と合わせている)
    cpu_quota: 50000 #CPUの利用率制限(全体が100000とした場合の数を指定。例えば50000なら50%に制限される)
    mem_reservation: 10000m #メモリの利用バイト数制限(この場合は1コンテナが使える最大サイズを10Gバイトに制限)
    logging: #ここ以下で、dockerのこのコンテナのログのファイルの最大サイズを指定する。
     driver: "json-file"  #形式をjsonにしないと、最大サイズ制限がかけられないのでこうしている。 
     options:
       max-size: "10m" #dockerのログファイルは際限なく大きくなることがあるので、制限を設けるようにしておく。
       max-file: "3" #適当な数でrotateするようにしておく。
    ports:
      - "8002:8888" #割り当てるホスト側のポート:Jupyterの場合は8888固定
    volumes:
      - /home/jupyter:/home/jovyan/work #ここの利用者が作成するプログラムやデータはworkというディレクトリを作りそこマウント
#コンテナ内にプログラムなどを置くと、コンテナを消した時に一緒に消えてしまうので注意
    tty: true
    stdin_open: true #これと上の行は、コマンドラインから入る時に必要
    command: [start-notebook.sh, --NotebookApp.token=''] #特にパスワードを設定しないで、Jupyterを利用する場合はこう。
    user: root #下のGRANT_SUDOを利用する場合は必要
    environment:
      - GRANT_SUDO=yes #ユーザにコンテナ内でのOS設定を操作する権限を与えて良い場合はこのように設定
      - NB_UID=1013 #Linux上の場合は、ホストのユーザアカウントをここに指定しておく
      - NB_GID=1001 #Linux上の場合は、ホストのユーザアカウントをここに指定しておく

RStudioの場合のdocker-compose.ymlの例は以下 (rockerのrocker/tidyverseのイメージを用いた場合)

version: '2.1' #最新バージョンは3だが、リソース制限の指定の表記が対応していないので、2.1にしている。 
services:
  rs_1:
    build: 
      context: ./rs_common_1/
      dockerfile: dockerfile
    image: rs_common_1_image:1.0
    container_name: rs_1  
    cpu_quota: 50000
    mem_reservation: 10000m
    logging:
     driver: "json-file"
     options:
       max-size: "10m"
       max-file: "3"
    ports:
      - "8051:8787" #割り当てるホスト側のポート:RStudioのrockerパッケージの場合は8787固定
    volumes:
      - /home/rstudio:/home/rstudio/work #個人ディレクトリをマウント
    tty: true
    stdin_open: true
    environment:
      - ROOT=TRUE #管理者権限を持たせる場合(コンテナ内のOSを弄らせる場合はTRUEにしておく)
      - USERID=1013
      - GROUPID=1001

こちらはcommand指定は不要。何も指定しなくても、RStudioが立ち上がっている。

留意点配下に箇条書き、

  • Mac版のDockerでは権限はよしなに変換されるが、Linux版だと指定をしないとバンバンrootとかホスト上に無いUIDでファイルが作られる事があるので注意。利用者のホスト上のアカウントと同じUIDを指定しておくのがベスト。
  • MemoryやCPUを制限するところは、docker-composer.ymlのバージョン3ではSwarm版のみに対応となっているので、無効になってしまう(未検証?)
  • コンテナ内はステートレスに保つため、マウントしたボリューム内でのみ、プログラムやデータファイルを置くようにする。さもないとコンテナを削除した際に同時に消えてしまう。*2
  • docker logsで見れるログファイルに制限をかけないと、際限無く大きくなることがあるので、この辺の制限を入れるようにすること。

RStudioとJupyterNotebbokのdockerfileの例とdockerfileの注意点は次エントリーにて。

*1:将来的にはEKSとかEFSを組み合わせてモダンな作りに出来ないか?とか考え中・・・

*2:難しい言葉で言うと「データの永続化領域を設定する」という表現になる