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