血と汗となみだを流す

個人の思ったこと、やったことの吐き出し口です。

JAWS-UG コンテナ支部 入門編 #6 コンテナの始め方 後編①

後編①とは

資料のリンク


ハンズオンの概要

ハンズオン環境の起動

  • さらっとコマンドを実行すれば環境が起動するのだが、「どのようにして起動するのか?」というのが気になったので調べる!(コンテナ便利すぎる)
1. アクセスキーをそれぞれ変数に設定します
  • これはいつもdirenvで設定しているのでOK
    • direnvを知らないと人生の半分を損している
  • ローカルPCからawscliで、AWS上のS3やCloudFormationを使うためのアクセスキー/シークレットキーの設定
2. ハンズオン環境の設定置き場を作ります
$ docker volume create scan-images
  • 設定の置き場・・・?
  • コンテナは使い捨てなので、設定などを永続化しておくボリュームをdocker volumeコマンドで作るっぽい
3. ハンズオン環境を起動します
$ docker run --rm -it -e AWS_DEFAULT_REGION=ap-northeast-1 \
     -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e AWS_DEFAULT_PROFILE \
     -v /var/run/docker.sock:/var/run/docker.sock \
     -v scan-images:/root/config \
     -v $HOME/.aws:/root/.aws \
     -p 8080:8080 jawsug/container:scan-images-fixed
  • docker run:コンテナ起動
  • オプション関連は公式のリファレンスを見ると良さそう
  • --rm:コンテナの終了時に自動的にコンテナをクリーンアップし、ファイルシステムを削除する
    • デフォルトではコンテナを終了してもコンテナのファイルシステムの内容を保持し続ける
    • 短い期間だけフォアグラウンドで動かす場合に適したオプション
  • -it:コンテナのプロセスに対してttyを割り当てる(簡単に言うとdocker内にログインして操作できる)
    • -i:標準入力を開き続ける
    • -t疑似ttyを割り当てる
  • -e:環境変数の組み合わせ
    • AWSのリージョン情報/アクセスキー/シークレットキー/プロファイル情報を、ローカルPCの環境変数から取得してDockerの環境変数としてセット
  • -v:共有ファイルシステム(VOLUME)
    • ホスト側のディレクトリ:コンテナ側のディレクトリでマウントを作成
    • /var/run/docker.sockをコンテナ内で操作できるようにする・・・?
    • scan-images:/root/config:コンテナ内の/root/configを共有VOLUMEに永続化しておく
    • $HOME/.aws:/root/.aws:ホストマシンのAWSクレデンシャル情報をコンテナ内に設定
      • コンテナ内からCloudFormationなどを操作するため
  • -p:ホストマシンとコンテナのポートのマッピング
    • コンテナが8080ポートで受けているのでホスト側の8080とマッピング
  • jawsug/container:scan-images-fixed

ついでにDockerfileを見てみる

FROM docker:18.06.0-ce-dind
  • FROM:コンテナのベースとなるイメージ
  • Dockerインストール済みのコンテナ
  • コンテナからコンテナを操作する
  • dindは「Docker in Docker」の略
ENV AWSCLI_VERSION=1.15.66 \
    JUPYTER_VERSION=1.0.0
  • AWS CLIとJUPYTERのバージョンの指定
RUN apk --no-cache add python3 git
  • Python3とGitのインストール
  • --no-cacheで不要なファイルを削除できる(イメージを小さくするため)

AWS CLIをインストールするレイヤ

# Install AWS CLI
RUN apk --no-cache add groff less jq \
 && apk --no-cache add --virtual build-deps py3-pip \
  • &&ワンライナーにしているのはイメージのレイヤーを少なくして、イメージの容量を減らすため
    • 複数行でコマンドを実行するとそれごとにレイヤーができる(=イメージの容量が増える)
  • AWSを操作するためのawscliのインストール
  • 前提として以下をインストール

    • groff
      • 文書整形を行う
    • less
      • テキストを1画面ずつ表示する
      • helpコマンドを打った時に必要になるらしい(後述の @pottava さんのtweet参照)
    • jq
      • JSONデータの整形
    • py3-pip
      • --virtual build-deps py3-pip
        • py3-pipbuild-depsという仮の名前でインストールしておく
        • あとでこの仮の名前で削除するため
      • py3-pipはPython3用のpip
  • groffやlessはAWS CLIが依存しているライブラリ

 && pip3 install "awscli == ${AWSCLI_VERSION}" \
 && pip3 install yq \
  • pip3コマンドでawscliをインストール
  • pip3コマンドでyqをインストール
    • yqYAMLが使えるjqのラッパー
 && find / -type d -name \__pycache__ -depth -exec rm -rf {} \; \
 && rm -rf /root/.cache \
  • rootユーザのキャッシュの削除
 && apk del --purge -r build-deps
  • build-depsという仮の名前でインストールしたpy3-pipを削除
  • awscliが入ればpip3自体はいらない

Jupyter Notebookをインストールするレイヤ

RUN apk --no-cache add bash tini \

(脱線)Dockerのinit processについて

  • ここを参考にさせて頂きました!
  • Dockerで特に考慮せずにプロセスを実行するとエントリーポイントとして設定したプロセスがPID:1で起動する
    • PID:1はdocker stopなどでSIGTERMシグナルを送ってもプロセスが停止しないで一定時間後にSIGKILLで強制終了する
    • コンテナの停止に余計な時間がかかったり、graceful shutdownがされないなどの問題がある
  • Dockerで使用できてシグナルを適切に処理するinit用プロセスがtini
    • Docker 1.13以降は--initオプションでdocker runすることでtiniが実行される
 && apk --no-cache add --virtual build-deps build-base python3-dev \
  • python3-devpython拡張ライブラリ
  • --virtualで仮の名前を付与しているけど、どこにも使ってない・・・?
 && pip3 install "jupyter == ${JUPYTER_VERSION}" \
  • pip3コマンドでjupyterのインストール
 && pip3 install backcall bash_kernel \
 && python3 -m bash_kernel.install \
 && find / -type d -name tests -depth -exec rm -rf {} \; \
 && find / -type d -name \__pycache__ -depth -exec rm -rf {} \; \
 && rm -rf /root/.cache
  • キャッシュの削除など
  • testsってディレクトリがどっかで作られてるのか・・・?
  • 他プロジェクトからの横展開で消し忘れとのことでした

Gitの設定をするレイヤ

RUN git config --global credential.helper '!aws codecommit credential-helper $@' \
 && git config --global credential.UseHttpPath true
  • CodeCommitでGitの認証をする際に使用するAWSのプロファイル情報を設定する

Jupyter Notebookの設定

WORKDIR /root/notebook
ADD notebooks_config/jupyter_notebook.py /root/.jupyter/jupyter_notebook_config.py
ADD notebooks /root/notebook
ADD application /root/notebook/application
ADD infrastructure /root/notebook/infrastructure
  • Jupyter Notebookで必要なファイルなどを配置
ADD notebooks_config/entrypoint.sh /
RUN chmod +x /entrypoint.sh
  • エントリポイントの設定
VOLUME /root/config
  • /root/configでマウントポイントを作る
ENTRYPOINT ["/entrypoint.sh"]
CMD ["tini", "--", "jupyter", "notebook"]
  • tiniでコンテナ起動

まとめ

  • コンテナを作る時にtiniを使ってゾンビプロセスの生成を防いでいる、という手法があるのを知れた
  • また、コンテナ関係ないがコールバック関数の上書きなども勉強になった
  • しかしgroffやbackcall、yqなどをどこで使うのかがまだわかっていない(Jupter Notebook関係)
  • コンテナを通じてインフラを勉強するの良さそう

次回

プライバシーポリシー