はじめに
『開発系エンジニアのためのDocker絵とき入門』を読んだので、覚えておきたいことやわかったことを書いておきたい。
⭐️これは書籍を読んで自分なりにまとめたメモです。正確な情報は公式ドキュメントや書籍を参照してください。
こんな人におすすめ(私)
- 会社の環境でDockerやコンテナを使っているが正直よくわかっていない
- そのため開発環境などのトラブルが起きると完全にお手上げ状態になってしまう
- 勉強しなきゃしなきゃと思いつつ後回しになってしまった
- "Docker" で検索して出てきた説明を軽く読んでみてもよくわからない
Docker(ドッカー)とは、アプリケーションとその実行に必要なライブラリや依存関係をコンテナという標準化されたユニットにまとめてパッケージ化し、開発からテスト、デプロイまでを加速するプラットフォームです。これにより、ホストOSを共有する軽量な仮想化環境を構築でき、異なる環境間でのアプリケーションの実行を容易にし、環境の違いによる問題を軽減します。
???
読んだらこうなった
- Dockerコマンドの構成が理解できたので、コマンドを見た時になんとなく理解できるようになった!
-
Dockerfileとcompose.ymlの違いがわかった!(元のレベルが低すぎる、、、) - イメージとコンテナの違いがわかった!(元のレベルが低すぎる、、、)
- 演習中でうまくコンテナが起動しなかったりしても、オプションをつけたり外したりして原因究明ができるようになった!
- コンテナの一覧を確認するとか、よく使うコマンドが自然に使えるようになった!
追記(早速仕事で役立った)
- DockerHubの障害でイメージをpullできず、ローカル環境が起動できなかったが、前に取得したイメージが残っているのでは?と考えられて起動できた!読む前なら絶対に無理だったので進歩を感じた。
- 会議でコンテナ関連の障害の話がわかった!
覚書
物理マシンと仮想マシン
- 仮想マシン
- ハードウェアの一部をソフトウェアで実現した物理マシンのように見えるもの
- 物理マシンのリソースを活用する
- 仮想化ソフトウェアに同じ設定を反映させれば同じ構成を起動できるので、別の物理マシンでも同じ構成で起動できる
- 用途ごとに環境を独立させられる
- 別の仮想マシンであれば言語のバージョンを違うものをインストールできる
- マシンの中に箱を置くイメージ。区切りがあるので、物理マシンの中のものを意図せずに使わない
- ホストOS: 物理マシンで直接動作しているOS
- ゲストOS: 仮想マシンで動作しているOS
- Dockerは「コンテナ型仮想化」。ホストOSにインストールしてコンテナという単位でアプリケーションを管理する
- ゲストOSは起動せず、OS機能はホストに借りる。(Linuxのコンテナを起動するにはホストマシンからLinuxカーネルを借りる必要がある。)仮想化ソフトウェアによりLinuxが起動しているように見える
- 1コンテナ1アプリケーション(例:pythonとphpとmysqlを使いたければ、それぞれコンテナを立てる)
- 注意:物理マシンのCPUアーキテクチャの違いがコンテナに影響する。仮想マシンのCPUは物理マシンと同じになるから。
Dockerの要素
- Docker: コンテナ仮想化ソフトウェアの一つ
- Docker Engine: デーモン(コンテナを管理する)・デーモンのAPI・CLIクライアントからなる
- Docker Compose: 複数のDockerコンテナを一括で操作するためのツール
-
docker compose upとか
-
- Docker Desktop: Dockerを扱うためのGUIアプリケーション。起動すると裏でLinux仮想マシンの起動もしてくれる。(感想:なるほど、だからこれを起動してないと使えないのか)
- Docker Hub: クラウド上のレジストリサービス。イメージ(コンテナの雛形)が公開されている。
- 使いたいベースイメージを検索して情報を得る
コンテナのコマンド(特によく使いそうなものを抜粋)
前提
docker container run だとconrainerをrun, docker image build だとimageをbuildという構造になっている。
(感想:重要!これがわかってだいぶコマンドを理解しやすくなった。)
バックスラッシュで改行できる。バックスラッシュの前にはスペースを入れること。
-
コンテナの起動:
docker container run [OPTION] IMAGE [COMMAND] [ARG...]- コマンドを指定せずに実行した場合は、イメージごとにあらかじめ決められたコマンドが実行される
- コマンドを指定すると、そのコマンドが実行される
- オプション
--nameをつけると、コンテナに名前をつけられる - オプション
--rmをつけると終了時にコンテナを自動で削除する - オプション
--interactive --ttyとつけるとコンテナと対話操作できる - オプション
--publishをつけると、コンテナのポートがホストマシンに公開される- ホストマシンのポート番号:コンテナのポート番号
- オプション
--envでコンテナの環境変数を設定。設定できる環境変数はイメージによる。 - オプション
--detach(-d)をつけるとバックグラウンドで起動する。ターミナルが占有されなくなる。- うまく起動できることを確認できてからつけたほうがいい
- detachやrmをつけて起動がうまくいかない場合、一度これらのオプションを外して原因を確認したほうがいい
- オプション
--mountでコンテナ内の任意のディレクトリをコンテナ外で保持する-
type=volume= ボリュームで保存 -
type=bind= ホストマシンで保存
-
- オプション
--networkでコンテナをネットワークに接続する(指定しないとデフォルトネットワークに接続されるが、他のコンテナと通信するときは自分で作ったものを指定することを推奨)
-
起動しているコンテナ一覧の確認:
docker container ls [OPTIONS]- オプションで
--allを指定すると起動していないコンテナも確認できる
- オプションで
-
コンテナの停止:
docker container stop [OPTIONS] CONTAINER_ID [CONTAINER...] -
コンテナ の削除:
docker container rm [OPTIONS] CONTAINER [CONTAINER...]- オプション
--forceをつけると、起動中のコンテナを強制削除- 停止と削除をいっぺんにやってくれるので便利
- オプション
-
コンテナのログ:docker container logs [OPTIONS] CONTAINER
- オプション --follow をつけると、ファイル末尾をリアルタイムに表示する(ログが更新され続ける)
イメージ
-
今後起動するすべてのコンテナに変更を反映したい場合は、コンテナではなくイメージを変更する必要がある。
-
完全イメージ名
-
[HOST[:PORT_NUMBER]/][NAMESPACE/]REPOSITORY[:TAG]- [HOST[:PORT_NUMBER]]は省略するとdocker hubから取得することになる
-
[:TAG]は省略すると:latestになるが、その時のlatestが使われるので毎回同じバージョンで起動できるとは限らない。バージョンを指定することを推奨。
-
-
コンテナレイヤ:コンテナとして起動する際に最上位に作られる書き込み可能レイヤ。ライブラリインストールや設定ファイル書き込みはここで行われる。他のレイヤは読み取り専用。コンテナ起動ごとに作られる。
-
メタデータ:環境変数やデフォルトコマンドなどが保存されている。イメージ全体のプロパティ。
イメージのコマンド(特によく使いそうなものを抜粋)
- イメージ一覧:
docker image ls [OPTIONS] [REPOSITORY[:TAG]] - Dockerfileなどからイメージの作成:
docker image build [OPTIONS] PATH | URL | -- パスかURLを指定する
- オプション
--fileでDockerfileを指定する。コンテキストにDockerfileというファイル名でDockerfileがあれば省略可 - オプション--tagで作成したイメージにタグをつける。--tag my-ubuntu:22.04だとmy-ubuntuがリポジトリ名(イメージの名前)で:22.04がタグ
-
docker image build --tag my-mysql:log .だとドット=カレントディレクトリのdockerfileが使われる - buildはホストマシンではなく、Dockerデーモンで行われる
- イメージレジストリからのイメージ取得:
docker image pull [OPTIONS] NAME[:TAG|@DIGEST]-
container runの時にimage pullも一緒に行われている。(ホストマシンに存在しないイメージでrunしようとするとimage pullされる)
-
- イメージの詳細を確認する:
docker image inspect [OPTIONS] IMAGE [IMAGE...]- コマンドを指定せずに起動した時のデフォルトコマンドは
Config.Cmdに書いてある
- コマンドを指定せずに起動した時のデフォルトコマンドは
Dockerfile
- イメージにレイヤを追加する設定ファイル
- 公開されているイメージでは用途に合致しないなどの場合に独自イメージを作成できる
(感想:つまり、Dockerfileは独自イメージの設定を書くもの) - FROMで他のイメージを指定する。そのイメージをベースに独自イメージを作っていく
- ベースイメージはDockerHubから探す
-
latestタグは避ける。バージョンを決めるには、そのイメージの元のサイト(ubuntuならubuntu)で長期サポート版について調べる必要がある - RUNが実行されるのは
image buildのタイミング - まずはコンテナを起動した状態でbashでコマンドを実行して動くことを確認してから、Dockerfileに転記するといい
- ホストマシンのファイルをイメージへコピーしてレイヤを作成:`COPY [--chown=: [--chmod=...]
- 例:
COPY ./my.cnf /etc/my.cnf
- 例:
- コンテナ起動時のコマンドを指定する:
CMD ["executable","param1","param2"]
ボリューム
- Dockerエンジン上のストレージ
- コンテナの任意のディレクトリにマウントすることで、コンテナファイルをコンテナ外に保存する
- コンテナを削除しても残るので、別のコンテナからも同じファイルを読める
ボリュームのコマンド
- 作る:
docker volume create [OPTIONS] [VOLUME]- オプション --name でボリューム名指定
バインドマウント
- ホストマシンの任意のディレクトリをコンテナにマウントする。マウントしたディレクトリはホストマシン・コンテナの双方から参照・編集できる。
- ボリュームとの違いは、保存場所がボリュームかホストマシンか。自分で編集するようなファイルはバインドマウント、自分は編集しないファイルはボリュームが適している。ソースコードを編集してコンテナで動かしたい、という場合はバインドマウント。
- コンテナからファイルを削除すると、ホストマシンからも無くなる
ネットワーク
- コンテナが他のコンテナと通信するには、Dockerのネットワーク機能を利用する
- ネットワークドライバ:仮想ネットワークを制御するソフトウェア
- コンテナ起動時にネットワークを指定しなかった場合にコンテナが接続するデフォルトネットワークは、デフォルトブリッジネットワーク。
- 自分で作ったブリッジネットワーク:ユーザー定義ブリッジネットワーク
- コンテナ同士の通信にはユーザー定義ブリッジネットワークを使うことが推奨されている
- デフォルトネットワークだと、毎回ipアドレスを調べないといけない
ネットワークのコマンド
- ネットワークを作る:
docker network create [OPTIONS] NETWORK
Docker compose
- 複数コンテナの定義及び実行をするためのツール
composeのコマンド
-
docker compose up: コンテナの作成と起動 -
docker compose down: コンテナの停止と削除- コンテナは自動で削除される
- イメージも削除したいときのオプション:
--rmi all/local - ボリュームも削除したいときのオプション:
--v
-
docker compose ps: コンテナ一覧の確認- compose.ymlがあるディレクトリで実行する
container lsはホストマシンの全コンテナを表示。compose psはcompose.yamlで動いているもののみ表示
- yamlファイル名はcompose.ymlにすれば自動で認識される
- コンテナ一つずつがserviceとして扱われる
- 以後コマンドでサービス名を使える
- 例:
docker compose exec サービス名
- 例:
-
environment: 環境変数 -
ports: 公開するport(--publishで指定してたもの) -
volumes: ここで書いた名前のvolumeが作られる。ここで作ったvolumeをservices内のvolumes:のsourceで指定できる。services内のvolumesにはバインドマウントも指定できる。このとき、ホストマシンのフォルダ名はcompose.ymlから見た相対パスで書く必要がある -
image: イメージ名を指定- 自分で作ったDockerfileからイメージビルドもする場合
- build: ./docker/app
- buildから必要なときはcompose upのオプションで
--buildをつける
- 自分で作ったDockerfileからイメージビルドもする場合
- 変数の設定
-
.envファイルで変数を設定できる。機密情報や変更のある情報など-
.envファイルや.gitファイルは.dockerignoreファイルに記載してイメージビルド時にDockerデーモンに渡さないようにする。機密情報的観点、ビルド効率的観点から。
-
- compose.yml側では
${変数名}の形式で読み込める- 変数名が未定義の場合にエラーにするかデフォルト値を使うかなど設定できる
-
${変数名-デフォルト値}→未定義の場合デフォルト値、${変数名?エラーメッセージ}→未定義の場合エラーメッセージ
-
docker compose convert:値がちゃんと設定されているのかの確認
-
- compose.ymlに書かれたコンテナは全てコンテナ起動時に作成されるブリッジネットワークにつながる。ので、コンテナ同士で通信できる。
- compose.ymlは複数指定できる。後のファイルの値が優先される。基本のファイルと環境ごとの設定を変えたい部分だけ定義したファイルを作ると、環境ごとの切り替えがしやすい。
うまくいかない時
-
docker container inspect コンテナ名でマウント情報や、ネットワーク情報を確認しよう。"Mount", "Networks","Cmd" あたり -
container logsでコンテナのログを確認しよう。エラーメッセージが出力されてるかも。 -
container execでコンテナの中を確認しよう。COPYしたファイルが意図した場所にあるかや、コンテナのディレクトリ構成とか。
-確認ポイント例- 起動してる?
- 通信したいコンテナと同じネットワークに接続している?
- 接続しようとしている名前で接続できるか
- 接続しようとしているポートがあってるか。
感想
実はこの本は一昨年に購入し、少しだけ読んだのだが、その時より知っていることやわかることが増えていてほっとした。しかし、わかっていないことの方が格段に多く、整理して理解できた感覚がある。会社でコンテナ関係のトラブルに遭遇する度に"何もわからない..."と無力感を感じていたが、これからは自分で原因を探せるようになっているとよいと思う。
Dockerのことをよくわかっている著者の方が、よくわかっていない時のことを覚えていて(それか想像力を働かせているのか)、とにかくわかっていない人向けの説明が充実していて本当にありがたい本でした。
また、書籍内の演習をやりつつメモをとりつつ読んだのだが、読みおわってメモをNotebookLMに取り込んだら、クイズを作ってくれ、理解度の確認ができてよかった。これはこれからpdfになっていない本を読む時にやりたいな。
