42ソウルのサークル5課題の一つであるInceptionのためにこの本を読み始めた。
他にも「図解で理解する〜」という本も読みたかったが、電子図書館で誰かが貸出中だったのでこちらを選んだ。
IT業界でよく使われるキーワードを別途説明なく使用しているため、IT初心者にとっては難易度が高い本かもしれない。
例)高可用性、IaaS、プロビジョニング、メインフレームなど。一部は脚注が付いていたり後で説明されている。
第1章#
第1章はDockerに関連する内容を説明している。インフラ側でなぜDockerという技術が必要になったのか、DevOpsによってサービス開発により集中できるようになった背景を説明している。
また、Dockerの発展過程も説明されているため、LXCからlibcontainer OCを経てrunC OCIまで、Docker内部技術がどのように変わってきたかを簡単に知ることができる。
第2章#
私はM1 + Ventura 13.4.1環境で進めた。仮想マシンプログラムにはUTMを使用し、Linux OSはubuntu-22.04.1-live-server-arm64を使用した。
本の指示通りにやるとDockerが正しくインストールされない。arm64だからだと思う。 Ubuntuバージョンが20.04以上だからだと思う。
sudo apt-get -y install docker-ceの代わりにsudo snap install dockerを使用する。
そしてsnapでインストールしたためか、sudo systemctl restart docker, sudo systemctl status dockerを確認できなかった。
また、sudo usermod -aG docker $(whoami)も機能しなかった。
このまま諦めるべきかと思ったが、ググって解決できた。
詳しい説明はSnapでDockerをインストールする Ubuntu 20.04を参考にしてほしい。この過程を実行すれば自分の環境でDockerを使用できるようになる。
ところが手順に従っているうちに、SSHで仮想マシンOSにアクセスして一画面にiTerm(4):電子書籍(6)の比率で分けて見たくなった。
UTMへのSSH接続方法
sudo apt-get install net-toolsでifconfigをインストールifconfigコマンドを実行して出力されたIPアドレス(私の場合はenp0s1)を確認ssh {ユーザー名}@{IP} -p22で接続し、パスワードを入力して接続
第3章#
Dockerイメージ詳細情報照会のパートで、Docker命令の活用中に管理者権限に変更して/var/lib/dockerパスに入る部分がある。
snapでインストールしたため、私は/var/snap/docker/common/var-lib-dockerこのパスに入る必要があった。
Dockerログイン・ログアウトのパートでcat ~ /.docker/config.jsonを確認する部分も異なるため、私はcat ./snap/docker/2895/.docker/config.jsonこのパスで確認した。
Webからアクセスしてアクセストークンを発行する必要があるため、コピー&ペーストが楽なSSH接続で行うことを推奨する。
Dockerイメージをファイルで管理のパートで、使用していたコンピュータがM1でarm64環境だったため、mysql5.7をダウンロードできなかった。今の例題ではmysqlを実行しないので問題が起きるか心配しなくても大丈夫だ。docker pull arm64v8/mysqlかdocker pull mysqlのどちらかをダウンロードすればよい。
Dockerコンテナコマンドを学ぶ。build、image、login、push、pull、commit、run、create、exec、attach、export、import、container、inspect、ps、logs、top、stats、stop、pause、unpause、restart、kill、rmが主に使われるもののようだ。
コンテナを制御するためのcreate、startコマンドを順番に使うことと、runコマンドは似た効果が得られる。
上でmysql 5.7バージョンがインストールできないと言ったが、こうすれば取得できる。 実行できない...docker pull --platform linux/amd64 mysql:5.7 実習3-1のためには5.7にするのが簡単なようだ。
cAdvisorもM1ではサポートされていないようだ。
ボリュームの処理を行う際、Dockerコンテナの種類によって活用される特定パスにdocker cpでソースを渡す方法よりも、ホストパスにあるフォルダをボリュームに接続して作業する方が良い。
ボリューム指定は間違った名前やパスでもフォルダを作成してしまうため、タイプミスに注意が必要だ。例をそのまま従っていると著者の/home/hyleeパスがそのまま露出される部分があるが、自分のパスに変更しないと予期しない結果を招く可能性がある(実際にそのままやってみていないので失敗するかはわからない)。
私がDockerを難しいと感じる理由には、Dockerの構造、コマンド、コンテナのライフサイクル(ホストと接続されていないデータの揮発性)、ボリューム接続、実際にDockerをどう活用するかをよく知らないことで負担を感じていることがあると思う。
ボリュームをホストで作成する必要がある場合や、特定のフォルダを指定して使う方式もあり得る。まだDockerボリュームの実務でのベストプラクティスを知らないため、既に作成されたボリュームやフォルダを確認して作成するかどうかも確認すべきではないかと思う。
Dockerは隔離された環境を提供するため、リソースの割り当ても便利だ。特定のアプリケーションで求められる推奨事項までだけリソースを使用させるのが一般的なのか気になった。ほとんどのDockerはクラウドで動くだろうから、リソースを多く使わないようにして請求料金を減らしたいが、クラウドが提供するコンピュータリソースを設定するからわざわざしないのか、それともDockerでも容量を制限するオプションを併用するのか調べる必要がありそうだ。
第4章#
いよいよDockerfileを使用する。IaCについての概念も説明される。
DockerfileからDocker ImageをBuildした後、Docker ContainerをRunする。
よく使われるDockerfileコマンド#
FROM
- 作成しようとするイメージのベースイメージを指定する。イメージタグはDocker Hubでバージョン情報のように複数のタグが提供される。タグを入れないとlatestに指定される。Pythonイメージを使用する場合、Debian Busterキーワードがあるものが有利だ。
- 例)FROM ubuntu:20.04
MAINTAINER
- 一般的にイメージをビルドした作成者の名前とメールアドレスを記述する。
- 例)
MAINTAINER sungjun.hwang <someone@gmail.com>
LABEL
- イメージの作成リストとしてバージョン、タイトル、説明、ライセンス情報などを記述する。1つ以上の記述が可能。
- 例)LABEL purpose = 'Nginx for webserver' 複数のLABELを個別に指定可能。複数使用する場合は以下のように推奨される。
推奨事項
LABEL purpose = 'Nginx for webserver' \
version = '1.0' \
RUN
- 設定された基本イメージにパッケージアップデートや各種パッケージのインストール、コマンド実行などを記述する。1つ以上の記述が可能。
- RUN apt update
- 推奨事項:マルチステージビルドの使用を推奨、各イメージごとに個別のDockerfileでビルド。複数のインストールコマンドを連結するとイメージのレイヤー数が減少。autoremove、autoclean、rm -rf /var/lib/apt/lists/*を使用すると保存されているaptキャッシュが削除されるためイメージサイズが減少。
- 例)Shell方式(RUN apt update && apt install -y nginx)とExec方式(RUN ["/bin/bash", "-c", "apt update"])がある。
CMD
- 作成されたイメージをコンテナとして実行する際に実行されるコマンドで、ENTRYPOINTコマンドで指定されたコマンドにデフォルトで渡すパラメータを指定する際に使用する。複数のCMDを記述しても最後の1つだけ処理される。一般的にイメージのコンテナ実行時にアプリケーションデーモンを実行させる場合に有用。
- 例)Shell方式(CMD apachectl -D FOREGROUND)とExec方式(CMD ["/usr/sbin/apachectl", "-D", "FOREGROUND"])
ENTRYPOINT
- CMDと同様に作成されたイメージがコンテナとして実行される際に使用されるが、コンテナ実行時にコマンドと引数値を渡して実行する点が異なる。複数のCMDを使用する場合、ENTRYPOINTコマンドと一緒に使用する。ENTRYPOINTはコマンドを指定し、CMDはデフォルトコマンドを指定することで柔軟にイメージを実行できる。
# 例
ENTRYPOINT ["python"]
CMD ["runapp.py"]- ENTRYPOINTはDockerコンテナ実行時に常に実行すべきコマンドを指定。
- CMDはDockerコンテナ実行時にさまざまなコマンドを指定する場合に有用。
COPY
- ホスト環境のファイル、フォルダをイメージ内にコピーする場合に記述する。
- 単純なコピー操作のみサポートする。ビルド作業フォルダ外のファイルはCOPYできない。
- 例)
COPY <ホストOSファイルパス> <Dockerコンテナ内のパス>
ADD
- ホスト環境のファイル、フォルダをイメージ内にコピーするだけでなく、URLアドレスから直接ダウンロードしてイメージに入れることもでき、圧縮ファイルの場合は指定パスに解凍して追加する。
- ビルド作業フォルダ外のファイルはADDできず、フォルダ追加時には/で終わる必要がある。
- 例)
ADD <ホストOSファイルパス> <Dockerコンテナ内のパス>
ENV
- イメージ内に各種環境変数を設定する場合に記述する。アプリケーションの使用を容易にするために事前に構成すべき環境変数がある。
- 例)ENV JAVA_HOME /usr/lib/jvm/java-8-oracle
EXPOSE
- コンテナがホストネットワークを通じて入ってくるトラフィックをリッスンするポートとプロトコルを指定するために記述する。
- 例)EXPOSE 80 or EXPOSE 80/tcp
VOLUME
- ボリュームをイメージビルドに事前設定する場合に記述する。
- VOLUMEで指定されたコンテナのパスはボリュームのデフォルトパス/var/lib/dockerと自動的に接続される。
- 例)VOLUME /var/log or VOLUME ["/project"]
USER
- コンテナのデフォルトユーザーはrootだ。
- アプリケーションが権限なしでサービスを実行できる場合、USERを通じて別のユーザーに変更して使用する。
- 例)USER sunhwang
WORKDIR
- コンテナ上で作業するパスを切り替えるために記述する。
- WORKDIRを設定するとRUN、CMD、ENTRYPOINT、COPY、ADDコマンドはそのフォルダを基準に実行する。
- 指定パスがない場合は自動生成され、コンテナ実行後に接続すると指定パスに接続される。
- 例)WORKDIR /workspace
ARG
- docker buildの時点で変数値を渡すために
--build-arg=引数を定義して使用する。 - 秘密鍵、アカウントパスワードなどの機密情報使用時にイメージにそのまま残り、漏洩のリスクがあるため注意が必要。
- 例)
ARG db_name(Dockerfileに記述) docker build --build_arg db_name=jpub_db .で渡すことができる。CMD db_start.sh -h 127.0.0.1 -d ${db_name}で使用可能。
ONBUILD
- 最初のイメージビルドに含まれるが実行されず、そのイメージが他のイメージのベースイメージとして使用される場合に実行するコマンドを指定する際に記述する。
- ONEBUILDコマンドは親Dockerfileが子Dockerfileに渡す方式だ。
- 例)ONEBUILD ADD websource.tar.gz /urs/share/nginx/html/
STOPSIGNAL
- docker stopコマンドはコンテナにSIGTERMを送信して停止する。別のシグナルを送りたい場合に記述する。
- 例)STOPSIGNAL SIGKILL # シグナル番号または名前を入れればよい。
HEALTHCHECK
- コンテナのプロセス状態をチェックしたい場合に記述する。
- HEALTHCHECKは1つのコマンドのみ有効で、最後に宣言されたものだけ適用される。
- 例)HEALTHCHECK --interval=1m --timeout=3s --retries=5 CMD curl -f http://localhost || exit 1
SHELL
- Dockerfile内で使用するデフォルトシェルを指定する場合に記述する。デフォルト値は"/bin/sh"。
- 例)SHELL ["/bin/bash", "-c"]
本を読み終えて感じたこと#
序盤はDockerについての概念と説明が良く、大変勉強になった。後半は実習中心の説明だったが、Docker Swarmの前の最後の実習はAWSのバージョン違いで何かうまくいかなかった。途中途中で動かない部分は修正しながら進めたが、最後のクラスタデプロイで何らかの問題があり解決できなかった。
読み終えても依然としてDockerが難しい理由は、「それでDockerをどんな状況でどう使うのか」がずっと疑問だからだ。何もない空のDockerfileが与えられて何かをしろと言われた時、問題なくうまくできるだろうか?Dockerをうまく使うためには、この技術で自分が達成したいことが何かを明確に定義する必要があると思う。自分もDockerで何ができるかもわからず、何をすべきかも不明確な状態で良い技術を学んでもうまく使えないと思う。こうしたインフラ側の経験不足で思い切り活用できないのがもどかしい。
途中で読んでいる最中に42ソウルのスタートアップブートキャンプに参加した8月は、それに忙しく他のことに気を配れなかった。
それでも9月初めに終わってから再び本を読んだが、それまで読んでいた内容がまったく思い出せず、少し理解が難しかった部分もある。
それでもこの本を読むよりは、他の本や動画、公式ドキュメントで学習する方がより良い方法だと思う。
