Slide 1

Slide 1 text

dip Labor force solution company compose.yaml読解 + ライブデモ 2026/04/15 26新卒講義 day2

Slide 2

Slide 2 text

自己紹介 •酒井駿(24卒エンジニア) •横山瑛太郎(25卒エンジニア) 2

Slide 3

Slide 3 text

アジェンダ(超ざっくり) •前半:座学(+ちょこっとデモ)パート →〜12:00くらい •後半: docker compose触ってみようパート→ 〜12:45 or お腹が空くまで 3

Slide 4

Slide 4 text

dip Labor force solution company 前半:座学パート 4

Slide 5

Slide 5 text

今日のゴール この研修後、 1. 任意プロジェクトの を読んで、何がどう動いているかを理解できる compose.yaml 2. docker compose コマンドを使いこなして、自力で開発を始められる コンテナが動かないとき、自分で原因を調べて対処できる 3. という状態を目指します! 5

Slide 6

Slide 6 text

前提知識の確認 この研修は、以下の内容を理解している前提で進めます。 •Docker の基礎: イメージ、コンテナ、Dockerfileの役割 ・基本コマンド: docker run, docker ps, docker stop Docker 単体の復習 Dockerfile (設計図) -(build) イメージ -(run) コンテナ (テンプレート) (実体) Dockerfile - 「どんな環境を作るか」のレシピ イメージ- Dockerfileからビルドされた不変のテンプレート ・コンテナーイメージから起動した実行中のプロセス 今回のDocker Composeは、この 「複数のコンテナ」を束ねて管理する仕組みです。 6

Slide 7

Slide 7 text

dip Labor force solution company 2. Docker Composeとは何か 7

Slide 8

Slide 8 text

Docker Compose とは 複数のDockerコンテナで構成されるアプリケーションを、 定義・実行・一括管理するためのオーケストレーションツールです。 8

Slide 9

Slide 9 text

現実のアプリケーションは複数のコンテナで動いている 今回の題材↓(7つのコンテナが協調して1つのシステムを構成) app (Python Webサーバ) :8000 db-replica (読取専用。 レプリカ)。 :5432 db (Postgres 15.4) :5432 db-testing (テスト用 DB) db-testing-replica (テスト用レプリカ) :5432 :5432 es (Elasticsearch 8.14.1) :9200 kibana (ESの可視化 ダッシュボード) :5601 これを手動で1つずつ管理するのはnot現実的 9

Slide 10

Slide 10 text

Docker Composeを使わない場合... 이 コマンドが長すぎて、打ち間違える 起動順序を人間が管理しなければならない(sleep で雑に待つしかない) ネットワークも自分で作らないといけない ・停止するときは docker stop を7回打つ必要がある(とにかく面倒) ・チームメンバーに共有するのが困難(「このコマンドをこの順番で打ってね」) 10

Slide 11

Slide 11 text

dip Labor force solution company 3. なぜDocker Composeが必要なのか 11

Slide 12

Slide 12 text

メリット1: コマンド1発で環境が完成する # たった1行で、7つのコンテナが全部起動する docker compose up -d 이 長い docker run コマンドを何度も叩く必要がない •起動順序(DBが先、レプリカが後)も depends_on + healthcheck 人間が sleep 10 で待つような不安定な運用がなくなる で自動制御 12

Slide 13

Slide 13 text

メリット2: チーム全員で「全く同じ環境」を作れる 設定ファイル(compose.yaml) をGitで管理する = インフラの設定がコードとして残る 開発者A のPC 開発者B のPC git clone git clone compose.yaml Dockerfile init.sql 同一 ↓ docker compose up -d 全く同じ環境 compose.yaml Dockerfile init.sql docker compose up -d 全く同じ環境 13

Slide 14

Slide 14 text

メリット3: コンテナ同士の通信が簡単 Docker Composeは docker compose up 時に自動的に専用のネットワーク(デフ ォルトネットワーク)を作成する 同じcompose.yaml 内のサービスは、このネットワークを通じてサービス名をホス ト名としてお互いに通信できる 14

Slide 15

Slide 15 text

具体例: サービス間の接続 # アプリ(app サービス)からDBに接続する場合 # IPアドレスではなく、サービス名 "db" で接続できる DATABASE_URL = "postgresql://myapp_user:password@db:5432/myapp" # # compose.yaml のサービス名 Docker Compose デフォルトネットワーク app -"db" db es 'es" "db" で接続可能 kibana —"myаpp-es"- (container_nameも使える) 15

Slide 16

Slide 16 text

Docker Composeを使わない場合... コンテナ間の通信は以下のように面倒になる: # Docker Composeなし: IPアドレスを調べて指定する必要がある docker inspect myapp-db | grep IPAddress #→"172.17.0.3" #→ このIPはコンテナを再起動すると変わる可能性がある! DATABASE_URL = "postgresql://[email protected]:5432/myapp" #不安定 Docker Composeならサービス名が自動的にDNSによって名前解決されるため、 IPアドレスを一切意識する必要なし 16

Slide 17

Slide 17 text

メリット4: 環境のライフサイクルを簡単に管理できる # 環境を丸ごと起動 docker compose up -d # 環境を丸ごと停止・削除 docker compose down # データも含めて完全リセット(DBのデータ等も消える) docker compose down -v # 設定を変更した後、変更があるサービスだけ再作成 docker compose up -d 「開発環境をまっさらにしてやり直したい」がdown −v →up -d の2コマンドで完了 17

Slide 18

Slide 18 text

dip Labor force solution company docker composeの基礎は以上です! 18

Slide 19

Slide 19 text

dip Labor force solution company 4. compose.yamlの読み方 19

Slide 20

Slide 20 text

題材となるcompose.yaml ここからは、 実例ベースのcompose.yaml を題材に深掘っていきます! (実装例は次のスライド以降に順次掲載していきます) 20

Slide 21

Slide 21 text

compose.yamlの全体構造 services: #←「どんなコンテナを動かすか」を定義するセクション app: db: es: volumes: #←「データをどこに永続化するか」を定義するセクション postgres_data: この2つのトップレベルキー が基本 他に networks などもあるが、多くの場合はデフォルトで十分なので省略される 21

Slide 22

Slide 22 text

4-1. services ーコンテナの定義 services の下に、動かしたいコンテナをサービスとして定義する services: app: #← サービス名(自由に決められる) db: #← サービス名 es: #← サービス名 サービス名はコンテナ間通信でホスト名として使われる 22

Slide 23

Slide 23 text

4-2. app サービスについて詳細説明 app: container_name: myapp-backend build: context: dockerfile: ./docker/Dockerfile args: - LOCAL_CERTS=${LOCAL_CERTS:-0} volumes: - .:/app dummy_volume:/app/.venv - app_cache:/root/.cache ports: 8080:8000 - 8888:8888 environment: - WATCHFILES_FORCE_POLLING=true # (1) コンテナ名 # (2) ビルド設定 - PYRIGHT_PYTHON_FORCE_VERSION=1.1.393 - PYRIGHT_PYTHON_IGNORE_WARNINGS=1 #(3) ファイル共有・永続化 #(4) ポート公開 #(5) 環境変数 - SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt - REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt extra_hosts: #(6) ホスト名追加 - host.docker.internal:host-gateway 23

Slide 24

Slide 24 text

container_name -ー コンテナに名前をつける container_name: myapp-backend docker psや docker logs で表示される名前になる ・指定しないと<プロジェクト名>−<サービス名>−1 のように自動生成される ・同じ名前のコンテナは同時に1つしか存在できない # container_name を指定した場合 $ docker ps CONTAINER ID NAMES abc123 myapp-backend #← わかりやすい # 指定しない場合 $ docker ps CONTAINER ID NAMES abc123 myproject-app-1 #← 自動生成 24

Slide 25

Slide 25 text

build - Dockerイメージをビルドする build: context: . dockerfile: ./docker/Dockerfile args: - LOCAL_CERTS=${L0CAL_CERTS:-0} # ビルドコンテキスト # 使用するDockerfile # ビルド時の引数(Dockerfile内のARGに渡る) ビルドコンテキスト = Dockerがビルド時に参照できるファイルの範囲 context: ・は「現在のディレクトリ以下のファイルをすべてDockerに渡す」とい う意味 プロジェクトルート(context: — compose.yaml .) docker/ Dockerfile dockerfile: で指定 src/ main.py Dockerfile内の COPY でコピー可能 requirements.txt Dockerfile内の COPY でコピー可能 25

Slide 26

Slide 26 text

build - Dockerイメージをビルドする buildと image の使い分け 設定 意味 build: Dockerfileからイメージをビルド image: postgres:15.4 Docker Hubの既存イメージをそのまま使う build.argsと environment の違い 設定 いつ使われるか build.args ビルド時のみ (docker compose build 時 environment コンテナ実行時 用途 Dockerfileの条件分岐、バージョン指定 アプリの設定値、接続情報 # build.args の例:ビルド時に証明書を入れるかどうかを切り替える args: - LOCAL_CERTS=${LOCAL_CERTS:-0} # 「環境変数 LOCAL_CERTSが設定されていればその値、なければ 0」を意味する # ↑${LOCAL_CERTS:−0} はシェルの構文で、 26

Slide 27

Slide 27 text

volumes - ファイルの共有・永続化 volumes: - .:/app # (a) バインドマウント - dummy_volume:/app/.venv #(b) 名前付きボリューム app_cache:/root/.cache #(b) 名前付きボリューム 重要ポイントなので、2種類のマウントを詳しく解説 27

Slide 28

Slide 28 text

バインドマウント 自分のPC上の特定のフォルダを、コンテナの中に直接つなぎ合わせる方法 .:/app # ホストの「「.」(カレントディレクトリ)を、コンテナの「/ app」にマウント ホストPC コンテナ / 同期 /app/ - src/ src/ main.py main.py tests/ L compose.yaml tests/ compose.yaml ホストでファイルを編集→コンテナにリアルタイム反映 コンテナ内で生成したファイル→ホストにも見える 主な用途:「開発環境」 →プログラムを書き換えながら実行結果を確認したい時に使います 28

Slide 29

Slide 29 text

名前付きボリューム Dockerが管理する専用のデータ領域を作り、そこに名前をつけてコンテナにつなぐ方法 dummy_volume:/app/.venv Docker dummy_volume (Dockerが管理) コンテナを消しても データは残る コンテナ /app/.venv (Python仮想環境) 主な用途:「データベースの保存先」 →中身を直接手でいじることがなく、データが消えてほしくないものに使います 29

Slide 30

Slide 30 text

.venv を名前付きボリュームにしている理由 バインドマウント(.:/app) でホストのディレクトリ全体をマウントしているため、 そのまま.venv (Pythonのパッケージがインストールされるディレクトリ)を使おうと すると問題が起きる: 이 ホストとコンテナでOSが違う(macOS vs Linux)ため、コンパイル済みパッケー ジが互換性を持たない ・バインドマウントで上書きされるのを防ぐ 名前付きボリュームで上書きすると、.venv だけはDocker管理の領域に保存され、ホス トとコンテナが干渉しなくなる 30

Slide 31

Slide 31 text

(まとめ)バインドマウント vs 名前付きボリューム 書き方 データの場所 ホストから見え るか コンテナ削除時 主な用途 バインドマウント ./host/path:/container/path ホストPCのファイルシステム 見える ホストにファイルが残る ソースコード同期、設定ファイル注 入 名前付きボリューム volume_name:/container/path Docker管理の領域 見えない(docker volume inspect で場所は確認 可能) ボリュームは残る(−v で削除可能) DB データ、パッケージキャッシュ 31

Slide 32

Slide 32 text

ports - ポートの公開 ports: 8080:8000 # ホストのポート:コンテナのポート - 8888:8888 ポートマッピングの仕組みを図解↓ あなたのブラウザ ホストPC コンテナ(app) http://localhost:8080 ポート 8080 ポート 8000 アプリが待ち受け http://localhost:8888 ポート 8888 ポート 8888 Jupyter等 なぜ8080:8000 のようにポートを変えるのか? ・コンテナ内のアプリはポート8000で動いている(Dockerfile等で決まっている) ・でもホスト側ではポート8000が他のプロセスで使われているかもしれない ・そこでホスト側だけ8080に変更して衝突を避ける 32

Slide 33

Slide 33 text

environment - 環境変数 environment: WATCHFILES_FORCE_POLLING=truе PYRIGHT_PYTHON_FORCE_VERSION=1.1.393 - PYRIGHT_PYTHON_IGNORE_WARNINGS=1 - SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt コンテナ内で使える環境変数を設定します。 環境変数 WATCHFILES_FORCE_POLLING PYRIGHT_PYTHON_FORCE_VERSION SSL_CERT_FILE / REQUESTS_CA_BUNDLE 役割 ファイル変更の検知方式を強制(Docker環境でホットリロードを 動かすため) 型チェックツールのバージョンを固定 SSL証明書の場所を指定(組織内のプロキシ対応等) 33

Slide 34

Slide 34 text

environment - 書き方と注意点 書き方は2通りある: # リスト形式(この compose.yaml で使われている形式) environment: KEY=value KEY2=value2 # マップ形式(こちらもよく見る) environment: KEY: value KEY2: value2 ※どちらも同じ意味 34

Slide 35

Slide 35 text

environment - 機密情報の扱い ・パスワードやAPIキーは compose.yaml に直接書くとGitに残ってしまう ・代わりに.env ファイルやenv_file ディレクティブを使い分ける # 良くない例(パスワードがGitに残る) environment: - API_KEY=sk-1234567890abcdef # 良い例(.envファイルから読み込む) env_file: - .env #← •gitignore に追加しておく 35

Slide 36

Slide 36 text

extra_hosts - ホスト名の追加 - extra_hosts: - host.docker.internal:host-gateway コンテナの/etc/hosts ファイルにエントリを追加する # コンテナ内の/etc/hosts に以下が追加される 192.168.65.2 host.docker.internal いつ使うのか? ・コンテナからホストPC上で動いているサービス(例えば、ローカルで動いている別 のAPIサーバー)にアクセスしたい場合に使う • host.docker. internal というホスト名でホストPCのIPアドレスが解決できるよう になる 36

Slide 37

Slide 37 text

4-3. db サービスを詳しく読む- ミドルウェアの定義 db: image: postgres:15.4 container_name: myapp-db command: -c "hba_file=/etc/postgresql/pg_hba.conf" ports: - 5432:5432 volumes: postgres_data:/var/lib/postgresql/data - ./docker/init_primary.sql:/docker-entrypoint-initdb.d/init_primary.sql -./docker/pg_hba.conf:/etc/postgresql/pg_hba.conf environment: - POSTGRES_USER=myapp_user - POSTGRES_PASSWORD=password - POSTGRES_DB=myapp healthcheck: test: pg_isready -U myapp_user -d myapp interval: 1s retries: 60 37

Slide 38

Slide 38 text

image - 既存のイメージを使う image: postgres:15.4 Docker Hubで公開されている公式イメージをそのまま使用する イメージ名:タグ(バージョン) の形式で指定 postgres:15.4 タグ(バージョンを指定) イメージ名 タグを省略すると latest (最新版)になるが、明示的に指定するのがベストプラクティス 38

Slide 39

Slide 39 text

command - 起動コマンドの上書き command: -c "hba_file=/etc/postgresql/pg_hba.conf" Dockerイメージには、デフォルトで実行されるコマンドが設定されている command を指定すると、それを上書きできる # PostgreSQLイメージのデフォルトコマンド postgres # command で引数を追加 postgres -c "hba_file=/etc/postgresql/pg_hba.conf" この部分がcommand で指定した内容 ここでは、PostgreSQLの認証設定ファイル (pg_hba.conf) のパスを指定している 39

Slide 40

Slide 40 text

DBサービスの volumes - 実践的な使い方 - volumes: # (a) DBのデータを永続化 postgres_data:/var/lib/postgresql/data # (b) 初期化SQLをコンテナに渡す ./docker/init_primary.sql:/docker-entrypoint-initdb.d/init_primary.sql # (c) 設定ファイルをコンテナに渡す ./docker/pg_hba.conf:/etc/postgresql/pg_hba.conf ※volumes の説明としては先程と同様のため割愛 ※問題:どれが「バインドマウント」で、どれが「名前付きボリューム」? 40

Slide 41

Slide 41 text

environment - PostgreSQL固有の環境変数 environment: - POSTGRES_USER=myapp_user - POSTGRES_PASSWORD=password POSTGRES_DB=myapp # 作成するユーザー名 # パスワード # 作成するデータベース名 ※これもenvironment の説明としては先程と同様のため割愛 41

Slide 42

Slide 42 text

healthcheck - コンテナの健康状態を確認する healthcheck: test: pg_isready -U myapp_user -d myapp interval: 1s retries: 60 設定 意味 test 健康かどうかを判定するコマンド。終了コードOで「healthy」 interval チェックを実行する間隔(1秒ごと) retries 連続失敗の上限(60回失敗すると「unhealthy」) 42

Slide 43

Slide 43 text

healthcheck - コンテナの状態遷移 コンテナの状態遷移: starting→ healthy(test が成功) unhealthy (retries 回連続で失敗) docker compose psで状態が確認できる: NAME myapp-db STATUS running (healthy) t healthcheck が通っている 43

Slide 44

Slide 44 text

4-4. db-replica サービス- depends_on と起動順序 の制御 db-replica: image: postgres:15.4 container_name: myapp-db-replica entrypoint: /etc/postgresql/entrypoint.sh ports: - 5436:5432 volumes: postgres_data_replica:/var/lib/postgresql/data -./docker/replica-entrypoint.sh:/etc/postgresql/entrypoint.sh depends_on: db: condition: service_healthy ※こちらも先程と同様、entrypoint とdepends_on 以外の説明は割愛 44

Slide 45

Slide 45 text

entrypoint - コンテナ起動時の最初のコマンド entrypoint: /etc/postgresql/entrypoint.sh 役割: コンテナが立ち上がったときに最初に動く実行ファイルやスクリプトを指定 特徴:基本的に上書きされることを想定しない固定の命令として使われる 設定 役割 entrypoint コンテナのメインプロセスそのものを置き換える command entrypointに渡す引数を上書きする 45

Slide 46

Slide 46 text

depends_on - 「このサービスの後に起動して」 depends_on: db: condition: service_healthy db サービスが healthy 状態になるまで、db-replica の起動を待つという意味 起動の流れ: 1. db が起動開始 2. dbの healthcheck が実行される(1秒ごと) 3. pg_is ready が成功 → db が「healthy」になる 4. db-replica の起動が始まる 46

Slide 47

Slide 47 text

depends_on condition condition service_started 意味 サービスが起動したら(デフォルト) service_healthy service_completed_successfully レプリカDBが起動を待つのはなぜ? 이 healthcheckが通ったら サービスが正常終了したら(バッチ処理向け) レプリカはプライマリDBのデータをコピーして作られる プライマリが起動していない状態でレプリカを起動しても、コピー元がないのでエラ 一になる 47

Slide 48

Slide 48 text

4-5. db-testingと db-testing-replica について ※dbや db-replicaと構造同じのため割愛 48

Slide 49

Slide 49 text

4-6. es (Elasticsearch)と kibana について ※一部、説明していない部分がありますがほとんど既存知識のため割愛 49

Slide 50

Slide 50 text

4-7. volumes - ボリュームの宣言 volumes: postgres_data: postgres_data_replica: dummy_volume: app_cache: postgres_data_testing: postgres_data_testing_replica: es-data: サービス定義内で使用する名前付きボリュームは、必ずここで宣言する必要がある (宣言を忘れるとエラーになる) services: db: volumes: postgres_data:/var/lib/postgresql/data ←ここで使っている volumes: postgres_data: ↓対応 ここで宣言が必要 50

Slide 51

Slide 51 text

4-8. compose.yaml全体のまとめ図 compose.yaml services: app (Webサーバー) build: Dockerfileからビルド - volumes: ソースコードをバインドマウント ports: 8080-8000 L environment:開発用の設定 db (プライマリDB) image: postgres:15.4 volumes:データ永続化 + 初期化SQL - environment: DB接続情報 healthcheck: pg_isready db-replica(読取専用DB) - depends_on: db (healthy) - db の後に起動 L entrypoint: レプリカ用の起動スクリプト db-testing / db-testing-replica(テスト用) └-構造は db / db-replica と同じ es (Elasticsearch) build: 専用Dockerfileからビルド ulimits: メモリロック無制限 L healthcheck: curlで HTTP チェック kibana (ESの可視化UI) image: Elastic公式レジストリから取得 L environment: ESの接続先を指定 volumes: postgres_data postgres_data_replica dummy_volume app_cache t DBデータ レプリカDBデータ Python.venv ←ビルドキャッシュ - postgres_data_testing ←テスト用DBデータ ☐ postgres_data_testing_replica es-data Elasticsearchデータ 51

Slide 52

Slide 52 text

dip Labor force solution company 5. よく使うコマンド 52

Slide 53

Slide 53 text

起動する- docker compose up # フォアグラウンドで起動(ログがターミナルに流れる) docker compose up # バックグラウンドで起動(−d = detached) docker compose up -d # イメージを再ビルドしてから起動 docker compose ud -p --quild # 特定のサービスだけ起動 docker compose ud -p app 53

Slide 54

Slide 54 text

停止・削除する- docker compose down # コンテナを停止して削除する # ネットワークも削除される # ボリュームは残る(= DBのデータは残る) docker compose down # ボリュームも含めて完全に削除する #▲ DBのデータも全部消えるので注意! docker compose down -v docker compose down コンテナ ネットワーク ボリューム(残る) イメージ(残る) の削除範囲: docker compose down −v の削除範囲: ✓ ☑ コンテナ ネットワーク ボリューム(消える!) イメージ(残る) 54

Slide 55

Slide 55 text

状態を確認する- docker compose ps docker compose ps 出力例: NAME myapp-backend STATUS PORTS running 0.0.0.0:8080->8000/tcp, 0.0.0.0:8888->8888/tcp myapp-db running (healthy) 0.0.0.0:5432->5432/tcp myapp-db-replica running (healthy) 0.0.0.0:5436->5432/tcp myapp-db-testing running (healthy) 0.0.0.0:5433->5432/tcp myapp-db-testing-replica running (healthy) 0.0.0.0:5437->5432/tcp myapp-es running (healthy) 0.0.0.0:9200->9200/tcp 55

Slide 56

Slide 56 text

No content

Slide 57

Slide 57 text

No content

Slide 58

Slide 58 text

No content

Slide 59

Slide 59 text

No content

Slide 60

Slide 60 text

No content

Slide 61

Slide 61 text

No content

Slide 62

Slide 62 text

No content