Warning: count(): Parameter must be an array or an object that implements Countable in /home/xs638785/agile-software.site/public_html/wp-content/plugins/rich-table-of-content/functions.php on line 490
ローカルやオンプレなどで動かしていたコンテナ環境を、AWSやAzureなどのクラウド上にデプロイすることも容易になってきています。
そのため、今後もDockerを使った開発、構築は増えてくるのではないかと思いますので、このタイミングでDockerについての良さや使い方を知っていただけるとよいと思っています。
Dockerとは何か、何が良いのか
Dockerは、コンテナ型の仮想環境を作成、配布、実行するためのプラットフォームです。
Dockerは、Linuxのコンテナ技術を使ったもので、よく仮想マシンと比較されます。VirtualBoxなどの仮想マシンでは、ホストマシン上でハイパーバイザを利用しゲストOSを動かし、その上でミドルウェアなどを動かします。それに対し、コンテナはホストマシンのカーネルを利用し、プロセスやユーザなどを隔離することで、あたかも別のマシンが動いているかのように動かすことができます。そのため、軽量で高速に起動、停止などが可能です。
また、Dockerはミドルウェアのインストールや各種環境設定をコード化して管理します。
これはInfrastracture as Code(IaC)と呼ばれていて、ソフトウェア開発で実施されてきた構成管理や自動化などを、サーバーの各種設定やミドルウェアのインストールなどにも適用したものです。
Dockerの利点
- コード化されたファイルを共有することで、どこでも誰でも同じ環境が作れる。
- 作成した環境を配布しやすい。
- スクラップ&ビルドが容易にできる。
例えば、開発環境(Windows上)では動いていたけどLinuxで動かなかった、といったケースも、開発工程からDockerを活用していくことで防ぎやすくなります。そして、開発工程の中で使っていた環境をそのまま本番環境に持っていくことも可能なため、環境差分が少なく、環境による問題を減らすことができます。
作成したDockerイメージを他の人にも渡して使ってもらうことで、各自の環境のバージョンずれ防止や、開発環境準備の短縮化にもつながります。開発環境の準備で、説明不足や手順ミスで、丸一日かかったとなってしまうのはもったいないですよね。私自身も、開発環境からDockerを使っていて、新規メンバ参画時のコスト削減や、環境依存問題を減らせて、役立っています。
また、クラスタ構成を構築する場合も、Dockerイメージがあれば、それを起動する名前(コンテナ名)などを変えるだけで、
複数の環境(コンテナ)を起動できるので、一から手順に沿って環境を作る作業もなくなり、クラスタ構成を構築するのも容易になります。これは、コンテナを管理するオーケストレーションツールを使うことで、より運用が楽になります。
最近では、オーケストレーションツールとしてKubernetes(https://kubernetes.io/)が注目を浴びていて、Dockerでネイティブでサポートされることになり、話題にもなりました。
さらに、コード化したもの(Dockerfile)を構成管理し、それをCIツール(JenkinsやCircleCIなど)で、ビルド(Dockerイメージの作成)、デプロイ(コンテナの起動)、環境のテスト(Serverspecなど)、画面試験(Seleniumなど)を毎日実行すれば、環境面の確認も含めて安心して開発を進められるようにもなります。このサイクルを回せると、いざ環境を構築するとなった際に「アプリを動かすのに何のパッケージが必要なの?」と慌てることも減らせて、開発・リリースサイクルも安定してくると思います。
このように、Dockerを使うことで安定した開発を進めたり、リリースサイクルの改善にも役立つので、ぜひ使ってみていただきたいと思っています。
説明ばかりでは退屈だと思いますので、実際にいくつかコマンドを実行して動かしてみます。(今回は、実行例のみで、インストールや詳細は次回以降に説明していく予定です。)
Dockerコンテナ実行例
Dockerのイメージ(仮想マシンでいうところのVMイメージ)は、Web上のDocker Hubで公開されています。そこからDockerイメージを取得してくれば、すでに必要なミドルウェアなどがインストールされた状態のDockerコンテナを起動でき、すぐに使用できます。
例として、NginxのDockerイメージを使ってWebサーバーを立ててみましょう。Dockerがインストールされた環境で以下を実行します。
docker run --name some-nginx -d -p 8080:80 nginx
このコマンドを打つだけで、
- Nginxがインストール済みのDockerイメージを取得
- 取得したDockerイメージでコンテナ起動
- コンテナの中でNginx起動
を実施してくれます。
あとはブラウザで「http://<IPアドレス>:8080/」を開けば、Webサーバーにアクセスできます。必要なファイルや設定を含めたDockerイメージを作っておけば、上記のコマンドくらいで、必要なWebサーバを起動することができます。
他の例として、WordPressのコンテナを動かしてみましょう。
docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:5.7
docker run --name some-wordpress -e WORDPRESS_DB_PASSWORD=my-secret-pw --link some-mysql:mysql -d -p 8080:80 wordpress
これでWordPress環境が起動しました。あとはブラウザで「http://<IPアドレス>:8080/」とアクセスすれば、WordPressが使えてしまいます。(以下では各種設定の画面は省略しています。)
このように、数コマンドで簡単にWebサーバーや、あるアプリが動いた環境を構築できてしまいます!
ツールがインストール済みのDockerイメージはいろいろと公開されています。例えば、CIツールのJenkinsや、プロジェクト管理ツールのRedmineなどもDockerイメージとして公開されており、上記と同程度のコマンドで起動することができます。そのためDockerを使えば、ちょっと気になったツールを上記のようにすぐ使用できるので、とても便利に感じています。(公式として公開されているDockerイメージと、個人が公開しているものがあるので、どれを使うかは注意が必要です。)
上記は一般に公開されているDockerイメージを使いましたが、自分でDockerイメージを作成することができます。それを他の人にも取得してもらえば、簡単に同じ環境を作ることができるのです。
また、上記はデータベースとしてのMySQLコンテナとWordPressコンテナが分かれています。そのため、「WordPressのバージョンを上げたい」といった場合には、WordPressの新しいバージョンのコンテナをもう一つ起動し、問題なければ、古いWordPressコンテナを削除する、という段取りを踏めば、切り戻しなどもしやすいため、バージョンアップなどの対応も敷居が下がるのもよいと思ってます。
Dockerとは何か
世の中のほとんどのソフトウェアは1人のプログラマの力で開発されているわけではなく、複数の開発者が協力して作成していますが、複数人でアプリケーション/システム開発を円滑に進めるにはどうしたら良いでしょうか。
最も重要なプログラムコードの共有には、今日Gitというバージョン管理の仕組みが使用され、自分の書いたプログラムコードをチームで共有するためのサービスとしてGithubやBitbucket、Gitlabなどがあります。
ですが、プログラムコードを円滑に共有することができたとしても、そのプログラムの実行環境を共有しないとプログラムが正常に動作しないということは多々あります。
開発者が使用しているコンピュータはMac OSX、Windowsなどの違いがあったり、人によって様々なソフトウェアが入っているなど、実行環境を共有するのは容易ではありません。
そこで、仮想化によってフラットな仮想マシンを作成し、その仮想マシンを作成する設定などを共有することで実行環境を共有することが考えられますが、従来のホスト型仮想化では、動作がとても重く、共有するためのファイルも軽量とは言えませんでした。
一方で、Dockerのコンテナ型仮想化は、軽量な動作と環境ファイル共有を実現しています。
プログラムの実行環境を管理するための仕組みとしてDockerがあり、それを共有するための仕組みとしてDockerHubなどのサービスがあります。
Dockerを使用することの一番のメリットは「ソフトウェアの実行環境を、複雑なアーキテクチャであっても、Dockerを使って管理することで、簡単にどんなマシンにでも共有できる」という点です。
以降で、Dockerの各要素について見て行きます。
⓪ Docker Engine
Dockerを利用するための常駐プログラム
Docker for mac、Docker for Windows、Docker ToolboxなどのソフトウェアをPCにInstallすることで、常駐プログラムとしてDocker Engineが動作し、Dockerを利用することができるようになります。
① イメージ(Image)
コンテナ(=アプリケーションの実行環境)を起動するのに必要な設定ファイルをまとめたもの
「Imageはコンテナの元であり、Imageからコンテナを起動する」と理解すると良いと思います。
DockerではこのImageを共有することで、様々なマシンで同じコンテナ(実行環境)を動作させることができるのです。
Tag
Dockerのimageにはtagという概念があります。
tagとは「imageのversion」のことです。
例えば、以下のDocker Hubの画像のようにnginxイメージには 「1.14-perl」や「alpine」のような様々なtagが存在し、どのversionを使用するかを選択できます。
tag名を何も指定しないと 自動的に「latest」タグが使用されるようになっています。
image名とタグ名を : で区切って
nginx:latest
nginx:1.14-perl
のように表されます。
imageの構造
イメージは以下のような2つの特徴を持ちます。
- layer構造になっている
- 一度作成されたimageは編集不可能 (読み取り専用)
イメージはレイヤー構造になっており、1つのミドルウェアをインストールするにつき、1レイヤーが重なっていくイメージ(1インストールコマンドで1レイヤー積み重なるという認識)
また、imageのレイヤーはRead onlyであり、編集不可能で、imageからコンテナを起動した際に作られるコンテナレイヤーのみが編集可能となっています。
これは、imageからコンテナを起動して、そのコンテナ内で何らかのミドルウェアをインストールした場合に、それがコンテナレイヤーに保存されるということであり、そのコンテナから再びimageを生成(commit)することもできるようになっています。
Imageを用意する
ローカルマシンに取得しているImage一覧は
$ docker images
で確認することができます。
さて、コンテナを実行するには、そのコンテナの元となるimageを用意しなくてはなりません。
imageを用意する方法には
- 他人が作ったimageを取得する(主にDocker Hubから)
- 自分で作る(他人のimageを改良する)
があります。
以下に順番に見て行きます。
1. Docker Hubからのimage取得
Docker Hubには様々なミドルウェアが入ったImageが公開されているので、自分が使用したい環境に応じて以下のコマンドでImageを指定して取得します。
$ docker pull イメージ名 #Docker Hubなどからイメージを取得
2. Dockerfileからのイメージ作成
Dockerfiile という名前のtextファイルを作り、その中にimage build(image作成)に関わる設定を記述して、そのDockerfileからイメージを自作します。
様々な記述ができますが、ここでは基礎的な以下の関数のみを紹介します。Dockerfile
FROM イメージ名:タグ名 #どのimageを元にimageを作成するか
RUN パッケージ等インストールコマンド #ここに記述したコマンドを実行してミドルウェアをインストールし、imageのレイヤーを重ねる
CMD コマンド指定 #コンテナが作成された後で実行するコマンドを指定する
$ docker build -t ビルドしたイメージに付けるイメージ名 .
-tオプションで作成したimageに名前をつけます。
また、image作成する際にdocker daemonに転送されるファイルの範囲をビルドコンテキストといい、イメージ名の後に指定します。(今回は . [カレントディレクトリ])
buildコマンド実行時に設定として読み込むDockerfileはデフォルトではビルドコンテキスト上のDockerfiile
が読み込まれるようになっているので、ビルドコンテキストにDockerfileを置いておく必要があります。
※ 別途-f Dockerfile名
で指定することもできます。
一度buildしたimageを、Dockerfileの変更無しに再びbuildする際にはbuild cacheが効いて、以前buildした情報を見に行くようになっているので、RUNにupdateコマンドなどを記述していたとしても普通にbuildし直した場合は、そのコマンドは実行されないことになる点に注意が必要です。
cacheを無効にしてbuildする場合は
$ docker build —no-cache -t docker-whale
とします。
② コンテナ
imageを用意したら、そのイメージからコンテナ(=アプリケーションの実行環境)が起動できます。
imageからコンテナの起動
$ docker create --name コンテナに付ける名前 イメージ名
でイメージからコンテナを作成
$ docker start コンテナ名
でコンテナを起動
これまで見てきた指定したイメージをDockerHubから取得して、コンテナを作成・起動するコマンドとして
$ docker run イメージ名
があります。
docker pull :DockerHubからイメージを取得
docker create :取得したイメージからコンテナを作成
docker start :作成したコンテナを起動
を同時に実行するコマンドがdocker run コマンドです。
コンテナの操作コマンド
コンテナ一覧を確認
$ docker ps
で現在実行中のコンテナを表示
$ docker ps -a
で現在存在しているコンテナ一覧を表示
コンテナの詳細を確認
$ docker inspect コンテナ名
で指定したコンテナの詳細情報を表示
コンテナの作成
$ docker create —name コンテナにつける名前 -it イメージ名 /bin/bash
-i はコンテナの標準入力を取得して双方向接続するオプション
-t はコンテナ内にTTYを割り当てるオプション
コンテナでシェル実行をして、フォアグラウンドで実行状態にしておきたい場合に -itの組み合わせで使われる
これをつけないとシェルがすぐに終了してコンテナが停止してしまう
コンテナの起動
$ docker start コンテナ名
でコンテナを起動
コンテナの一時停止
$ docker pause コンテナ名
で、コンテナを一時停止できる
コンテナの再開
$ docker unpause コンテナ名
でコンテナの一時停止を解除できる
コンテナの再起動
$ docker restart コンテナ名
でコンテナが再起動される
コンテナの停止
$ docker stop コンテナ名
でコンテナが停止
コンテナが終了後、そのままローカルに残っている状態はExitとなることに注意が必要です。
使わないコンテナは削除しておかないとハードディスクが圧迫されます。
コンテナの削除
$ docker rm コンテナ名
でコンテナを削除
$ docker rm -f コンテナ名
で強制削除
起動中のコンテナのシェルへ接続
接続方法はattachとexecの2つがあります。
$ docker attach 起動中コンテナ名
起動中のコンテナがシェルを実行している場合は、シェルに接続できるが、Deamonしか起動していない場合にはDeamonの標準入出力に接続されてしまうことに注意して下さい。
attachで接続して、exitで抜けると起動中のコンテナが終了してしまうのが特徴です。
起動時に -itフラグをつけている場合は、control + p, control + qで抜けるとコンテナは終了しません。
$ docker exec -it 起動中のコンテナ名 /bin/bash
exitで抜けることができ、抜けてもコンテナが停止することはないのが特徴です。
コンテナからイメージを作成
$ docker commit コンテナ名 image名:タグ名
コンテナの状態を、指定した「image名:タグ名」でイメージとして保存するコマンド
$ docker history イメージ名
で、そのイメージの変更履歴を確認できますが、docker commitでイメージを作成すると、コンテナの内部でどんな変更を加えたのかはどこにも記録として残らず、とても使いにくいimageになってしまう点に注意が必要です。
そのため、基本的にはDockerfileからimageに変更を加えてイメージ自作をするべきです。
ここまでの全体像
③ Docker Hub (Container Registry)
Docker Hubでのimage共有
Githubと殆ど同じです。
Dockerhubのアカウントを持っている必要があります。
手順としては
- Docker hub上でリポジトリを作成する
- ローカルでimageを作成
- ローカルのコマンドラインで以下のコマンドを使ってdocker hubへログイン
$ docker login
4.以下のコマンドでpushしたいimageにタグ付け
$ docker tag <pushしたいimage名> <docker hub ID>/<新規image名>:<タグ名>
5.以下のコマンドでローカルのimageをリモートリポジトリにpushする
$ docker push <docker hub ID> / <image名>:<タグ名>
ここまでの全体像
前編では、仮想化の解説から始め、
⓪Docker Engine
①Image
②コンテナ
③Container Registry (DockerHub等)
という4つの要素について見て行きました。
これらをまとめると、以下の図のような全体像になります。