Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
プログラマのための Docker 教科書_読書メモ

プログラマのための Docker 教科書

コンテナ技術と Docker の概要

コンテナ技術の概要

コンテナ

コンテナについて:

  • ホスト OS 上に論理的な区画を作り、アプリケーションを動作させるのに必要なライブラリやアプリケーションなどを1つにまとめ、あたかも個別のサーバであるかのように扱うことができるようにしたもの
  • ホスト OS のリソースを論理的に分離し、複数のコンテナで共有して使う
  • オーバヘッドが少ないため、軽量で高速に動作する

複数のコンテナを組み合わせて1つのアプリケーションを構成する、マイクロサービス型のアプリケーションと親和性が高い。

サーバ仮想化技術あれこれ

ホスト型サーバ仮想化:

  • ホスト OS のインストールした仮想化ソフトウェアの上でゲスト OS を動作させるやり方
  • ホスト OS からゲスト OS を動かす必要があるため、オーバヘッドが大きくなる
  • Oracle VM VirtualBox や VMware Workstation Player など

ハイパーバイザー型サーバ仮想化:

  • ハードウェア上に仮想化を専門に行うソフトウェアである「ハイパーバイザー」を配置し、ハードウェアと仮想化環境を制御するやり方
  • 仮想環境ごとに別の OS が動作するので、仮想環境の起動にかかるオーバヘッドは大きくなる
  • Hyper-V や XenServer など

コンテナ技術は、アプリケーションの実行環境をまとめることで可搬性を高め、スケーラブルな環境でも動作することを目指している。
仮想化技術の多くは、異なる環境をどう効率よくエミュレートするか、に重きを置いている。

Docker の概要

Docker は、アプリケーションの実行に必要な環境を1つのイメージにまとめ、そのイメージを使って、様々な環境でアプリケーション実行環境を構築・運用するためのオープンソースのプラットフォーム。

プログラマにとっての Docker

アプリケーションをプロダクション環境で稼働させるためには、次のような要素が必要。

  • アプリケーションの実行モジュール
  • ミドルウェアやライブラリ群
  • OS/ネットワークなどのインフラ環境設定

Docker では、これらのインフラ環境を コンテナ として管理する。

Docker で作成した Docker イメージ は、Docker をインストールしている環境であれば基本的にどこでも動作する。
「開発・テスト環境では動くけど、プロダクション環境では動かない」リスクを減らすことができる。

Docker の機能

Docker には大きく分けて3つの機能がある。

  • Docker イメージを作る機能(Build)
  • Docker イメージを共有する機能(Ship)
  • Docker コンテナを動かす機能(Run)

Docker イメージを作る機能(Build)

Docker はアプリケーションの実行に必要になるプログラム本体、ライブラリ、ミドルウェアや、OS やネットワークの設定などを1つにまとめて Docker イメージ を作る。
Docker では1つのイメージには、1つのアプリケーションのみを入れておき、複数のコンテナを組み合わせてサービスを構築するという手法が推奨されている。

Docker イメージを作る手段には二種類ある。

  • Docker のコマンドを使って手動で作る
  • Dokcerfile という設定ファイルを作ってそれを元に自動でイメージを作る

CI/CD の観点から考えると、Dockerfile を使って管理することが望ましい。

Docker イメージを共有する機能(Ship)

Docker のイメージは Docker レジストリで共有できる。
公式の Docker レジストリであり Docker Hub では、Ubuntu や CentOS などのベースイメージが配布されている。
これらのベースイメージにミドルウェアやライブラリなどのイメージを積み重ねて、独自の Docker イメージを作ることができる。

Docker コンテナを動かす機能(Run)

Dokcer は、Linux 上で、コンテナ単位でサーバ機能を動かす。
Docker イメージさえあれば、Docker がインストールされた環境であればどこでもコンテナを動かすことができる。

Docker のエディション

Docker Community Edition(CE)

  • 無償版。下記の機能が提供される
    • Docker コンテナで動作するアプリケーションを構築・テストするためのツール
    • マルチホスト環境での環境構築を行うツール

Docker Enterprise Edition(EE)

  • 商用利用に適した有償版。Basic、Standard、Advanced の三種類がある
    • Basic:Docker 社のサポート、Docker Store での認証済みコンテナ、認証済みプラグインを利用可能
    • Standard:LDAP や AD と統合可能な Docker Datacenter を利用可能
    • Advanced:各種セキュリティ機能を利用可能

Docker のコンポーネント

  • Docker Engine
    • Docker イメージの生成やコンテナの起動などを行うためのコア機能
    • Docker コマンドの実行や Dockerfile によるイメージ生成も行う
  • Docker Registry
    • コンテナの元になる Docker イメージを公開・共有するための機能
  • Docker Compose
    • 複数のコンテナの構成情報をコードで定義して、コンテナを一元管理するためのツール
    • コマンドを実行することでアプリケーションの実行環境を構成するコンテナをまとめて立ち上げることができる
  • Docker Machine
    • Docker の実行環境をコマンドで自動生成するためのツール
    • VirtualBox をはじめ Amazon EC2 や Azure などのクラウド環境にも実行環境を作れる
  • Docker Swarm
    • 複数の Docker ホストをクラスタ化するためのツール

Docker が動く仕組み

コンテナを区画化する仕組み(namespace)

コンテナを区画化する技術には Linux カーネルの namespace という技術を使っている。
Linux カーネルの namespace 機能は、Linux のオブジェクトに名前をつけることで、次の6つの独立した環境を構築できる。

  • PID namespace
  • Network namespace
  • UID namespace
  • MOUNT namespace
  • UTS namespace
  • IPC namespace

リソース管理の仕組み(cgroups)

Docker では、物理マシン上のリソースを複数のコンテナで共有して動作する。
その際のリソースの割り当てなどの管理は Linux カーネルの機能である cgroups を使っている。

cgroups はプロセス・スレッドをグループ化して、そのグループ内に存在するプロセス・スレッドに対して管理を行うための機能。
cgroups でコンテナ内のプロセスに対してリソース制限をかけることで、あるコンテナがホスト OS のリソースを使い尽くして、同じホスト OS 上で稼働している他のコンテナに影響を与えてしまう、ということを防げる。

cgroups で管理できる主なものは以下の通り。

  • cpu:CPU 使用量の制限
  • cpuacct:CPU 使用量の統計情報を提供
  • cpuset:CPU やメモリの配置を制御
  • memory:メモリやスワップの使用量の制限
  • devices:デバイスへのアクセス許可・拒否
  • freezer:グループに属するプロセスの停止・再開
  • net_cls:ネットワーク制御のタグを付加
  • blkio:ブロックデバイスの入出力制御

ネットワーク構成(仮想ブリッジ・仮想 NIC)

Docker コンテナと外部ネットワークが通信を行うときは、仮想ブリッジ docker0 とホスト OS の物理 NIC でパケットを転送する仕組みが必要。
Docker では、 NAPT の機能を使って接続する。

NAPT(Network Address Port Translation) とは、1つの IP アドレスを複数のコンピュータで共有する技術で、 IP アドレスとポート番号を変換する機能のこと。

Docker でこの機能を使うときは、コンテナの起動時にコンテナ内で使っているポートを仮想ブリッジ docker0 に対して開放する。
例えば、コンテナの起動時にコンテナ内の Web サーバが使用する 80 番ポートを、ホスト OS の 8080 番ポートに転送するように設定する。
すると、外部のネットワークからホスト OS の 8080 番ポートにアクセスすると、コンテナ内の 80 番ポートに繋がる。

ちなみに NAPT は技術の名称。
Linux における NAPT の実装のことを IP マスカレード と呼ぶ。

Docker のインストールとチュートリアル

Docker の基本コマンドあれこれ

Docker のバージョン確認

docker version

Docker の実行環境確認

docker system info

Docker のディスク利用状況

docker system df

Docker コマンド

Docker イメージの操作

イメージのダウンロード

イメージの取得は、 docker image pull コマンドを使う。

docker image pull [オプション] イメージ名[:タグ名]

タグ名を省略すると最新版(latest)が取得される。
-a オプションを指定すると、全てのタグを取得することができる。

イメージの一覧表示

docker image ls [オプション] [レポジトリ名]

Docker イメージにはインフラ構成が含まれるため、悪意のある第三者からのなりすましや改ざんを防ぐ必要がある。
Docker Content Trust(DCT)という機能を使うとイメージの正当性を確認できる。

イメージ作成者が Docker レジストリにイメージをアップロードする前に、ローカル環境でイメージ作成者の秘密鍵を使ってイメージに署名する。
この鍵を Offline Key と呼ぶ。

署名されたイメージをダウンロードするときに、イメージ作成者の公開鍵を使って、イメージが本物かどうかを確認する。
この鍵を Tagging key と呼ぶ。

以下の設定を行うことで DCT 機能を有効にできる。

export DOCKER_CONTENT_TRUST=1

イメージの詳細確認

docker image inspect イメージ名[:タグ名]

イメージのタグ設定

Docker イメージに目印となるタグをつけるには、 docker image tag コマンドを使う。
イメージのタグには識別しやすいバージョン名をつけるのが一般的。
また、Docker Hub に作成したイメージを登録するには、以下の規則でイメージにユーザ名をつける必要がある。

Docker Hub のユーザ名/イメージ名:[タグ名]

イメージの検索

docker search [オプション] 検索キーワード

イメージの削除

作成したイメージは docker image rm コマンドで削除できる。

docker image rm [オプション] イメージ名 [イメージ名]

未使用の Docker イメージを削除するときは docker image prune コマンドを使う。
使用していない Docker イメージは無駄なディスク容量を使用するため、定期的に削除するとよい。

Docker Hub へのログイン

Docker レポジトリにアップロードするために、 docker login コマンドを使ってログインする。

docker login [オプション] [サーバ]

サーバ名を指定しない場合、Docker Hub にアクセスする。
別環境にレポジトリがある場合は、サーバ名を指定する。

イメージのアップロード

docker image push イメージ名[:タグ名]

Docker Hub からのログアウト

docker logout [サーバ名]

Docker コンテナの生成・起動・停止

スクリーンショット 2019-04-07

コンテナの生成・起動

Docker コンテナの生成は docker container create を実行する。 Docker コンテナの生成・起動は docker container run を実行する。

docker comntainer run [オプション] イメージ名[:タグ名] [引数]

-d オプションをつけるとコンテナをバックグラウンド実行できる。
バックグラウンド実行時は、コンソールにログが表示されないため、 docker container logs コマンドを使う。

docker container logs -t fbcdab0e9417

コンテナのネットワーク設定

指定できる主なオプションは次の通り。

  • --add-host:コンテナの /etc/hosts にホスト名と IP アドレスを定義する
  • --dns:コンテナ用の DNS サーバの IP アドレス指定
  • --expose:指定したレンジのポート番号を割り当てる
  • --mac-address:コンテナの MAC アドレスを指定する
  • --net:コンテナのネットワークを指定する
  • --hostname:コンテナ自身のホスト名を指定する
  • --publish:ホストとコンテナのポートマッピング
  • --pubulish-all:ホストの任意のポートをコンテナに割り当てる

例えば、コンテナのポート番号とホスト OS のポート番号をマッピングするときは、次のようにコマンドを指定する。

docker container run -d -p 8080:80 nginx

リソースを指定してコンテナを生成・実行

指定できる主なオプションは次の通り。

  • --cpu-shares:CPU の使用の配分
  • --memory:使用するメモリを制限して実行する
  • --volume:ホストとコンテナのディレクトリを共有

コンテナを起動する時に CPU とメモリのリソース利用を制限することができる。
メモリの使用量は --memory オプションを指定する。
CPU 時間は、 --cpu-shares オプションを使うと相対比率が指定できる。
デフォルトでは cpu-shares には 1024 が入っているため、例えば半分の CPU 時間を割り当てたい時は cpu-shares の値を 512 に設定する。

コンテナを生成・起動する環境を指定

指定できる主なオプションは次の通り。

  • --env:環境変数を設定する
  • --env-file:環境変数をファイルから設定する
  • --read-only:コンテナのファイルシステムを読み取り専用にする
  • --workdir:コンテナの作業ディレクトリを指定する
  • --user:ユーザー名または UID を指定する

稼働コンテナの一覧表示

Docker 上で動作するコンテナの稼働状態を確認するときは、 docker container ls コマンドを使う。
このコマンドを実行すると、稼働しているコンテナの状態が一覧で表示できる。

docker container ls [オプション]

docker container ls-a オプションをつけると、停止しているコンテナも全て表示できる。
コンテナをフィルタリングしたい場合は -f オプションで key=value を指定する。

コンテナの稼働確認

Docker 上で動作するコンテナの稼働状態を確認するときは、 docker container stats コマンドを使う。
このコマンドを実行すると、コンテナの稼働状態が一覧で表示できる。

docker container stats [コンテナ識別子]

コンテナの起動

docker container start [オプション] コンテナ識別子 [コンテナ識別子]

コンテナの停止

docker container stop [オプション] コンテナ識別子 [コンテナ識別子]

コンテナの再起動

docker container restart [オプション] コンテナ識別子 [コンテナ識別子]

コンテナの削除

docker container rm [オプション] コンテナ識別子 [コンテナ識別子]

コンテナの中断・再開

docker container pause コンテナ識別子

Docker コンテナのネットワーク

ネットワークの一覧表示

docker network ls [オプション]

ネットワークの作成

docker network create [オプション] ネットワーク

Docker のデフォルトのブリッジネットワークと docker network create でユーザが任意に作成したネットワークでは、名前解決の仕組みが異なる。

  • ブリッジネットワーク
    • コンテナ生成時に明示的に指定しない場合、このネットワークでコンテナが起動する
    • 起動したコンテナは名前解決ができないため、コンテナの生成時にあらかじめ --link オプションをつけておく必要がある
    • --link を指定すると、コンテナ内の /etc/hosts ファイルにコンテナ名とコンテナに割り当てられた IP アドレスが登録される
  • ユーザ定義ネットワーク
    • docker デーモンに内臓された DNS サーバにより名前解決が行われる
    • --link を指定しなくても名前解決ができる
    • コンテナ名だけでなく、 --net-alias オプションによるエイリアス名でも名前解決ができる

ユーザ定義ネットワークを使った方がネットワーク構成を柔軟に設定できる。
特に理由がない場合こちらを使うのが良い。

ネットワークへの接続

ネットワークに接続するときは docker network connect を使う。
ネットワークから切断するときは docker network disconnect を使う。

docker network connect [オプション] ネットワーク コンテナ

ネットワークの詳細確認

docker network inspect [オプション] ネットワーク

ネットワークの削除

docker network rm [オプション] ネットワーク

稼働している Docker コンテナの操作

稼働コンテナへの接続

docker container attach コンテナ識別子

稼働コンテナでプロセス実行

Web サーバのようにバックグラウンドで実行しているコンテナにアクセスしたい時、 docker container attach コマンドで接続しても、シェルが動作していない場合は、コマンドを受け付けることができない。
そのため、 docker container exec を使って任意のコマンドを実行する。

docker container exec [オプション] コンテナ識別子 実行するコマンド [引数]

稼働コンテナのプロセス確認

dcoker container top コンテナ識別子

稼働コンテナのポート転送確認

docker container port コンテナ識別子

コンテナの名前変更

docker container rename 旧コンテナ識別子 新コンテナ識別子

コンテナ内のファイルをコピー

コンテナからホストへのファイルコピー

docker container cp webserver:/etc/nginx/nginx.conf /tmp/nginx.conf

ホストからコンテナへのファイルコピー

docker container cp ./test.txt webserver:/tmp/test.txt

コンテナ操作の差分確認

docker container diff コンテナ識別子

Docker イメージの作成

コンテナからイメージ作成

docker container commit [オプション] コンテナ識別子 [イメージ名[:タグ名]]

コンテナを tar ファイル出力

Docker では、動作しているコンテナのディレクトリ・ファイル群をまとめて tar ファイルを作成することができる。
この tar ファイルを元にして、別のサーバでコンテナを稼働させることができる。

docker container export コンテナ識別子

tar ファイルからイメージ作成

docker container import ファイルまたは URL - [イメージ名[:タグ名]]

イメージの保存

docker image save [オプション] 保存ファイル名 [イメージ名]

イメージの読み込み

docker image load [オプション]

export で保存したものは import で読みこむ。
save で保存したものは load で読み込む。

不要なイメージ・コンテナを一括削除

docker system prune [オプション]

Dockerfile を使ったコードによるサーバ構築

Dockerfile による構成管理

Dockerfile は、Docker 上で動作させるコンテナの構成情報を記述するためのファイル。
Dockerfile を指定して docker build コマンドを実行することで Docker イメージを作成できる。

Dockerfile の主な命令は次の通り。

  • FROM:ベースイメージの指定
  • RUN:コマンド実行
  • CMD:コンテナの実行コマンド
  • LABEL:ラベルを指定
  • EXPOSE:ポートのエクスポート
  • ENV:環境変数
  • ADD:ファイル・ディレクトリのコピー
  • COPY:ファイルのコピー
  • ENTRYPOINT:コンテナの実行コマンド
  • VOLUME:ボリュームのマウント
  • USER:ユーザの指定
  • WORKDIR:作業ディレクトリ
  • ARG:Dockerfile 内の変数
  • ONBUILD:ビルド完了後に実行される命令
  • STOPSIGNAL:システムコールシグナルの設定
  • HEALTHCHECK:コンテナのヘルスチェック
  • SHELL:デフォルトシェルの設定

Dockerfile の作成

Dockerfile では、「Docker コンテナをどの Docker イメージから生成するか」の情報を必ず記述する必要がある。
このイメージをベースイメージと呼ぶ。

FROM [イメージ名]
FROM [イメージ名][:タグ名]
FROM [イメージ名][@ダイジェスト]

タグ名を省略したときは、ベースイメージの最新バージョン(latest)が適用される。

Dockerfile のビルドとイメージレイヤ

Dockerfile から Docker イメージの作成

docker build -t [生成するイメージ名][:タグ名] [Dockerfile の場所]

ベースイメージと作成したイメージは IMAGE ID が同じになる。
これは、イメージとしては別々の名前が付いているが、実態は同じイメージであることを示している。

Docker イメージのレイヤ構造

Dockerfile をビルドしてイメージを作成すると、Dockerfile の命令ごとにイメージが作成される。
作成された複数のイメージはレイヤ構造になる(作成したイメージは共有される)。
Docker では、ディスクの容量を効率よく利用できるようにするため、イメージを積み重ねる方式を採用している。

マルチステージビルドによるアプリケーション開発

Docker にはアプリケーションをビルドするための Docker イメージと、プロダクション環境で実際に動作させる Docker イメージを同時に作成できる機能がある。
これをマルチステージビルドという。

コマンド・デーモンの実行

コマンドの実行

イメージを作成するために何らかのコマンドを実行するときには、 RUN 命令を使う。

RUN 命令には二種類の記述の仕方がある。

  • Shell 形式での記述
RUN apt-get install -y nginx
  • Exec 形式での記述
RUN ["/bin/bash", "-c", "apt-get install -y nginx"]

/bin/sh を介してコマンドを実行したい場合は Shell 形式で記述し、それ以外は Exec 形式で記述すると良い。

Dockerfile をビルドすると、記述された1命令ごとに、内部のイメージが一つ作成される。
1行でかける RUN 命令はなるべく1行で書くほうが望ましい。

デーモンの実行

イメージを元に生成したコンテナ内でコマンドを実行するには、CMD 命令を使う。
Dockerfile には、1つの CMD 命令を記述することができる。

例えば、

  • Web サーバを稼働させるために Nginx をインストールする時は RUN コマンド
  • インストールした Nginx をデーモンとしてコンテナ内で起動させる時は CMD コマンド

CMD 命令には三種類の記述の仕方がある。

  • Exec 形式での記述
CMD ["nginx", "-g", darmon off;""]
  • Shell 形式での記述
CMD nginx -g 'daemon off;'
  • ENTRYPOINT 命令のパラメータとしての記述

Nginx を 80 ポートでデーモン起動する場合はこんな感じで書く。

FROM ubuntu:16.04

RUN apt-get -y update && apt-get -y upgrade
RUN apt-get -y install nginx

EXPOSE 80

CMD ["nginx", "-g", darmon off;""]

デーモンの実行

ENTRYPOINT 命令で指定したコマンドは、Dockerfile からビルドしたイメージから Docker コンテナを起動するため、docker container run コマンドを実行した時に実行される。

ENTRYPOINT 命令は二種類の記述の仕方がある。

  • Exec 形式での記述
  • Shell 形式での記述

CMD 命令の場合は、コンテナ起動時に実行したいコマンドを定義しても、 docker container run コマンド実行時に引数で新たなコマンドを指定した場合、そちらを優先実行する。

ENTRYPOINT 命令で指定したコマンドは、必ずコンテナで実行される。
実行時にコマンド引数を指定したい時は、CMD 命令組み合わせて使う。
コンテナをデフォルトで実行した時の動作を決定できるため便利。

ビルド完了後に実行される命令

ONBUILD 命令は、次のビルドで実行するコマンドをイメージ内に設定するための命令。

ONBUILD [実行したいコマンド]

ONBUILD 命令では、自身の Dockerfile から生成したイメージをベースイメージとした別の Dockerfile をビルドする時に実行したいコマンドを記述する。
例えば、

  • インフラ構築の担当者が OS やミドルウェア設定などのベースとなる Dockerfile を作る
  • アプリケーション開発の担当者はこのベースを元に実行環境を作る

みたいな役割分担をしたい場合に便利。

システムコールシグナルの設定

コンテナを終了するときに送信するシグナルを設定する時は STOPSIGNAL 命令を使う。

STOPSIGNAL [シグナル]

コンテナのヘルスチェック命令

コンテナ内のプロセスが正しく動作しているかをチェックしたい時は HEALTHCHECK 命令を使う。

HEALTHCHECK [オプション] CMD 実行するコマンド

指定できるオプションいろいろ:

  • --interval=n:ヘルスチェックの間隔
  • --timeout=n:ヘルスチェックのタイムアウト
  • --retries=N:タイムアウトの回数

環境・ネットワークの設定

環境変数の設定

Dockerfile 内で環境変数を設定したいときは ENV 命令を使う。

ENV [key] [values]
ENV [key]=[values]

ENV の設定の仕方は次の二種類。

  • key value 型:単一の環境変数に1つの値をセットする
  • key=value 型:一度に複数の値をセットする

ENV 命令で設定した環境変数は、コンテナ実行時の docker container run コマンドの --env オプションを使用することで変更できる。

作業ディレクトリの指定

WORKDIR [作業ディレクトリのパス]

WORKDIR 命令は、Dockerfile に書かれた次の命令を実行するための作業用ディレクトリを指定する。

  • RUN 命令
  • CMD 命令
  • ENTRYPOINT 命令
  • COPY 命令
  • ADD 命令

指定したディレクトリが存在しなければ、新たに作成する。

WORKDIR 命令には、ENV 命令で指定した環境変数を使うことができる。

ENV DIRPATH /first
ENV DIRNAME second
WORKDIR $DIRPATH/$DIRNAME

ユーザの指定

USER [ユーザ名/UID]

USER 命令で指定するユーザは、あらかじめ RUN 命令で作成する必要があるので注意。

ラベルの指定

イメージにバージョン情報や作成者情報をもたせたい場合は LABEL 命令を使う。

LABEL <キー>=<値>

旧バージョンの Docker では MAINTAINER 命令を使っていたが、この命令は現在非推奨。
作成者を指定したい場合は LABEL を使うのが良い。

ポートの設定

EXPOSE <ポート番号>

Dockerfile 内変数の設定

Dockerfile 内で使用する変数を定義するときは ARG 命令を使う。
環境変数である ENV とは異なり、Dockerfile 内でのみこの変数を使用できる。

ARG <名前>[=デフォルト値]

デフォルトシェルの設定

デフォルトのシェル設定を変更したい場合は SHELL 命令を使う。
Linux なら ["/bin/sh", "-c"]、Windows なら ["cmd", "/S", "/C"] がデフォルトで使用される。

SHELL ["シェルのパス", "パラメータ"]

ファイルの設定

ファイル・ディレクトリの追加

ADD <ホストのファイルパス> <Docker イメージのファイルパス>
ADD ["<ホストのファイルパス>" "<Docker イメージのファイルパス>"]

ADD 命令は、ホストのファイル・ディレクトリやリモートファイルを Docker イメージ内にコピーする。

追加したいホストのファイルパスには、Dockerfile のあるディレクトリ内部を指定する。
ホストのファイルパスには、ワイルドカードと Go 言語の filepath.Match ルールに一致するパターンが使える。

ビルドに不要なファイルを除外したい場合は .dockerignore ファイルを作成すると便利。

ファイルのコピー

COPY <ホストのファイルパス> <Docker イメージのファイルパス>
COPY ["<ホストのファイルパス>" "<Docker イメージのファイルパス>"]

ADD 命令はリモートファイルのダウンロードやアーカイブの解凍などの機能をもつ。
COPY 命令は、ホスト上のファイルをイメージ内にコピーするだけ。
単純に、イメージ内にファイルを配置したいだけのときは COPY 命令を使う。

ボリュームのマウント

VOLUME ["/マウントポイント"]

コンテナは永続データを保持するのに適していない。
そのため、永続化が必要なデータはコンテナの外のストレージに保存するのが良い。

永続データは Docker のホストマシン上のボリュームにマウントするか、共有ストレージをボリュームとして、マウントすることが可能。

Docker イメージの公開

Docker イメージの自動生成・公開

Docker Hub には、GitHub および BitBucket と連携して、Dockerfile から Docker イメージを自動で生成する Automated Build 機能がある。

Docker Registry を使ったプライベートレジストリ構築

Docker レジストリを、プライベートネットワーク内で構築するためには、Docker Store で公開されている公式イメージである registry を使用する。

プライベートレジストリでは、Docker イメージを永続データとして管理する必要がある。

Docker では、ホストマシンにボリュームを共有することで、永続データを一元管理できる。
しかし、このデータを管理するには、信頼性が高く、十分な空き容量を持つストレージを用意する必要がある。

複数コンテナの運用管理

複数コンテナ管理の概要

Docker Compose

Docker Compose は複数のコンテナをまとめて管理するためのツール。
docker-compose.yml というファイルにコンテナの構成情報を定義することで、同一のホスト上の複数のコンテナを一括管理できる。

Docker Compose による複数コンテナの構成管理

docker-compose.yml の概要

Docker Compose では、 docker-compose.yml という定義ファイルに、システム内で稼働する複数のサーバ群の構成をまとめて定義する。
この定義ファイルは YAML で書かれる。

Compose 定義ファイルには、管理したいコンテナの

  • サービス(services:)
  • ネットワーク(networks:)
  • ボリューム(volumes:)

を定義する。

Compose 定義ファイルは、バージョンによって記述できる項目が異なる。
明示的なバージョンの指定がない場合は 1.0 として動作する。

docker-compose.yml は例えばこんな感じで書く。

verison: "3"
services:
  webserver:
    image: ubuntu
    ports:
      - "80:80"
    networks:
      - webnet
  redis:
    image: redis
    networks:
      - webnet
networks:
  webnet: ...
volumes:
  data-volume: ...

イメージの指定

ベースイメージを指定するには image を使う。
image には、イメージの名前またはイメージ ID のいずれかを指定する。
イメージのタグを指定しない場合、最新バージョン(latest)がダウンロードされる。

イメージのビルド

イメージの構成を Dockerfile に記述して、それを自動でビルドしてベースイメージに指定するときは build を指定する。
build には Dockerfile のファイルパスを指定する。
build には、docker-compose.yml のあるディレクトリをカレントディレクトリとしたときの Dockerfile の場所を指定する。

services:
  webserver:
    build: .

任意の名前の Dockerfile をビルドするときは dockerfile を指定する。
その際には、Dockerfile があるディレクトリのパスや Git レポジトリの URL を context で指定する。

services:
  webserver:
    build:
      context: /data
      dockerfile: Dockerfile-alternate

Docker イメージをビルドする際に引数を args として指定することもできる。

コンテナ内で動かすコマンドの指定

コンテナで動かすコマンドは command で指定する。
ベースイメージで指定されている場合は、そのコマンドを上書きする。

command: /bin/bash

また、 entrypoint を上書きすることもできる。

entrypoint:
  - php
  - -d
  - memory_limit=-1

コンテナ間の連携

別のコンテナへリンク機能を使って連携したいときは、 links に連携先のコンテナ名を設定する。
コンテナ名とは別にエイリアスをつけたい場合は サービス名:エイリアス名 を指定する。

links:
  - logserver
  - logserver:log01

コンテナ間の通信

コンテナが公開するポートは ports で指定する。
ホストマシンのポート番号:コンテナのポート番号 を指定するか、コンテナのポート番号のみを指定する。
(コンテナのポート番号のみを指定した場合、ホストのポート番号はランダムになる)

ポート番号を指定する場合はダブルクォーテーションで囲み、文字列として扱うこと。

ports:
  - "80:80"

ホストマシンへポートを公開せず、リンク機能を使って連携するコンテナのみポートを公開するときは expose を指定する。

expose:
  - "80"

サービスの依存関係の定義

複数のサービスの依存関係を定義するときは depends_on を指定する。

例えば、webserver コンテナを起動する前に db と redis を起動したい、という場合はこう書く。

services:
  webserver:
    build: .
    depends_on:
      - db
      - redis
  redis:
    image: redis
  db:
    image: postgres

depends_on がやるのは、コンテナの開始順序の制御だけ。
コンテナのアプリケーションが利用可能な状態になるまで待ったりはしてくれないので、そこはアプリケーション側で対応する必要がある。

コンテナの環境変数の指定

コンテナ内の環境変数を指定するときは environment を指定する。
YAML 配列形式、またはハッシュ形式のどちらかで変数を指定できる。

設定したい環境変数の数が多いときは、別ファイルで環境変数を定義して、そのファイルを読み込ませることもできる。
環境変数ファイルを読み込むときは env_file を指定する。

envfile:

HOGE=fuga
FOO=bar

Dockerfile:

env_file: envfile

コンテナの情報設定

Docker Compose で生成されるコンテナに名前をつけるときは、 container_name を指定する。
Docker コンテナ名は一意である必要がある。

container_name: web-container

コンテナにラベルをつけるときは labels を指定する。

コンテナのデータ管理

コンテナにボリュームをマウントするときは、 volumes を指定する。

volumes:
  - /var/lib/mysql
  - cache/:/tmp/cahce

ボリュームの指定の後ろに ro を指定することで、ボリュームを読み取り専用としてマウントすることができる。
設定ファイルが格納されたボリュームなど、書き込みを禁止したい場合に使うと便利。

volumes:
  - ~/configs:/etc/configs/:ro

別コンテナから全てのボリュームをマウントするときは、volumes_from にコンテナ名を指定する。

volumes_from:
  - logs

Docker Compose による複数コンテナ運用

Docker Compose のバージョン確認

dokcer-compose --version

Docker Compose の基本コマンド

  • up:コンテナの生成・起動
  • ps:コンテナの一覧表示
  • logs:コンテナログ出力
  • run:コンテナの実行
  • start:コンテナの起動
  • stop:コンテナの停止
  • restart:コンテナの再起動
  • pause:コンテナの中断
  • unpause:コンテナの再開
  • port:公開ポート番号の表示
  • config:構成の確認
  • kill:実行中のコンテナの強制停止
  • rm:コンテナの削除
  • down:リソースの削除

docker-compose コマンドは、docker-compose.yml を保存したディレクトリで実行する。
サブコマンドの後ろにコンテナ名を指定すると、そのコンテナのみを操作できる。

複数コンテナの生成

docker-compose up [オプション] [サービス名]

コンテナをバックグラウンドで実行するときは -d オプションを指定する。
コンテナ起動時に Dockerfile をビルドしたいときは、 --build オプションを指定する。
コンテナ生成する数を指定するときは --scale オプションを使う。

docker-compose up --scale [サービス名=数]

複数コンテナの確認

複数コンテナの一覧表示を行うときは docker-compose ps を使う。

docker-compose ps

コンテナのログを確認するには docker-compose logs コマンドを使用する。

コンテナでのコマンド実行

docker-compose run [サービス名] [コマンド]

複数コンテナの起動・停止・再起動

docker-compose start
docker-compose stop
docker-compose restart

複数コンテナの一時停止・再開

docker-compose pause
docker-compose unpause

サービスの構成確認

サービスの公開ようポートを確認するときは docker-compose port コマンドを使用する。

docker-compose port [オプション] サービス名 プライベートポート番号

Compose の構成を確認するときは docker-compose config コマンドを使う。

docker-compose config

複数コンテナの強制停止・削除

実行中のコンテナを強制停止するときは docker-compose kill コマンドを使う。

docker-compose kill

オプションを指定せずに docker-compose kill を実行すると、 SIGKILL が送信される。
SIGKILL はプロセスを強制終了させる。

生成した複数のコンテナを削除するときは docker-compose rm を使う。

docker-compose rm

複数リソースの一括削除

Compose 定義ファイルに基づいて生成したコンテナや Docker イメージなどのリソースをまとめて削除するときは docker-compose down を使う。

docker-compose down

docker-compose down は、以下の作業を一括で行う。

  • 実行中のコンテナの停止
  • Docker イメージの削除
  • ネットワークの削除
  • データボリュームの削除

マルチホスト環境での Docker 実行環境構築

マルチホスト環境でのコンテナ管理の概要

マルチホスト環境とクラスタリング

Docker では、単一のホストマシンでの動作だけでなく、複数のホストマシン上で Docker を動作させて、高可用性・高拡張性のアプリケーション実行環境を構築できる。
マルチホスト環境でコンテナ群のクラスタリングを行うためのツールを コンテナオーケストレーションツール と呼ぶ。

Docker Machine とは

Docker Machine とは、ホストマシン・クラウド・仮想環境などに Docker の実行環境を作成できるコマンドラインツール。

GCE 上で動かす場合は、こんな感じでプロジェクトの設定をして、

gcloud config set project docker-book
PROJECT_ID=$(gcloud config list project --format "value(core.project)")

こんな感じで GCE インスタンスを起動できる。

docker-machine create --driver google \
  --google-project $PROJECT_ID \
  --google-zone asia-northeast1-a \
  --google-machine-type f1-micro \
  --google-tags 'http-server' \
  --google-machine-image httos://www.googleapos.com/compute/v1/projects/ubuntu-os-cloud/global/images/family/ubuntu-1604-lts \
  gcp-host

インスタンスが起動したら、ssh して、

docker-machine ssh gcp-host

コンテナを起動する。

sudo docker container run --name webserver -it -p 80:80 asashiho/photoview-image

Docker Machine 基本コマンド

コマンドいろいろ:

  • craete:実行環境の作成
  • ls:実行環境の一覧表示
  • status:実行環境のステータス表示
  • url:実行環境の URL 表示
  • ssh:実行環境の
  • start:実行環境への SSH 接続
  • stop:実行環境の起動
  • restart:実行環境の再起動
  • scp:実行環境からのファイルダウンロード
  • rm:実行環境の削除
  • kill:実行環境の強制停止
  • ip:実行環境の IP アドレス確認
  • inspect:実行環境の情報確認

クラウドを使った Docker 実行環境構築

クラウド環境での Docker オーケストレーション

分散環境におけるコンテナの運用管理

Docker コンテナは、1台のマシンで稼働させるときは手軽に導入できる。
マルチホストで構成された本番環境をクラスタ構成で稼働させるには、コンテナの起動・停止などの操作だけでなく、

  • ホスト間のネットワーク接続
  • ストレージの管理
  • コンテナをどのホストで稼働させるかなどのスケジューリング機能
  • コンテナが正常動作しているかを監視する仕組み

などが必要になる。
これらの機能を備え、コンテナを統合管理できるツールを コンテナオーケストレーションツール と呼ぶ。

代表的なコンテナオーケストレーションツールは以下の通り。

  • Kubernetes
  • Docker Engine(Swarm モード)
  • Apache Mesos、Marathon

パブリッククラウドが提供するマネージドサービス

  • Amazon EC2 Container Service
  • Azure Container Service(AKS)
  • Google Kubernetes Engine(GKE)

Google Cloud Platform のコンテナ関連サービス

  • Google Container Builder
  • Google Kubernetes Engine
  • Google Container Registry

Kubernetes の概要

Kubernetes は、複数のホストを束ねて Docker を利用するためのオーケストレーションツール。
分散環境において「あたかも一台のコンピュータ」のように透過的にコンテナにアクセスすることができる。

Kubernetes の主な機能は次の通り:

  • 複数サーバでのコンテナ管理
  • コンテナ間のネットワーク管理
  • コンテナの負荷分散
  • コンテナの監視
  • 無停止でのアップデート

Kubernetes のサーバ構成

Kubernetes では マスター ノード データストア がお互いに協調しながらコンテナの実行環境を管理する。
概要を説明するとこんな感じ:

マスターサーバ(Kubernetes Master)

Kubernetes クラスタ内のコンテナを操作するためのサーバ。
kubectrl コマンドが投げられると、マスターサーバがリクエストを受け取って処理を行う。
ノードのリソース使用状況を確認して、コンテナを起動するノードを自動的に選択してくれる。

バックエンドデータベース(etcd)

etcd と呼ばれる分散キーバリューストア(KVS)を使って、クラスタの構成情報を管理する。
etcd にはクラスタを構成するための設定情報が書き込まれている。

ノード(Node)

実際に Docker コンテナを動作させるサーバ。
ノードを複数用意してクラスタを構成する。
クラウドでは仮想マシンのインスタンスがノードになる。

アプリケーションの構成管理

Kubernetes の基本概念の説明いろいろ。

ポッド(Pod)

Kubernetes におけるアプリケーションのデプロイの最小単位。
Pod の単位でコンテナの作成・開始・停止・削除が行われる。
Web フロントエンドとデータベースサーバ、など、役割の異なる機能を1つの Pod に格納するのは NG。

Pod は必ず同じノード上に同時にデプロイされる、という特徴がある。
Pod 内の複数のコンテナで仮想 NIC (プライベート IP )を共有する構成を取るため、コンテナ同士が localhost 経由で通信できる。
共有ディレクトリを介してログ情報をやりとりすることもできる。
ノードの中には複数の Pod が配置される。

レプリカセット(ReplicaSet)

Kubernetes クラスタ上であらかじめ指定された Pod を作成・起動しておく仕組み。
クラスタ上に決められた数の Pod を必ず起動しておいてくれる。

ReplicaSet は起動中の Pod を監視し、障害など何らかの理由で停止してしまった場合、該当の Pod を削除し、新たな Pod を起動する。
クラスタ内に Pod をいくつ起動しておくかの値を レプリカ数 と呼ぶ。

デプロイメント(Deployment)

Pod と ReplicaSet をまとめたもので、 ReplicaSet の履歴を管理するもの。
Deployment は ReplicaSet のテンプレートを持ち、そこで Pod の構成を定義し、このテンプレートを使って ReplicaSet を作る。
履歴を管理できるため、Pod 内のコンテナをローリングアップデートしたり、履歴を元に1つ前の世代に戻すことができたりする。

ReplicaSet は定義されたレプリカの数を維持するもの。
Deployment は ReplicaSet の作成や更新を定義するもの。
と整理するとわかりやすい。

ネットワークの管理

Kubernetes クラスタ内で起動した Pod に対して、外部からアクセスするときは「サービス」を定義する。
サービスは Kubernetes のネットワークを管理するもので、いくつか種類がある。
そのうちの一つである LoadBalancer は、Service に対応する IP アドレス + ポート番号にアクセスすると、複数の Pod に対するレイヤ4レベルの負荷分散を行う。

サービスによって割り当てられる IP アドレスには二種類ある。

  • ClusterIP:クラスタ内の Pod 同士で通信するためのプライベート IP アドレス
  • ExternalIP:外部のクライアントから接続するためのパブリック IP アドレス

Label によるリソースの識別

Kubernetes ではリソースを識別するためにランダムな名前が内部で自動的に付与される。
これだとリソース管理がしづらいので、 Label をつけて管理できる。

Kubernetes の仕組み

マスター

マスターは以下のようなコンポーネントで構成される。

  • API Server
    • Kubernetes のリソース情報を管理するためのフロントエンドの REST API
    • 各コンポーネントからリソースの情報を受け取り、データストア(etcd)上に格納する
    • プログラマがこの API Server にアクセスするには、Web の GUI ツールか kubectrl コマンドを使う
  • Scheduler
    • Pod をどのノードで動かすかを制御するバックエンドコンポーネント
  • Controll Manager
    • Kubernetes クラスタの状態を常に監視するバックエンドコンポーネント
    • 定義ファイルで指定したものと実際のノードやコンテナで動作している状態をまとめて管理する

データストア

Kubernetes クラスタの構成を保持する分散 KVS。
どのような Pod をどう配置するかなどの構成情報をもち、API Server から参照される。

ノード

ノードは以下のようなコンポーネントで構成される。

  • Kubelet
    • Pod の定義ファイルにしたがって Docker コンテナを実行したり、ストレージをマウントしたりする機能をもつ
    • ノードのステータスを定期的に監視する機能をもち、ステータスが変わると API Server に通知する

Kubernetes では、クラスタの構成情報を YAML または JSON の定義ファイルで管理できる。
この定義ファイルをマニフェスト(manifest)ファイルと呼ぶ。

GCP を使った Docker アプリケーション実行環境構築

アプリケーションの設定情報管理

アプリケーションで利用する設定情報や、外部サービスの API キーなどはコンテナ外部で管理するのが望ましい。
Kubernetes では、これらの設定情報を管理する機能が提供されている。

ConfigMap

アプリケーションで共通に利用するプロパティを定義したもの。
Key-Value 型でプロパティを指定できる。
設定した値は etcd でプレーンテキストで管理される。

apiVersion: v1
kind: ConfigMap
metadata:
  name: projectId
data:
  project.id: "hello-docker"

ConfigMap で設定した値は、コンテナ内から環境変数として利用できる。

Secrets

API キーやデータベースに接続するための ID、パスワードなどの機密データは Secrets で管理する。
ConfigMap 同様、Key-Value 型でプロパティを指定できる。
Secrets は Base64 エンコードした値を使い、Cloud Console から設定が確認できないようになっている。

apiVersion: v1
kind: Secret
metadata:
  name: apiKey
type: Opaque
data:
  id: YXNh
  Key: YUJjRDEyMw==

Base64 エンコードは暗号化ではないため、Secrets 定義ファイルは公開リポジトリに置いたりしないよう適切に管理すること。

アプリのデプロイ

デプロイメント定義ファイルはこんな感じ:

apiVersion: v1
kind: Deployment
metadata:
  name: webserver-blue
spec:
  replicas: 3
  template:
    metadata:
      labels:
        type: webserver
        color: blue
    spec:
      containers:
        - image: gcr.io/<PROJECT_ID>/imageview:blue
          name: webserver-container
    env:
      - name: PROJECT_ID
        valueFrom:
          configMapKeyRef:
            name: projectid
            key: project.id
      - name: SECRET_ID
        valueFrom:
          secretKeyRef:
            name: apikey
            key: id
      - name: SECRET_KEY
        valueFrom:
          secretKeyRef:
            name: apikey
            key: key
    ports:
      - containerPort: 80
        name: http-server

アプリケーションをデプロイ:

kubectl create -f config/deployment-blue.yaml
kubectl create -f config/deployment-green.yaml

サービスの公開

Kubernetes でデプロイしたアプリを外部に公開するときは、サービスを使う。

サービス定義ファイルはこんな感じ:

apiVersion: v1
kind: Service
metadata:
  name: webserver
spec:
  type: LoadBalancer
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  selector:
    type: webserver
    color: blue

サービスを公開:

kubectrl create -f config/service.yaml

blue を green に切り替えるときはこんな感じ:

kubectrl edit svc webserver

バッチジョブの実行

定期的に実行するバッチジョブを Kubernetes クラスタ上で実行したいときには CronJob を使う。
一度きりのジョブを実行したい場合は Jobs を使う。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.