case-kの備忘録

日々の備忘録です。データ分析とクラウドに興味があります。

「Docker/Kubernetes実践コンテナ開発入門」Docker(1~3章)備忘録

Google Kubernetes Engineについて調べてたのですが、そもそもDockerも今までなんとなく使っていたので、改めて調べて見ました。コマンドとかは自分用の備忘録です。
書籍の「Docker/Kubernetes実践コンテナ開発入門」1~3章と「入門 Docker」を参考にさせてもらいました。
gihyo.jp

y-ohgi.com

Dockerの概要

DevOpsにおけるマイクロサービスとDockerの役割を調べてみました。 

DevOpsとマイクロサービス

DevOPSとは開発と運用のギャップを埋める概念で、開発と運用を高速に行い、ビジネス要件の急速な変化に対応します。近年は変化が激しいため、新しいビジネスやデータを使った機能開発が頻繁に行われています。この変化に対応するためにはプログラムの依存関係をできるだけ無くし、修正しやすく、新しい技術を取り込み安い構成にする必要があります。これには各モジュールを疎結合にする必要があり、このオペレーションや改善しやすい構成を「マイクロサービスアーキテクチャ」と呼ばれています。このアーキテクチャのメリットとしては、ビルドやデプロイがサービス単位でシンプルになり、新しい機能やサービス、技術を取り込み安くなります。

マイクロサービスとDocker

コンテナ技術はDockerの登場がきっかけとなり、本格的に活用が始まりました。Dockerの最大のメリットとしては「ポータビリティ」ことが挙げられます。アプリケーションとそのライブラリなど依存関係にある機能をパッケージングし、1つのユニットとして管理します。マイクロサービスアーキテクチャはこのDokcerコンテナ1つ1つの集合体です。アプリケーションとその依存性がまとまっているため、開発環境や本番環境で差分が小さくなり、同一性の高い環境を構築することが可能になります。
その他にVMと比較した場合「リソース使用量の少なさ」や「軽量で起動速度が早い」といったメリットがあります。VMは コンピュータ自体 を仮想化するのに対して、Dockerは プロセス の仮想化を行います。VMは低レイヤーであるOSから(Mac OS上でWindowsを使う)仮想化を行うのに対して、DockerはホストOSのリソース(Mac OS上ならMAC OSのリソース)を使用することができます。そのため、「軽量化」と「高速化」を実現することができます。

セットアップ

ローカルPCにDocker for Macをインストール
https://hub.docker.com/editions/community/docker-ce-desktop-mac

Docker イメージの操作

Dockerイメージを操作するための基本コマンドです。

docker image buildーイメージビルド

次のようにDockerfileを定義イメージを作ります。

FROM golang:1.9 
RUN mkdir /echo
COPY main.go /echo
CMD ["go", "run", "/echo/main.go"]
  • FROM:Dockerイメージの取得
  • RUN: イメージビルド時にコンテナ内で実行するコマンド
  • COPY:Dockerを動かしているホストマシン上のファイルやディレクトリをDockerコンテナ内にコピーする
  • CMD:コンテナ起動時にコンテナ内で1度実行するコマンド

Dockerfileからイメージを作るコマンドは次の通りです。

# 書式
$ docker image build -t イメージ名[:タグ名] Dockerfile配置ディレクトリのパス 
# ex
$ docker image build -t example/echo:latest .
  • t:任意のイメージを指定。タグ名を省略する場合は「latest」になる。

ファイル名を「Dockerfile」以外で作り、ビルドしたい場合は「-f」オプションを付けます。

$  docker image build -f Dockerfile-test -t example/echo:latest .
  • f:任意の名前のDockerfileをビルドしたい場合

毎回リモートにある最新のDockerfileを取得したい場合は次のようにします。

$ docker image build  --pull=true -t example/echo:latest
  • pull=true :強制的にベースイメージを再取得したい場合

docker image ls ーイメージ確認

docker image ls 

docker searchーイメージの検索

Docker Hubのイメージを検索します。「STARS」の数はイメージを選ぶ指標として使います。

# 書式
docker search [options] 検索キーワード

# ex
$ docker search --limit 5 mysql
NAME                  DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
mysql                 MySQL is a widely used, open-source relation…   9132                [OK]
mysql/mysql-server    Optimized MySQL Server Docker images. Create…   676                                     [OK]
mysql/mysql-cluster   Experimental MySQL Cluster Docker images. Cr…   62
bitnami/mysql         Bitnami MySQL Docker Image                      35                                      [OK]
circleci/mysql        MySQL is a widely used, open-source relation…   18

docker image pullーイメージ取得

docker image pullを使い、Docker Hubのイメージを取得します。

$ docker image pull jenkins:latestc

docker image tagーイメージのタグ付け

Dockerイメージのバージョンはイメージを管理しやすくするために使われます。例えば特定のアプリのバージョンに対応していることを示したい場合はリリース番号を付けます。

$ docker image tag example/echo:latest example/echo:0.1.0

docker image pushーイメージの公開

docker image pushコマンドはDockerイメージをDocker Hubなどのレジストリに登録することができます。

# 認証
$ docker login -u [Docker ID] -p [Password]
# 登録
$ docker image push

Docker Hub

Dockerコンテナの操作

Dockerコンテナを操作するための基本コマンドです。

docker container runーDockerコンテナを実行する

$ docker container run -d -p 9000:8080 example/echo:latest
  • p:ポートフォワーディング。ホストのポートをコンテナのポートに紐付け、コンテナの外から来た通信をコンテナポートに転送する。
  • d:バックグランドでの動作。-dがない場合フォアグランドでの動作になる。

ポートフォワーディングの動作確認

$ curl localhost:9000

docker container lsーコンテナ一覧

$ docker container ls
CONTAINER ID        IMAGE                 COMMAND                  CREATED              STATUS              PORTS                    NAMES
df19212be4bf        example/echo:latest   "go run /echo/main.go"   About a minute ago   Up About a minute   0.0.0.0:9000->8080/tcp   friendly_turing

docker container run --nameー名前付きコンテナ

docker container runに「--name」オプションを付与するとコンテナに任意の名前をつけることができます。dockerコマンドを繰り返し実行するとコンテナIDが変わるため、確認する手間を省くことができます。

# 書式
$ docker container run --name [コンテナ名] [イメージ名][タグ]
# ex
$ docker container run -t -d --name gihyo-echo example/echo:latest

docker container restartーコンテナ再起動

$ docker container restart [コンテナID]

docker container stopーコンテナ停止

$ docker container stop [コンテナID]

docker container rmーコンテナの破棄

$ docker container rm [コンテナID] 

コンテナ実行時に「--rm」オプションを付与するとコンテナ停止時にコンテナを削除する。

docker container run -i --rm [コンテナID]

docker container logsー標準出力の取得

$ docker container logs [コンテナID]

「-f」オプションを付与すると標準出力の取得をし続けます。

docker container execー実行中のコンテナでコマンドを実行

実行中のコンテナでコマンドを実行します。Dockerコンテナのシェルに入りたい場合は次のようにします。

$ docker container exec -it [コンテナID] bash
root@df19212be4bf:/go#
  • i:標準入力を開いたままにする
  • t:仮想ターミナルを割り当てるオプション

シェルに入る場合「-it」をつけて実行する

docker container cpーファイルのコピー

コンテナ内のファイルをローカルにコピーする場合

# 書式 
$ docker container cp [options] コンテナID:コンテナ内のコピー元 ホストのコピー先
$ docker container cp [options] ホストのコピー元 コンテナID:コンテナ内のコピー先

# ex コンテナ=>ホスト
$ docker cp df19212be4bf:/echo/main.go ./main_cp.go

運用管理向けコマンド

Dockerを運用・管理する上で有用なコマンド

docker container pruneーコンテナの破棄

$ docker container prune

docker image pruneーイメージの破棄

$ docker image prune

docker system pruneー利用してない全てのDockerリソース一括削除

利用されてないDockerコンテナやイメージ、ボリューム、ネットワークなど全てのリソースを一括で削除する

$ docker system prune

docker container statsー利用状況の取得

コンテナ単位でシステムリソースの利用状況をしる。

$ docker container stats

表示するコンテナID。UNIX系のOSにおけるTOPコマンドと同じ

Docker Composeー複数のコンテナを操作

実用的なアプリケーションを作る場合、アプリケーション同士の連携が必要です。複数のコンテナが互いに通信し、依存関係も発生します。複数のコンテナの依存関係を定義するには「Docker Compose」を利用します。Composeはyml形式の設定ファイルで、複数コンテナ実行を一括で管理します。

yml形式の設定ファイルを定義

次の実行結果と同じものを、ymlで定義します

$ docker container run -d -p 9000:8080 example/echo:latest

docker-compose.yml

version: "3"
services:
  echo:
    image: example/echo:latest
    ports:
      - 9000:8080
  • version:docker-compose.ymlのファイルフォーマットのバージョン
  • echo:コンテナの名前
  • image:Dockerイメージ
  • ports:ポートフォワーディング指定

docker-compose up -dーコンテナ群起動

定義したymlファイルを元にコンテナ群を起動します。

$ docker-compose up -d

docker-compose downーコンテナ群を停止

ymlで定義したコンテナを全て停止します。

$ docker-compose down

ビルドーymlでDockerfileからイメージを作る

イメージではなく、Dockerfileからビルドしイメージを作る場合はDockerfileのパスをビルドで指定します。

version: "3"
services:
  echo:
    build: .
    ports:
      - 9000:8080

すでにComposeでイメージがビルドされている場合は、「--build」オプションをつけることで、docker compose upの際に必ずDockerイメージのビルドをさせることが可能です。頻繁にイメージをビルドして開発を行う場合、「--build」オプションを利用します。

$ docker-compose up -d --build

Composeで複数のコンテナを実行

Composeで複数のコンテナを実行してみます。Docker Hubに登録されているJenkinsの公式イメージを利用します。まずはマスタのコンテナを作り、その後スレーブのコンテナを立ち上げ、マスタからスレーブを参照できるようにします。

マスタコンテナ作成

まずはjenkinsのマスタコンテナを作ります。次のようにdocker-compose.ymlを作成します。

version: "3"
services:
  master:
    container_name: master
    image: jenkinsci/jenkins:2.142-slim
    ports:
      - 8080:8080
    volumes:
      - ./jenkins_home:/var/jenkins_home
  • volumes:ホスト・コンテナ間でファイルが共有される仕組み。
スレーブコンテナーマスタコンテナのSSH鍵を作る

マスタコンテナにスレーブコンテナを追加します。事前準備としてマスタコンテナからスレーブコンテナにSSH接続できるようにするために、マスタコンテナにSSH keyを作ります。

$ docker container exec -it master ssh-keygen -t rsa -C ""
Jenkins Slaveコンテナを作る

次のようにdocker-compose.ymlを作りビルドします。

version: "3"
services:
  master:
    container_name: master
    image: jenkinsci/jenkins:2.142-slim
    ports:
      - 8080:8080
    volumes:
      - ./jenkins_home:/var/jenkins_home
    links: 
      - slave01
  slave01:
    container_name: slave01
    image: jenkinsci/ssh-slave
    environment:
      - JENKINS_SLAVE_SSH_PUBKEY=[./jenkins_home/.ssh/id_rsa.pubの内容を貼り付ける]
  • links:マスタコンテナからスレーブコンテナへ通信できるようにする
  • environment:環境変数

永続化データの扱い方

Data Volume

Data VolumeはDockerコンテナ内のディレクトリをディスクに永続化するための仕組み。ホストとコンテナ間でデータの共有が可能になるため、ホストの変更をコンテナに反映させることができます。「-v」オプションを利用して行います。

docker container run [options] -v ホスト側ディレクトリ:コンテナ側ディレクトリ リポジトリ名[:タグ] [コマンド] [コマンド引数]
(ex)
$ docker container run -d -p 8080:8080 -v ${PWD}/jenkins_home:/var/jenkins_home jenkins:latest
fdd54656ffdc098f5c9fc53f39279efe1123d8acacff49af387c825cb263e9d4

Data Volumeコンテナ

Data Volumeはコンテナ間とホストで直接ディレクトリを共有してましたが、Data Volumeコンテナを利用する方法では「コンテナ間」でディレクトリを共有します。Data Volumeはホストからコンテナ内のファイルを変更しやすい一方で、ホストの特定のパスに依存しており、誤った操作によりアプリケーション側にデメリットが発生してしまうことも考えらました。Data Volumeコンテナはデータだけをもつコンテナです。永続化データではData Volumeではなく、Data Volumeコンテナで扱うことが推奨されています。Data Volumeコンテナで扱うことで、ホストやアプリケーションのコンテナが削除されても、Data Volumeコンテナを削除しなければデータは保持できます。実際にDaga Volumeコンテナを試してみようと思います。次のようなDockerfileを作りビルドします。

From busybox
VOLUME /var/lib/mysql
CMD ["bin/true"]

DockerfileからイメージをData Volumeコンテナのイメージを作成

$ docker image build -t example/mysql-data:latest .

Data Volumeコンテナを実行。busyboxのshが実行されるだけなのでコンテナは実行直後に終了します。

$ docker container run -d --name mysql-data example/mysql-data:latest

MySQLコンテナを起動する。環境変数MySQLで必要な設定情報を渡し、「--volumes-from」を使ってData VolumeコンテナをMySQLコンテナにマウントする。これにより、MySQLコンテni/var/lib/mysqlのデータは保存されず、Data Volumeのデータを参照するようになる。

$ docker container run -d --rm --name mysql \
 -e "MYSQL_ALLOW_EMPTY_PASSWORD=yes" \
 -e "MYSQL_DATABASE=volume_test" \
 -e "MYSQL_USER=example" \
 -e "MYSQL_PASSWORD=example" \
 --volumes-from mysql-data \
 mysql:5.7

実行中のMySQLコンテナにrootユーザでログインし、データを挿入する。

$ docker container exec -it mysql mysql -u root -p volume_test

 mysql>  CREATE TABLE user(
     id int PRIMARY KEY AUTO_INCREMENT,
     name VARCHAR(255)
 ) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci;

 mysql>  INSERT  INTO  user (name) VALUES ('gihyo'), ('docker'), ('Solomon Hykes');

exitとしてMySQLコンテナを停止する。--rmオプションをつけて起動してるので停止するとコンテナは削除される。削除が確認できたらサイド新しいコンテナを実行して、Data Volumeコンテナに保存したデータがあることを確認する。

$ docker container stop mysql;
 mysql> select * from user;
+----+---------------+
| id | name          |
+----+---------------+
|  1 | gihyo         |
|  2 | docker        |
|  3 | Solomon Hykes |
+----+---------------+
3 rows in set (0.00 sec)

Dockerは一旦以上にしようと思います。次はKubernetesについて調べて行きたいと思います。