武井(Twitter:@noriyukitakei)です。タイトルが少々長いのですが、今回はこれからコンテナ、Docker、Kubernetesを始める人のための、入り口的なブログを書こうと思っております。コンテナとかDockerとかKubernetesって言葉は聞いたあるけど、なんとなくぼんやりとしたイメージを持っている人が、このブログを読んで頂くことで、少しでもそのイメージがクリアになればいいなと思っております。本ブログではコンテナ、Dockerの細かいオペレーションには触れません。まとめコンテナってなに?最近、「Kubernetes」という言葉をよく聞くと思います。従来の仮想化とは異なるアプローチのシステム構築方法であり、使い方によっては、開発工数や運用工数の削減に大きく貢献するのですが、そのKubernetesの基礎技術としてあるのが「コンテナ」です。この「コンテナ」というのがなかなかにイメージがつかみにくい代物です。以下のように解説されていることが多くあります。コンテナとは、プロセスの実行空間を隔離するための技術である。うーん、わかったような、わからないような、、、。言ってしまうとOSの中にOSが立てられます。以下のようなイメージですね。図にもありますが、コンテナと似たような概念に「仮想化」というのがあります。コンテナを説明する前にまず仮想化について説明をして、仮想化との違いを明確にすることで、コンテナの核心に迫りたいと思います。仮想化について仮想化という技術にては、ご存じの方が多いと思いますが、ここでおさらいしておきます。下図が仮想化のおおざっぱなイメージにございます。ホストOSというのがパソコンに搭載されているOSです。WindowsとかLinuxです。Boxといった仮想化ソフトウェアがあり、その上にさらにOS(ゲストOSと呼ばれることが多いです)が稼働します。ゲストOSの上でプロセスが稼働します。このプロセスは、例えばExcelが一つ起動すると、一つのプロセスが起動する、つまり1アプリケーション=1プロセスと考えて下さい。この方式はもう長年実績もありますし、イメージがしやすいと思います。先の図にコンテナの場合を加えてみました。プロセスという構成にになります。(コンテナで区切られた)プロセスとなります。ゲストOSが不要になります。余計なものがいらなくなった分、なんかすごいような気がしませんか?例えば、仮想化の場合にApacheを起動する場合を考えてみます。Wareなどの仮想化ソフトウェア上のゲストOSを起動して、そのゲストOSの起動完了したら、Apacheのプロセスを起動して、初めてApacheが稼働します。ゲストOSの起動を待つ分、稼働までは時間がかかります。コンテナの場合には、仮想化ソフトウェアもゲストOSもありません。高速にプロセスを起動出来ます。プロセスが起動するためには、必ずOSが必要です。結論から言いますと、コンテナ内のプロセスは、ホスト内のOSを使います。正確にいうと、ホスト内のOSのカーネルを使うという言い方の方が正しいかも知れません。先の図をもうちょっと詳しく書いてみます。OSの基本的な構造からご説明しますと、OSは以下の2つから成り立っています。コマンドやライブラリカーネル「コマンドやライブラリ」は、Linuxで言うところのlsコマンドや、/lib配下のライブラリ群です。Windowsでは、dirコマンドやWindowsフォルダ配下のDLL群になります。「カーネル」はコンピューターの基本的な操作を行う機能を格納したライブラリ群のようなもので、先程の「コマンドやライブラリ」はこのカーネルの中にあるライブラリ(システムコールと呼んだりします)を呼び出します。lsコマンドはC言語で書かれているのですが、その中でgetdentsというシステムコールを呼び、ファイルのリストを取得しています。プロセスは、OS内のコマンドやライブラリを呼び出し、そのコマンドやライブラリは、カーネル内のシステムコールを呼び出しているというわけです。話は長くなりましたが、コンテナの場合は、先の図の通り、コンテナ内のプロセスがコンテナ内のコマンドやライブラリを通して、ホストOSのカーネルを使っているわけです。ところで、先の図の一番右側にあるプロセスはホストOS上にあるプロセスですが、こちらも(当たり前ですが)ホストOS内のカーネルを使っています。いうことは、ホストOSから見れば、ホストOS上で稼働しているプロセス(=アプリケーション)も、コンテナ上で稼働しているプロセスも全く同じ扱いなのです。先程から上図でも出ている「コンテナ」ですが、これについてはまだ説明をしておりません。次章で説明をしていきます。ホストOS上で複数のアプリを動かす場合では、コンテナの説明をする前に、ホストOS上で以下のような2つのアプリケーションを同時に動作させる場合を考えてみます。ファイルのパスは同じ、app.phpの実行権限もwww-data(id=33)同じです。違うのは、app.phpの中身で、一方はhogeと表示、もう片方はfugaと表示しています。このアプリを一つのホストOSで同時に動かす方法は、仮想化であれば容易に想像が出来ます。仮想化で実現する場合は、仮想化ソフトウェアの上に、ゲストOSを2つインストールして、それぞれのOS情報で、hogeを表示するアプリ、fugaを表示するアプリを動作させればいいだけです。コンテナでは同実現すればいいでしょうか?コンテナには仮想化ソフトウェアもなければゲストOSもありません。先程から申し上げていますように、コンテナはホストOSのカーネルを共有します。基本的に上記の2つのアプリ(≒プロセス)は、同じOS上で動くものですので、同じパス・ファイル名を取ることも出来ないですし、同じUIDを取ることも出来ません。コンテナではこれを実現しています。そのための重要な概念がnamespaceというものです。コンテナで超重要な概念「namespace」とは?同じホストOS上で、仮想化ソフトウェアを使わずに、複数のアプリケーションを同時に動かす技術として重要なのが「namespace」というものです。「namespace」という機能は、2006年あたりにLinuxカーネルに実装された技術であり、最新の技術ではありません。namespaceを使うと、プロセス、ファイル構造、ユーザーID、グループIDなどを一つのOSの中で分離することができます。以下のようなイメージです。AとBという、2つのnamspaceがありまして、その中では全く独立したファイル構造やプロセス空間を持つことが出来ます。プロセス空間については、実際には、ホストOS上で動作しているプロセスIDとコンテナ上で動作しているプロセスIDをマッピングしているテーブルがあり、ホストOS上ではpidが2だけどコンテナ上ではpidが1に見えているということになります。namespaceという技術を使うと、このようなことが出来てしまうのです。コンテナのコア技術はこのnamespaceにあると言っても過言ではありません。このnamespaceで区切られた部分が「コンテナ」と呼ばれるものです。namespaceを使うと、プロセス空間やファイルシステムを一つのOSの中で分離できるので、namespaceで区切られた部分は全く異なるOSのように振る舞うことが可能です。先程のhoge、fugaを表示するアプリを一つのホストOSを使って実現する場合、以下のようなイメージになります。2つのnamespaceを作成して、その中にアプリケーションを配置します。namespaceが異なれば、先程申し上げましたように、プロセスID(www-data)が同じでもOKですし、同じパス・同じファイル名のファイルで内容が異なるものでも、一つのホストOS上に存在することができます。ところで、このnamespaceという言葉、どこかできいたことありませんでしょうか?C#やJavaといったアプリケーション開発言語でよく出てきます。C#ではそのまんまnamespace、Javaではpackageと呼ばれたります。JavaやC#で出てくるこれらの概念も、コンテナのものと考え方は同様で、一つのアプリケーションの中で同じ名称のものを使いたいときに活用します。Javaを例にあげますと、機能Aと機能BというパッケージでUser.javaという同じ名称のクラス名を使いたいときには以下のように実装します。{...}話は逸れましたが、もし、アプリケーション開発を行っている人であれば、コンテナで利用するnamespaceは、アプリケーション開発で利用するnamespaceやpackageと似たような概念であると捉えていただくとイメージしやすいかも知れません。namespaceを作ってみよう!!先程から頻繁に出ています「namespace」ですが、説明だけですとイメージが沸かないと思いますので、実際にnamespaceを作ってみます。ここではnamespaceを使ってプロセス空間を分離してみます。普通にpsコマンドを実施しますと、たくさんプロセスが表示されます。[rcu_sched]............ここで新たなnamespaceを作成して、プロセス空間を分離してみます。namespaceの作成にはunshareコマンドを用います。psunshareコマンドを使ってnamespaceを作成して、そのあとにpsコマンドを実施するとプロセスの数がすごく少なくなったのがわかります。先程のunshareコマンドは、新たなnamespaceを作成して、そのnamespace上でbashというプロセスを動かしますとという意味です。新たなnamespace上ではbashのプロセスしか動いていません。いかがでしょうか?これはプロセス空間だけ分離するという簡単な例でした。現場で利用するコンテナは、プロセス空間のみならず、ファイルシステムやネットワークなど色々なものを分離しなければいけません。namespaceだけではなくコマンドやライブラリも必要プロセスをコンテナ上で稼働させるためには、namespaceを作成するだけでは動きません。先程ご説明したようにOSの動作に必要なコマンドやライブラリが必要になります。ApacheでSSLの処理を行うプロセスが稼働するためには、OpenSSLのライブラリが必要になります。他にも必要なライブラリやコマンドはたくさんあります。よって、先程unshareコマンドで作成したような、プロセス空間を分離するというものではなく、より実用的なコンテナを作成するには、以下のことを実施しなければなりません。コマンドやライブラリの取得プロセス空間の分離ネットワーク空間の分離ファイルシステム空間の分離などなどその他もろもろこれを実現するためには、相当量のコマンドを発行しなければなりません。簡単にコンテナを作成したいですよね。Dockerってなに?そこでDockerです。namespaceの作成とか、コマンドやライブラリのダウンロードなど、全てDockerコマンド一発で実現出来ます。言ってしまうとDockerはnamespaceなどコンテナの作成に必要なたくさんの複雑なコマンドをラップして、簡単にコンテナを作れるようにしたものです。CentOS7に必要なコマンドやライブラリ(以降、これらのコマンドやライブラリのことをOSイメージと呼びます)を取得して、そのコンテナの中でbashを実行するDockerコマンドは以下のとおりです。/bin/bashたったこれだけで、実現出来てしまうのです。Wareなどの仮想化ソフトウェアを使ってCentOSを立てようとすると、もっと大変な手順を踏むことになりますので、Dockerがいかにすごいかがわかると思います。Hubについてところで、先程のコマンドを今一度見てみたいと思います。Hubという、インターネット上に公開されているリポジトリから取得してきています。Hubには、CentOSやDebianなどのOSイメージがアップされており、先程のdockerコマンドを通じて取得する仕組みになっております。イメージにするとこんな感じです。Hubには、複数のOSの、複数のバージョンのイメージがあります。そこからdockerコマンドで指定してきます。コンテナのカスタマイズ先の図でダウンロードしたCentOS7は、OSの動作に必要な最低限のものしか入っておりません。Apacheを動作させたいという用途は往々にしてあると思います。そんな場合は「Dockerfile」というものにモロモロ書きます。ここでCentOS7にApacheをインストールしたコンテナをDockerfileで作ってみたいと思います。以下のようなDockerfileを作成します。httpdFROMでは、ダウンロードしたいOSのイメージを指定します。RUNでは、FROMでダウンロードしたコンテナの中で実施したいコマンドを指定します。httpdと定義します。Dockerfileのあるディレクトリで、以下のコマンドを実行します。web.これだけで、Apacheがインストールされたコンテナが出来上がります。今までの一連の流れをイメージにすると以下のような感じになります。Hubはインターネットに公開されて、誰でもダウンロード出来ますが、その一方で社内専用のプライベートなDockerリポジトリも作ることが可能です。その構築方法は、オンプレミスのサーバーにインストールしてもよいですし、Azureなどのパブリッククラウドで提供されているものを使ってもOKです。プライベートリポジトリの主な用途は、先程の章でカスタマイズしたコンテナを社内だけで限定公開したいときです。Hubのようなものに上げるのは抵抗があります、、、。本章でプライベートリポジトリの利用イメージをご説明致します。pushコマンドでプライベートリポジトリにアップロードします。プライベートリポジトリにアップロードされたイメージを開発者みんなで共有して、開発者のPCにコンテナを作成することが出来ます。なんでコンテナを使うの?そもそもですが、なんで従来どおりの仮想化ではなくて、コンテナを使うのでしょうか?色々と理由はありますが、仮想化との比較という点でいいますと、理由は以下の1点です。コンテナはカーネルを含まず軽量なのでダウンロードが速い。ここで最初の方にご紹介した、仮想化とコンテナの比較の図を再び上げたいと思います。コマンドやライブラリですが、コンテナ上でOSを動作させるために必要なものは、コマンドやライブラリのみです。コンテナではカーネルの部分をホストOSと共有するので、カーネルは必要ありません。カーネルが必要ない分、コンテナのほうが容量が小さくてすみます。これが仮想化に比べてコンテナが大きく勝っているところの一つであります。この可搬性のよさがどんなときに活きて来るのでしょうか?ここで、開発環境の構築を例に考えてみます。エンジニア全員が定められた手順書に従って、エンジニアのPC上に構築されたVMに開発環境を構築したとします。何らかの理由でこの開発環境に変更が必要になったとします。仮想化では、変更した内容を記載した手順書を配布して、開発環境の変更を依頼します。この場合、誰かが間違えてしまう場合が考えられます。みんな手順書通りにやってくれればいいのですが、やっぱり人間なのでミスもします。そんなとき、システム管理者は間違えちゃった人に対して個別に対応しなければいけないので、大変です。VMのイメージを配ってみたらどうでしょうか?この場合も、VMのイメージ自体がとても大きいのでネットワークの帯域を圧迫したり、遅かったりで大変です。コンテナを使えば、これらの問題は解決します。システム管理者が、変更になった開発環境のイメージをプライベートリポジトリに上げて、そしてエンジニアたちにはそのイメージから自分たちのPCに変更後の開発環境のコンテナを生成してもらえばよいのです。これであれば手順書によるミスも生じませんし、コンテナのイメージは軽量なのでダウンロードもサクサクです!!こんな利用用途でコンテナは使われたりします。他にも色々なメリットはありますが、やはり開発環境構築を円滑にできるというのは、コンテナの大きなメリットと思います。まとめいかがでしたでしょうか?これからコンテナやDockerを始めるけど、なんとなくコンテナというもののイメージがぼんやりしている方が、本記事をご覧いただくことで、そのぼんやりなイメージがクリアになって頂ければ幸いです。次回は、Dockerコマンドの使い方について書きたいと思います。雑誌等の執筆依頼を受付しております。役に立たなかった2人がこの投稿は役に立ったと言っています。コメントをキャンセルメールアドレスは表示されません。Reserved.本サイトに掲載されている社名、製品名、サービス名等は各社の商標または登録商標です。プライバシーポリシーお問い合わせ。