---
title: 開運研修2026 Docker入門
tags:  #開運研修  
author: [サイボウズ開発本部](https://docswell.com/user/cybozu-tech)
site: [Docswell](https://www.docswell.com/)
thumbnail: https://bcdn.docswell.com/page/3EK94625ED.jpg?width=480
description: 2026年エンジニア新人研修の資料です。
published: August 13, 26
canonical: https://docswell.com/s/cybozu-tech/58NL9P-Training_2026_Introduction_to_Docker
---
# Page. 1

![Page Image](https://bcdn.docswell.com/page/3EK94625ED.jpg)

開運研修2026
Docker入門
Kubernetes基盤 石井 正將
1


# Page. 2

![Page Image](https://bcdn.docswell.com/page/L73WL64175.jpg)

研修後どうなってほしいか
▌この研修のゴール
1. コンテナの用途と仕組みを理解できる
2. コンテナランタイムやコンテナオーケストレーションの概要を知っている
3. ベストプラクティスの存在を知り、調べるための手がかりを持っている
➢今日の内容をすべて暗記する必要はありません。
「こういう仕組みがある」「推奨される方法がある」ということを、頭の片隅に置いておいてもらえ
れば十分です。
2


# Page. 3

![Page Image](https://bcdn.docswell.com/page/87DKNVQKJG.jpg)

目次
1. コンテナの目的
2. コンテナの仕組み
3. コンテナランタイム
4. コンテナオーケストレーション
5. Dockerfileの書き方
6. ベストプラクティス（Dockerfile編、アプリケーション編）
3


# Page. 4

![Page Image](https://bcdn.docswell.com/page/VJPK5VL3E8.jpg)

コンテナの目的
4


# Page. 5

![Page Image](https://bcdn.docswell.com/page/2EVVPZQNEQ.jpg)

コンテナとは何か
▌アプリケーションとその依存関係をまとめてパッケージ化し、隔離された環境で実行する仕組み
➢どこでも、誰でも同じ環境でアプリケーションを動かせるようになる
隔離された環境で
プログラムを動かす
コンテナイメージ
プログラム
依存関係
干渉できない
コンテナ
別のコンテナ
プロセス
プロセス
ライブラリ・ランタイム
依存関係
ファイルシステム
アプリケーションや依存関係（ライブラリ等）を
パッケージ化したもの
OS
5


# Page. 6

![Page Image](https://bcdn.docswell.com/page/57GLP4W5EL.jpg)

用語の整理
▌プログラムや依存関係をパッケージ化したものを「コンテナイメージ」と呼びます
▌コンテナイメージを実際に起動したものが「コンテナ」です
クラスとインスタンス（オブジェクト）、プログラムとプロセスのような関係。
6


# Page. 7

![Page Image](https://bcdn.docswell.com/page/4EQY2G3LJP.jpg)

コンテナが使われる場面
▌次のような目的で使われます
1. 開発環境の統一
➢ チーム全員が同じ環境で開発できます
2. テスト、CI/CD
➢ 毎回クリーンな環境でテストを実行できます
3. アプリケーションのデプロイ
➢ 開発環境と同じ環境を本番に展開できます
4. マイクロサービスの運用
➢ サービスごとに独立した環境を用意できます
7


# Page. 8

![Page Image](https://bcdn.docswell.com/page/KJ4WL51571.jpg)

コンテナがなかったら（1）
▌開発環境の構築に時間がかかるかも
ビルドができません……
手順書見た？
最新のビルド環境
新入社員
2バージョン前
ベテラン社員
8


# Page. 9

![Page Image](https://bcdn.docswell.com/page/LE1YLWG27G.jpg)

コンテナがなかったら（2）
▌他のプロセスとリソースが競合するかも
ファイルがおかしくなった…
新しいサービスをデプロイするぞ！
前から動いている
プロセス
新しい
プロセス
前から使ってるよ
ちょっと借りるね
とあるディレクトリ
9


# Page. 10

![Page Image](https://bcdn.docswell.com/page/GEWGV6K2J2.jpg)

コンテナがなかったら（3）
▌環境の差異で問題が発生するかも
テストOK
知らない環境だ…
本番環境だと
エラーが出る……
テストOKだね
本番いってみよう！
プロセス
プロセス
呼び出し
ライブラリ v3
ライブラリ v1
開発環境
本番環境
10


# Page. 11

![Page Image](https://bcdn.docswell.com/page/47ZL4YZ4J3.jpg)

コンテナがあれば
▌依存関係ごとデプロイできるため、環境の差異やリソースの競合といった問題を解消できます
▌隔離して実行できるため、他のプロセスからの影響を防ぐことができます
隔離された環境で
プログラムを動かす
コンテナイメージ
プログラム
依存関係
干渉できない
コンテナ
別のコンテナ
プロセス
プロセス
ライブラリ・ランタイム
依存関係
ファイルシステム
アプリケーションや依存関係（ライブラリ等）を
パッケージ化したもの
OS
11


# Page. 12

![Page Image](https://bcdn.docswell.com/page/YJ6W3DZGJV.jpg)

サイボウズでのコンテナ事情
▌ 社内では、開発の様々なフェーズでコンテナが活用されています
⚫ 開発
➢ Docker、Docker Compose、kind(Kubernetes IN Docker)等を使い
手元でアプリケーションを動かす
⚫ テスト
➢ GitHub Actionsのコンテナ上でテスト
⚫ 運用
➢ Kubernetesで本番サービスを運用
12


# Page. 13

![Page Image](https://bcdn.docswell.com/page/GJ5ML3WXJ4.jpg)

コンテナの仕組み
13


# Page. 14

![Page Image](https://bcdn.docswell.com/page/9E29LZQQ7R.jpg)

コンテナの仕組み
▌ コンテナは、次のLinuxの機能を組み合わせて実現されています
1. Namespace
2. Overlay FileSystem
3. cgroups
14


# Page. 15

![Page Image](https://bcdn.docswell.com/page/D7Y4QRWYEM.jpg)

Namespace（名前空間）
▌プロセスから見えるシステムリソースを制限する仕組みです
▌PID namespace、Network namespace など、さまざまな種類があります
ホストから見ると
コンテナ1の見える世界
コンテナ2の見える世界
PID Namespace
PID 1 … プロセス1
PID 2 … 子プロセス1
(他のプロセスは見えない)
PID Namespace
PID 1 … プロセス2
PID 2 … 子プロセス2
(他のプロセスは見えない)
Network Namespace
eth0: 192.168.100.1
port 80
(他のネットワーク設定は見えない)
Network Namespace
eth0: 192.168.200.1
port 80
(他のネットワーク設定は見えない)
Linux
PID 100 … プロセス1
PID 101 … 子プロセス1
PID 102 … プロセス2
PID 103 … 子プロセス2
PID Namespaceの中と外では、
見えるPIDが変わる
Network Namespaceによって、
コンテナごとに個別のネットワークの設定ができる
ポートの被りを気にしないでよい
15


# Page. 16

![Page Image](https://bcdn.docswell.com/page/VENYKD9RJ8.jpg)

Overlay FileSystem
▌複数のディレクトリを重ね合わせて、一か所に統合してマウントする仕組みです
▌コンテナイメージのレイヤー構造を実現するために使われています
書き込み可能
hoge/
読み取り専用(1)
piyo/
file1.txt
Overlay FSで結合
fuga/
file1.txt
file2.txt
読み取り専用(2)
fuga/
file2.txt
読み込み専用のディレクトリの内容が重ね合わせて見える
書き込んだファイルは、書き込み可能ディレクトリに出力される
16


# Page. 17

![Page Image](https://bcdn.docswell.com/page/Y79PVG2ZE3.jpg)

cgroups
▌プロセスが使用できるCPUやメモリなどのリソース量を制限する仕組みです
⚫ CPUを使いすぎた場合
➢ スロットリング（一時的にプロセスの実行が抑制される）
⚫ メモリを使いすぎた場合
➢ OOM Killerによって強制終了される
17


# Page. 18

![Page Image](https://bcdn.docswell.com/page/G78DPVMY7D.jpg)

中間まとめ
▌コンテナとは、隔離された環境でプロセスを動かす仕組みです
▌以下のようなLinux機能を組み合わせて実現されています
⚫ Namespace
➢ プロセスから見えるリソースを制限する
⚫ Overlay FileSystem
➢ コンテナイメージから専用のルートファイルシステムを用意する
⚫ cgroups
➢ リソースの過剰使用を防ぐ
※ ここで挙げた以外にも、多くのLinux機能が活用されています
18


# Page. 19

![Page Image](https://bcdn.docswell.com/page/L7LM1539JR.jpg)

コンテナと仮想マシン
▌コンテナと仮想マシンはよく比較されます
▌システム構成図では似たように描かれる
仮想マシン
仮想マシン
プロセス
プロセス
プロセス
プロセス
コンテナ
コンテナ
ファイルシステム
ファイルシステム
プロセス
プロセス
OS
OS
ファイルシステム
ファイルシステム
ハイパーバイザー
Linux
H/W
コンテナの場合
ここが違う
OS
H/W
仮想マシンの場合
19


# Page. 20

![Page Image](https://bcdn.docswell.com/page/4EMYW3DVEW.jpg)

コンテナと仮想マシンの比較
▌コンテナ
⚫ Linux上で直接プロセスを動かす
⚫ Linuxカーネルの機能で他のプロセスから隔離する
⚫ ホストとカーネルを共有するため、リソース効率が高く、起動が速い
▌仮想マシン
⚫ 仮想的なH/Wを用意し、ホストOSと異なるOS（ゲストOS）を動かす
⚫ H/Wの仮想化支援機能を使うため、隔離レベルが高い
⚫ ゲストOSの動作にメモリやディスクが必要で、起動も遅い
⚫ ホストOSと異なるOSを動かせる、H/Wのエミュレーションをする場合もある
20


# Page. 21

![Page Image](https://bcdn.docswell.com/page/PER9YQ4WJ9.jpg)

コンテナのメリット 仮想マシンと比べて
▌エコシステムが充実している
⚫ コンテナイメージを共有するための仕組み（コンテナレジストリ）が整備されている
⚫ コンテナを前提としたツールが豊富に揃っている
⚫ CI/CDとの親和性が高い
▌ マイクロサービスとの相性が良い
⚫ リソース効率が高く、小さなサービスを多数動かす構成に適している
21


# Page. 22

![Page Image](https://bcdn.docswell.com/page/P7XQG52VEX.jpg)

MacやWindowsでのコンテナ
▌ここまで説明した仕組みはLinuxの機能を利用したものです
これらの機能はmacOSやWindowsには存在しません
▌macOSやWindowsでは、内部で軽量なLinux仮想マシンを起動し、
その上でコンテナを動かしています
22


# Page. 23

![Page Image](https://bcdn.docswell.com/page/37K946M57D.jpg)

コンテナでサービスを運用する場合
▌本格的なサービスを運用するには、複数のコンテナやホストとの連携が必要になります
▌連携を効率よく管理するために、コンテナオーケストレーションツールが生まれました
23


# Page. 24

![Page Image](https://bcdn.docswell.com/page/LJ3WL6Y1J5.jpg)

コンテナの仕組み まとめ
▌コンテナとは、Linuxの機能を組み合わせて隔離環境で起動したプロセスのことです
▌リソース効率が高く、マイクロサービスとの相性に優れています
▌ツールやサービスなどのエコシステムが充実しています
▌macOSやWindowsでは、内部で軽量な仮想マシンを利用して実現しています
▌実運用では、多数のコンテナを連携させて使います
24


# Page. 25

![Page Image](https://bcdn.docswell.com/page/8JDKNV5KEG.jpg)

コンテナランタイム
25


# Page. 26

![Page Image](https://bcdn.docswell.com/page/VEPK5VG378.jpg)

コンテナランタイムとは
▌コンテナを起動、管理するためのソフトウェアです
⚫ 代表例: Docker、containerd、runc
コンテナランタイム
Docker
コンテナの操作
containerd
runc
コンテナ
起動
プロセス
ファイルシステム
※ Docker はコンテナランタイムと呼ばれることがありますが、実際にはそれ以上の多くの機能を備えており、厳密にはこの呼称は正確ではありません。
本資料では、わかりやすさを優先して「コンテナランタイム」と表現しています。
26


# Page. 27

![Page Image](https://bcdn.docswell.com/page/27VVPZ6N7Q.jpg)

コンテナランタイムの2つの層
コンテナランタイムは、役割によって2つの層に分かれています
1. 高レベルランタイム
⚫ コンテナイメージの管理や、低レベルランタイムの呼び出しを担当
⚫ 例: Docker、containerd
2. 低レベルのランタイム
⚫ コンテナのプロセス起動（Namespaceの設定など）を担当
⚫ 例: runc、gVisor、Kata Containers
⚫ OCI（Open Container Initiative）によって仕様が標準化されているため、
異なるランタイム間でも同じコンテナイメージを使用できます
27


# Page. 28

![Page Image](https://bcdn.docswell.com/page/5JGLP4N57L.jpg)

主流のコンテナランタイム
▌開発環境としてはDockerが普及しています
⚫ 情報が豊富で、学習コストが低い
⚫ Docker Desktopを使えば、macOSやWindowsでも手軽に利用できる
▌ただし、一定規模以上の組織ではDocker Desktopが有料となります
▌業務で必要になるまでは代替ツールを使う選択肢もあります
（別の講義で説明があります）
28


# Page. 29

![Page Image](https://bcdn.docswell.com/page/47QY2GQLEP.jpg)

Dockerの構成要素
▌Dockerは複数のコンポーネントで構成されています
1. Dockerクライアント（CLI）
⚫ ユーザが実行するコマンド
2. Dockerデーモン
⚫ CLIから命令を受け取り、コンテナイメージのビルドやコンテナの起動、管理を行う
3. containerd、runc
⚫ Dockerデーモンの指示を受けて、コンテナを実際に起動、管理する
4. コンテナイメージ
⚫ アプリケーションとその依存関係をまとめたパッケージ
5. コンテナレジストリ
⚫ コンテナイメージを保存、共有する外部サービス
6. Dockerfile
⚫ コンテナイメージのビルド手順を記述したテキストファイル
29


# Page. 30

![Page Image](https://bcdn.docswell.com/page/KE4WL5N5J1.jpg)

Dockerの構成（1）
▌コンテナを起動する場合
1. ユーザが、Docker CLIでコンテナを操作する
2. Docker CLIの命令を、Dockerデーモンが処理する
3. 内部的には、containerdがコンテナのライフサイクルを管理し、
runcが実際にコンテナのプロセスを起動する
Docker デーモン
コンテナの操作
Docker CLI
containerd
コンテナ
起動
プロセス
ファイルシステム
runc
ホスト
30


# Page. 31

![Page Image](https://bcdn.docswell.com/page/L71YLW52JG.jpg)

Dockerの構成（2）
▌コンテナイメージをビルドしたりする場合
1. Dockerfileからコンテナイメージをビルドする
コンテナレジストリ
2. 作成したイメージはコンテナレジストリにdocker pushで送り
別の環境からdocker pullで取得できます
イメージ
コンテナ
イメージ
docker
push
Dockerfile
&amp;
ソース等
docker
pull
docker
build
Docker デーモン
コンテナイメージ
コンテナイメージの操作
Docker CLI
ホスト
31


# Page. 32

![Page Image](https://bcdn.docswell.com/page/G7WGV652E2.jpg)

コンテナレジストリ
▌コンテナイメージの保存や管理、配布を行うサービスです
⚫ 代表例: Docker Hub、GitHub Container Registry（GHCR）
▌コンテナイメージを共有することで、誰でも、どこでも同じ環境を再現できます
32


# Page. 33

![Page Image](https://bcdn.docswell.com/page/4JZL4YN4E3.jpg)

コンテナイメージ
▌プログラムとその依存関係をまとめたパッケージです
▌複数のレイヤーが積み重なった構造になっています
➢ この「レイヤー構造」は、この後の説明でも重要なポイントになります
レイヤー(1)：Ubuntuの標準パッケージ
レイヤー(2)：依存関係とか
レイヤー(3)：プログラムの実行ファイル
コンテナイメージ
33


# Page. 34

![Page Image](https://bcdn.docswell.com/page/YE6W3D8GEV.jpg)

コンテナオーケストレーション
34


# Page. 35

![Page Image](https://bcdn.docswell.com/page/GE5ML39XE4.jpg)

コンテナオーケストレーションとは
▌コンテナオーケストレーションとは
⚫ 多数のコンテナの管理を自動化する仕組み
⚫ アプリケーションのデプロイやスケーリングをしてくれる
▌「オーケストレーション（orchestration）」とは、
複数の要素を組み合わせて調整・指揮することを意味します
➢本格的なサービスの運用では、多数のコンテナを組み合わせる必要があり、
コンテナオーケストレーションツールが不可欠
35


# Page. 36

![Page Image](https://bcdn.docswell.com/page/9729LZ2QJR.jpg)

代表的なコンテナオーケストレーションツール
▌Docker Compose
➢ 1台のホスト上で、複数のコンテナを組み合わせて実行する
▌Kubernetes
➢ 複数のホストにまたがって、多数のコンテナを管理、運用する
36


# Page. 37

![Page Image](https://bcdn.docswell.com/page/DJY4QRYY7M.jpg)

Docker Compose
▌1台のホスト上で、複数のコンテナを組み合わせて実行できます
▌コンテナ間のネットワークや、ホストとのボリューム共有をシンプルに設定できます
▌コマンド1つで、複数コンテナからなる環境をまるごと再現できます
コマンド一発で
環境を再現できる
コンテナ
(Web)
コンテナ
(AP)
コンテナ
(DB)
nginx
アプリケーション
MySQL
ホストとの
ボリュームの共有
コンテナ間のネットワーク
データ
ホスト
37


# Page. 38

![Page Image](https://bcdn.docswell.com/page/V7NYKDPRE8.jpg)

複数のホストを扱いたい場合
複数のホストで冗長化したい場合は、Docker Composeとは別の仕組みが必要です
▌Docker Swarmモード（参考）
⚫ Dockerに組み込まれたオーケストレーション機能
⚫ Docker Composeと互換性のある設定で複数ホストを扱える
⚫ ただし、現在は開発が活発ではない
➢複数ホストでの運用は、Kubernetesがデファクトスタンダードとなっています
38


# Page. 39

![Page Image](https://bcdn.docswell.com/page/YJ9PVG3Z73.jpg)

Kubernetes（1）
▌複数のノード（サーバ）にまたがって、多数のコンテナを管理する仕組みです
▌名前が長いため「K8s」と略されることも多いです
▌宣言的な設定が特徴
⚫ 「あるべき状態」を記述するだけで、システムが自動的にその状態を維持してくれます
➢詳細は別の研修で扱います
39


# Page. 40

![Page Image](https://bcdn.docswell.com/page/GJ8DPVLYJD.jpg)

Kubernetes（2）
▌Kubernetesの概要
⚫ 「Control Plane」と「Node」でクラスタを構成
⚫ Control Planeがリソースの状況に応じて自動で配置を最適化し、
Node上で「Pod」（コンテナ）を動かします
リソースが空いてるから
Node(1)とNode(3)で動かすで
冗長構成で
デプロイするぞ！
Control Plane
k8sクラスタを管理する
サーバ
YAML形式
の設定
Pod(コンテナ)
レプリカ(1)
Node(1)
Pod(コンテナ)
レプリカ(2)
Node(2)
Node(3)
コンテナを動かすサーバ
Kubernetes クラスタ
40


# Page. 41

![Page Image](https://bcdn.docswell.com/page/LJLM15L9ER.jpg)

Kubernetes（3）
▌Kubernetesでは、複数のコンテナをひとまとめにした単位を「Pod」として扱います
▌Pod内のコンテナはネットワークを共有します
▌PID Namespaceやルートファイルシステムは、コンテナごとに独立しています
Pod
(クラスタIP: 10.20.30.40、Pod固有のIP)
コンテナ1
コンテナ内のプロセスは
PID 1から始まります
プロセス
(PID 1)
…
コンテナ2
プロセス
(PID N)
コンテナ1用のRoot FS
ルートファイルシステムは
コンテナ毎に独立しており、
再起動するとリセットされます
/
+ /bin
+ /etc
+ /hoge/piyo
プロセス
(PID 1)
…
プロセス
(PID M)
コンテナ2用のRoot FS
/
+ /bin
+ /etc
+ /foo/bar
41


# Page. 42

![Page Image](https://bcdn.docswell.com/page/47MYW3MV7W.jpg)

DockerとKubernetesの関係
▌以前はKubernetesがDockerを呼び出してコンテナを操作していました
▌Dockerの機能が大きくなりすぎたため、コンテナ管理部分がcontainerdとして切り出され、
現在はKubernetesがcontainerdを直接操作しています
Docker CLI
Docker
デーモン
Control Plane
kubelet
(Node上で動くデーモン)
呼び出す
呼び出す
Pod
containerd
起動
runc
コンテナ
kubectl
(CLIツール)
起動
runc
プロセス
ホスト
Dockerの構成
containerd
コンテナ
コンテナ
プロセス
プロセス
Node
DockerもKubernetesも、
内部でcontainerdを呼び出している
Kubernetesの構成
42


# Page. 43

![Page Image](https://bcdn.docswell.com/page/P7R9YQVWE9.jpg)

コンテナオーケストレーション まとめ
▌本格的なサービスを運用するには、多数のコンテナを組み合わせる必要があります
▌コンテナオーケストレーションツールを使うことで、多数のコンテナを効率よく管理できます
⚫ Docker Compose:
シングルホスト向け
⚫ Kubernetes:
マルチホスト向け
43


# Page. 44

![Page Image](https://bcdn.docswell.com/page/PJXQG5ZV7X.jpg)

Dockerfileの書き方
44


# Page. 45

![Page Image](https://bcdn.docswell.com/page/3JK94685JD.jpg)

Dockerfile
▌コンテナイメージのビルド手順を記述したテキストファイルです
▌Dockerfileを用意して「docker build」を実行すると、コンテナイメージが作成されます
45


# Page. 46

![Page Image](https://bcdn.docswell.com/page/LE3WL621E5.jpg)

Dockerfileの書き方
FROM ghcr.io/cybozu/ubuntu:24.04
COPY ./myapp /work/myapp
WORKDIR /work/myapp
ベースとなるコンテナイメージ（ベースイメージ）
を指定する
docker build時に実行する操作
RUN make &amp;&amp; make install
COPY: ホストからコンテナにファイルをコピーする
WORKDIR: 作業ディレクトリを指定する
RUN: 任意のコマンドを実行する
ENV PATH /usr/local/bin
docker run時に参照される設定
CMD [“myapp”, “--opt=hoge”]
ENV: 環境変数を設定する
CMD: デフォルトの実行コマンドを指定する
46


# Page. 47

![Page Image](https://bcdn.docswell.com/page/8EDKNVZK7G.jpg)

イメージのビルド方法
▌カレントディレクトリにDockerfileを置いた状態で、次のように実行するとイメージができる
$ docker build -t
myapp:1.0.0 .
Dockerfileのあるディレクトリパスを指定
コンテナイメージのタグを指定
コンテナイメージの名前を指定
47


# Page. 48

![Page Image](https://bcdn.docswell.com/page/V7PK5VD3J8.jpg)

Dockerfileとコンテナイメージ
▌ベースイメージを元に、命令（COPYやRUNなど）ごとにレイヤーが追加されていきます
➢ レイヤーをOverlay Filesystemで重ね合わせて、
コンテナのファイルシステムを構成している
▌各レイヤーで生成されるファイルが増えるほど、イメージサイズが大きくなります
ベースイメージのレイヤー(1)
FROM ghcr.io/cybozu/ubuntu:24.04
COPY ./myapp /work/myapp
RUN make &amp;&amp; make install
Dockerfile
ベースイメージのレイヤー(2)
ベースイメージのレイヤー(3)
COPY myapp のレイヤー
RUN make のレイヤー
コンテナイメージ
48


# Page. 49

![Page Image](https://bcdn.docswell.com/page/2JVVPZ1NJQ.jpg)

Overlay Filesystemの動作
▌コンテナ内でmountコマンドを実行すると、Overlay FSの設定を確認できます
▌ホストでこれらのディレクトリを見ると、レイヤーの中が確認できます
(この実行例は見やすさのため、改行、整形しています)
lowerdir: 読み取り専用
$ docker run -it --rm ghcr.io/cybozu/ubuntu-debug:24.04 /bin/bash
コンテナイメージの各レイヤーに対応します
root@8f45aedef6e4:/# mount
overlay on / type overlay (rw,relatime,
lowerdir=/var/lib/docker/overlay2/l/4GGUTT3N4HBOIYGMCPOPQIWNHJ:
/var/lib/docker/overlay2/l/K6P3GKW4EHQ2J2ALQPQAQZW4SM:
upperdir: 読み書き可能
…
コンテナ内でファイルを更新すると、この領域に記録されます
/var/lib/docker/overlay2/l/KLSOYHMW7TEBHXQG4CNOVDKEOD:
/var/lib/docker/overlay2/l/EPIZLBCOBVLYBFS2TWQVKJMS2B,
upperdir=/var/lib/docker/overlay2/3d2c88014e88a24b6665b7a8ae9ddfcfb8fa4180e1cdc2cc54ae1203292c51fd/diff,
workdir=/var/lib/docker/overlay2/3d2c88014e88a24b6665b7a8ae9ddfcfb8fa4180e1cdc2cc54ae1203292c51fd/work)
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
tmpfs on /dev type tmpfs (rw,nosuid,size=65536k,mode=755)
49


# Page. 50

![Page Image](https://bcdn.docswell.com/page/5EGLP425JL.jpg)

コンテナベストプラクティス
Dockerfile編
50


# Page. 51

![Page Image](https://bcdn.docswell.com/page/4JQY2GPL7P.jpg)

ベストプラクティス
▌いくつか紹介します
⚫ 信頼できるコンテナイメージを使う（出所不明なイメージは避ける）
⚫ コンテナイメージをできる限り小さくする
⚫ タグを適切に運用する
⚫ ビルドに不要なファイルを.dockerignoreで除外する
⚫ Lint ツールで Dockerfile を静的解析する
⚫ コンテナイメージを定期的にリビルドする
▌Docker公式のベストプラクティスもあるので、そちらも見てください
⚫ https://docs.docker.com/build/building/best-practices/
51


# Page. 52

![Page Image](https://bcdn.docswell.com/page/K74WL5Y5E1.jpg)

信頼できるコンテナイメージを使う
▌出所不明なコンテナイメージには、脆弱性や悪意のあるコードが含まれているリスクがあります
▌社内で推奨されているベースコンテナイメージを活用しましょう
▌Docker Official Imagesは比較的信頼性が高いです
▌いずれの場合も、使用前によく調査することが大切です
52


# Page. 53

![Page Image](https://bcdn.docswell.com/page/LJ1YLW62EG.jpg)

Necoのベースコンテナイメージ
▌PDXチームで、Ubuntuのイメージを管理しています
▌3か月ごとの定期更新および緊急性の高い脆弱性が見つかった場合は即時対応しています
▌いくつか種類があるので用途に応じて使い分けましょう
⚫ ghcr.io/cybozu/ubuntu:24.04
必要最小限のパッケージのみ
⚫ ghcr.io/cybozu/ubuntu-dev:24.04
開発に必要なパッケージを追加
⚫ ghcr.io/cybozu/ubuntu-debug:24.04
デバッグに必要なパッケージを追加
⚫ ghcr.io/cybozu/golang:1.26-noble
Go 言語の開発環境を追加
53


# Page. 54

![Page Image](https://bcdn.docswell.com/page/GJWGV6W272.jpg)

コンテナイメージをできる限り小さくする
▌コンテナイメージのサイズが大きくなると、ディスク容量を圧迫したり
ダウンロードに時間がかかる原因になります
▌イメージを小さくするための主なアプローチは以下の3つです
1. レイヤーを意識してDockerfileを書く
2. マルチステージビルドを活用する
3. サイズの小さなベースイメージを選ぶ
54


# Page. 55

![Page Image](https://bcdn.docswell.com/page/4EZL4Y5473.jpg)

レイヤーを意識してDockerfileを書く（1）
▌RUNやCOPYを実行するたびにレイヤーが追加されます
▌中間ファイルを別のRUN命令で削除しても、そのファイルは前のレイヤーに残り続けます
▌結果として、イメージサイズが意図せず大きくなってしまいます
FROM ghcr.io/cybozu/ubuntu:24.04
ubuntuイメージのファイル
RUN hostname &gt; hostname.txt
hostname.txtの追加
RUN date &gt; date.txt
data.txtの追加
RUN cat hostname.txt date.txt &gt; id.txt
id.txtの追加
RUN rm hostname.txt date.txt
消したつもり
中間ファイルと
削除のレイヤが残る
hostname.txtとdata.txtの削除
コンテナイメージ
55


# Page. 56

![Page Image](https://bcdn.docswell.com/page/Y76W3D9G7V.jpg)

レイヤーを意識してDockerfileを書く（2）
▌複数の処理を1つのRUN命令にまとめ、不要なファイルは同じRUN内で削除します
▌ただし、1つのRUNに詰め込みすぎると可読性が下がるデメリットもあります
▌次に紹介するマルチステージビルドを使う場合は、それほど意識しなくてもかまいません
FROM ghcr.io/cybozu/ubuntu:24.04
1つのRUNでいろいろ実行
不要な一時ファイルを削除
RUN hostname &gt; hostname.txt &amp;&amp; ¥
date &gt; date.txt &amp;&amp; ¥
cat hostname.txt date.txt &gt; id.txt &amp;&amp; ¥
rm hostname.txt date.txt
ubuntuイメージのファイル
id.txtの追加
コンテナイメージ
レイヤーが少なく、
中間ファイルも残らない
56


# Page. 57

![Page Image](https://bcdn.docswell.com/page/G75ML3NX74.jpg)

レイヤーを意識してDockerfileを書く（3）
▌docker history コマンドで、イメージのレイヤー構成を確認できます
▌イメージサイズが予想より大きい場合の原因調査に役立ちます
Dockerfileで
追加したレイヤー
ベースイメージの
レイヤー
$ docker history ghcr.io/cybozu/ubuntu-debug:24.04
IMAGE
CREATED
CREATED BY
07ebfbdbc3f0 29 hours ago
CMD [&quot;/bin/bash&quot;]
&lt;missing&gt;
29 hours ago
RUN /bin/sh -c adduser --disabled-password -…
&lt;missing&gt;
29 hours ago
COPY /go/src/github.com/google/go-containerr…
…
&lt;missing&gt;
30 hours ago
RUN /bin/sh -c apt-get update
&amp;&amp; apt-get…
&lt;missing&gt;
6 days ago
/bin/sh -c #(nop) CMD [&quot;/bin/bash&quot;]
…
&lt;missing&gt;
6 days ago
/bin/sh -c #(nop) ARG LAUNCHPAD_BUILD_ARCH
&lt;missing&gt;
6 days ago
/bin/sh -c #(nop) ARG RELEASE
SIZE
0B
10.2kB
11.4kB
COMMENT
buildkit.dockerfile.v0
buildkit.dockerfile.v0
buildkit.dockerfile.v0
34.9MB
0B
buildkit.dockerfile.v0
0B
0B
57


# Page. 58

![Page Image](https://bcdn.docswell.com/page/9J29LZ5QER.jpg)

マルチステージビルド
▌1つのDockerfileを複数のステージに分けて記述できます
▌ビルド用ステージで生成したファイルを、実行用ステージにコピーします
▌最終ステージのみがコンテナイメージとして保存されるため、イメージサイズを削減できます
# Stage1: build from source
FROM ghcr.io/cybozu/golang:1.26-noble AS build
COPY ./src /work/src
WORKDIR /work/src
RUN go install ./...
Go言語のツール
ソース
# Stage2: setup runtime container
FROM ghcr.io/cybozu/ubuntu:24.04
COPY --from=build /go/bin /
ENTRYPOINT [“/myapp”]
Ubuntu
中間ファイル、ビルド結果
バイナリ
build
最終イメージ
必要なものだけコピー
58


# Page. 59

![Page Image](https://bcdn.docswell.com/page/DEY4QRKYJM.jpg)

小さなコンテナイメージをベースにする
▌ベースイメージの種類によって、サイズや特徴が大きく異なります
▌用途に応じて適切なものを選びましょう
イメージ名
サイズ
特徴
scratch
0B
•
•
libcもshellも含まない空のイメージ。
Go言語などでシングル実行可能なバイナリを作れば、イメージサイズは非常に小さくなり、
OS依存の脆弱性も含まないためセキュア。
busybox
1.2MB
•
•
Linuxのユーティリティをシングルバイナリで提供。
scratch同様、シングル実行バイナリのベースとして使われる。
Alpine Linux
5.6MB
•
•
軽量なLinuxディストリビューション。
ハマりどころも多いので利用には注意が必要。(Necoでは利用禁止)
distroless
16.9MB
～
•
•
実行に必要なものだけを持つイメージ。multi-stage buildと組み合わせて使いやすい。
Java, Python, Node.js用などランタイムごとにイメージが用意されている。
cybozu/ubuntu
103MB
•
PDXチームが管理しているベースイメージ。
59


# Page. 60

![Page Image](https://bcdn.docswell.com/page/VJNYKDRR78.jpg)

タグを適切に運用する
▌コンテナイメージのタグは容易に上書きできるため、運用ルールを決めておくことが重要です
▌他者が公開しているイメージを使う場合
➢ そのタグ運用ルールを事前に確認しましょう
▌自分たちで作成するイメージの場合
➢ タグ運用ルールを明確に定めましょう
社内（Neco チーム）でのタグ運用ルール
⚫ レジストリにプッシュするイメージには、必ず固定タグを付ける
⚫ 一度付けた固定タグは変更しない
⚫ 利便性のために可変タグ（ブランチ名など）を追加することは可
60


# Page. 61

![Page Image](https://bcdn.docswell.com/page/YE9PVGMZJ3.jpg)

ビルドに不要なファイルを.dockerignoreで除外する
▌ビルドに不要なファイルは .dockerignoreに記述して、転送対象から除外しましょう
▌docker build実行時、Dockerfileと同じディレクトリのファイルが
Dockerデーモンに一括転送されます
▌不要なファイルを除外することで、ビルド時間を短縮できます
# 除外するディレクトリや
# ファイルのパターンを列挙
.git/
logs/*
node_modules/
./README.md
61


# Page. 62

![Page Image](https://bcdn.docswell.com/page/GE8DPV1YED.jpg)

LintツールでDockerfileを静的解析する
▌hadolint（https://github.com/hadolint/hadolint）を使いましょう
▌Dockerfileの構文やベストプラクティスへの準拠を静的に解析してくれるツールです
62


# Page. 63

![Page Image](https://bcdn.docswell.com/page/LELM15Q97R.jpg)

コンテナイメージを定期的にリビルドする
▌コンテナイメージは、ビルドした時点の依存関係のスナップショットです
▌アプリケーションに変更がない場合でも、ベースイメージや依存パッケージの
セキュリティ更新を取り込むために、定期的なリビルドをお勧めします
63


# Page. 64

![Page Image](https://bcdn.docswell.com/page/4JMYW31VJW.jpg)

コンテナベストプラクティス
アプリケーション編
64


# Page. 65

![Page Image](https://bcdn.docswell.com/page/PJR9YQLW79.jpg)

コンテナアプリケーションのベストプラクティス
▌コンテナをステートレスに設計する
▌1つのコンテナには1つの役割を持たせる
▌ヘルスチェックのエンドポイントを用意する
▌SIGTERMなどのシグナルを適切に処理する
▌ログは標準出力や標準エラー出力へ出力する
▌回復できないエラーが発生したら速やかに終了する
▌設定値はコンテナイメージに含めない
65


# Page. 66

![Page Image](https://bcdn.docswell.com/page/PEXQG5WVJX.jpg)

ベストプラクティスの背景
▌コンテナの起動や終了はオーケストレーションツールが管理します
▌アプリの更新やスケールアウト、障害復旧など、さまざまな場面でコンテナは動的に入れ替わり
ます
▌オーケストレーションツールの動作を妨げないアプリ設計を心がけましょう
66


# Page. 67

![Page Image](https://bcdn.docswell.com/page/3EK946V5ED.jpg)

コンテナをステートレスに設計する
▌コンテナが突然終了しても、データが失われないように設計しましょう
▌コンテナのファイルシステムは揮発性です
コンテナが終了すると、ファイルシステムに書き込んだデータも消えます
▌永続化が必要なデータは、DBやKubernetesのPersistentVolumeなどの
外部ストレージに保存するのが基本です
▌どのコンテナにリクエストが振り分けられても、同じように動作できる設計を目指しましょう
67


# Page. 68

![Page Image](https://bcdn.docswell.com/page/L73WL6M175.jpg)

1つのコンテナには1つの役割を持たせる
▌WebサーバーやDBなど、異なる役割のプログラムを1つのコンテナに詰め込むのは避けましょう
▌役割ごとにコンテナを分けることで、スケールアウトや障害対応がしやすくなります
▌ログ収集やプロキシなど、メイン処理を補助するコンテナを一緒に動かしたい場合は、
Kubernetesのサイドカーパターンが有効です
▌1つのPodに複数のコンテナを同居させつつ、それぞれの役割を明確に分離できます
68


# Page. 69

![Page Image](https://bcdn.docswell.com/page/87DKNV6KJG.jpg)

ヘルスチェックのエンドポイントを用意する
▌オーケストレーションツールは、コンテナが正常に動作しているかを定期的に確認しています
▌ヘルスチェック用のエンドポイントを用意しておくことで、異常なコンテナを自動で検知・再起動
できます
▌DockerのHEALTHCHECK命令や、KubernetesのLiveness Probeを活用して、
コンテナの死活監視を実装しましょう
69


# Page. 70

![Page Image](https://bcdn.docswell.com/page/VJPK5VY3E8.jpg)

SIGTERMなどのシグナルを適切に処理する
▌コンテナを停止する時、オーケストレーションツールはまずSIGTERMを送信して
プロセスに終了を通知します
▌SIGTERMを無視すると、一定時間後に強制終了（SIGKILL）されてしまいます
▌シグナルを受け取ったら、処理中のリクエストを完了してからグレースフルに終了する実装を心
がけましょう
70


# Page. 71

![Page Image](https://bcdn.docswell.com/page/2EVVPZGNEQ.jpg)

ログは標準出力や標準エラー出力へ出力する
▌コンテナのルートファイルシステムは再起動されると消えてしまうので、
ログをファイルに書き出していると、コンテナ終了時にログも失われてしまいます
▌stdoutやstderrに出力することで、オーケストレーションツールやログ収集基盤が自動的に収
集してくれます
▌複数種類のログがありstdoutやstderrだけでは対応できない場合は、Kubernetesの
PersistentVolumeなどの永続化ストレージにファイルとして出力しましょう
71


# Page. 72

![Page Image](https://bcdn.docswell.com/page/57GLP485EL.jpg)

回復できないエラーが発生したら速やかに終了する
▌回復できないエラーが発生した場合、無理に動き続けることは避けましょう
▌異常な状態のまま処理を続けると、不正なデータを生成したり、障害の原因究明が困難にな
る恐れがあります
▌オーケストレーションツールに再起動を任せ、速やかに終了するのが適切な設計です
▌ヘルスチェックの失敗や異常終了をツールが検知し、自動で再起動してくれます
72


# Page. 73

![Page Image](https://bcdn.docswell.com/page/4EQY2G9LJP.jpg)

設定値はコンテナイメージに含めない
▌接続先のURLやAPIキーなど、環境ごとに違う設定値をイメージに埋め込むのは避けましょう
▌設定値は、環境変数やシークレット管理ツールを通じて、実行時に注入するようにしましょう
▌こうすることで、同じイメージを開発やステージング、本番環境で使い回せるようになります
73


# Page. 74

![Page Image](https://bcdn.docswell.com/page/KJ4WL5X571.jpg)

まとめ
74


# Page. 75

![Page Image](https://bcdn.docswell.com/page/LE1YLWN27G.jpg)

まとめ
▌コンテナとは、依存関係をパッケージ化し、隔離された環境で動かす仕組みです
▌マイクロサービスとの相性が良く、エコシステムも充実しています
▌Docker以外にも、さまざまなコンテナランタイムがあります
▌コンテナの仕様はOCI（Open Container Initiative）で標準化されており、どのランタイ
ムでも同じイメージを利用できます
▌Docker ComposeやKubernetesなど、複数のコンテナを連携させるツールが揃っています
▌Dockerfileの書き方やアプリケーション設計には、押さえておくべきベストプラクティスがあります
75


# Page. 76

![Page Image](https://bcdn.docswell.com/page/GEWGV642J2.jpg)

ハンズオン
Dockerをさわってみる
76


# Page. 77

![Page Image](https://bcdn.docswell.com/page/47ZL4Y24J3.jpg)

ハンズオンの内容
▌コンテナイメージの取得
▌コンテナの起動
▌コンテナに入ってみる
77


# Page. 78

![Page Image](https://bcdn.docswell.com/page/YJ6W3DVGJV.jpg)

よく使うDockerコマンド
▌ container run
: コンテナの実行
▌ run
: コンテナの実行
▌ container exec
: コンテナ上でのコマンドの実行
▌ exec
: コンテナ上でコマンドの実行
▌ container ls
: コンテナの確認
▌ ps
: コンテナの確認
▌ container stop
: コンテナの停止
▌ stop
: コンテナの停止
▌ container rm
: コンテナの削除
▌ rm
: コンテナの削除
▌ container logs
: コンテナのログを確認
▌ logs
: コンテナのログを確認
▌ image ls
: コンテナイメージの確認
▌ images
: コンテナイメージの確認
▌ image rm
: コンテナイメージの削除
▌ rmi
: コンテナイメージの削除
▌ image pull
: コンテナイメージのpull
▌ pull
: コンテナイメージのpull
▌ image build
: コンテナイメージのビルド
▌ build
: コンテナイメージのビルド
▌ image push
: コンテナイメージのpush
▌ push
: コンテナイメージのpush
※ Docker 1.13でコマンド体系が整理されました。左が新しい体系、右が旧来のコマンドです。
詳細は docker &lt;COMMAND&gt; --help で確認できます。
78


# Page. 79

![Page Image](https://bcdn.docswell.com/page/GJ5ML3DXJ4.jpg)

コンテナイメージの取得
# ローカルのコンテナイメージの表示
docker images
# Docker Hubからコンテナイメージを取得する
docker pull nginx:latest
# 再度、ローカルのコンテナイメージの表示
docker images
79


# Page. 80

![Page Image](https://bcdn.docswell.com/page/LE3WL6M4E5.jpg)

コンテナの起動
# コンテナの起動
# -d: バックグラウンドで起動
# --name: コンテナに名前をつける(省略した場合は自動で名前がつく)
# -p 8080:80: コンテナの80番ポートをホストの8080番ポートにバインド
docker run -d --name mynginx -p 8080:80 nginx:latest
# 起動しているコンテナの確認
# コンテナの停止・削除
docker ps
docker stop mynginx
curl localhost:8080
docker rm mynginx
docker logs mynginx
80


# Page. 81

![Page Image](https://bcdn.docswell.com/page/8EDKNV657G.jpg)

コンテナに入ってみる
# ubuntu-debugコンテナ上でbashを実行する
# -i: STDINをオープンし続ける -t: 擬似端末を割り当てる
# --rm: コンテナ終了時にコンテナを自動削除
docker run -it --rm ghcr.io/cybozu/ubuntu-debug:24.04 /bin/bash
# いろんなコマンドを叩いて、コンテナ内のプロセスやファイルシステム、
# ネットワークの状態などを確認してみる
ls
ps aux
hostname
mount
ip a
81


