Dockerとはどういったものなのか、めちゃくちゃ丁寧に説明してみる

お詫びと訂正

おまけ2 の内容に関して誤りの情報を記載していたので、修正いたしました。(2020/6/6 22:55)
誤った情報を流布してしまい申し訳ございませんでした。

またコメントで大変丁寧にご指摘&アドバイスをくださった@souchi00さん、ありがとうございます🙇‍♂️

この記事はこんな人向け

  • プログラミング初学者
  • Dockerがどんな技術かよくわかってない人
  • フロントエンドとバックエンドの違いがわからない人
  • ウェブサイトの開発がどういうものかわかっていない人

はじめに

最近プログラミングを学び始めたばかりの人向けにtwitterで情報発信を始めたのですが、よく聞く単語だけどDockerって何? 何ができるの? という声を目にする機会が多かったので, 今回は Docker について紹介します。

いきなりDockerの仕組みとメリットを書いても初学者の方にはピンとこない気がしたので、初学者の多くの方が目標としているウェブサイトの作成工程の中で、Dockerが大活躍するサーバーのデプロイに絡めて解説していきたいと思います。

そもそもサーバーとはなにかフロントエンドとバックエンドとはデプロイとは
と言った関連ワードに関しても解説しており、たくさん寄り道をした分ボリュームのある記事になってしまいましたが、学びの多いものになっていると思いますので最後までお付き合いいただけると幸いです🙏

(この記事はdockerがどういったものか、概要をざっくり説明するもので、command等はほとんど出てこないので悪しからず)

サーバーとは

ウェブサイトを自分で作れるようになってエンジニアとして働きたい! フリーランスで稼ぎたい! という方は多いかと思いますが、そもそもウェブサイトとはどういったものでしょう?(何を作ればいい?)

皆さんなんとなくリンクをクリックしたりブラウザ(ChromeやIE)の検索バーにurlを入力してウェブサイトを見ていますが、その裏では一体何が起きているのでしょうか?

urlとはUniform Resource Locatorの略で、文字通りリソースの場所を表すものです。

ここで言うリソースとは, htmlやcss, javascript, webページ中で表示したい画像など、webページを表示するのに必要な材料を表します。

皆さんがブラウザでurlを入力すると, ブラウザはその "urlが表す場所にあるリソースをください" というリクエストをインターネットに送りだします。

このリクエストを受け取って必要なリソースを返送してあげるのがサーバーです。

返送されてきたリソース(レスポンスと呼ばれます)はブラウザによって解釈され、みなさんが今見ているような画面として出力されます。

image.png

ちなみにサーバーの仕事は、リクエストに応じてただ事前に用意してあったリソースを返すだけではありません

例えばユーザーに似ている芸能人を機械学習で算出して教えてあげるサイトを作ったとすると、ユーザーが画像をアップロードするまで似ている芸能人を計算することはできません。

なので、リクエストが来てからその場で計算したり、機械学習用の別のサーバーに計算を依頼してユーザーに返す画像を決定します。

またデータベースと呼ばれるデータを管理するためのサーバーに、ユーザーの情報を登録してもらったり、レスポンスに必要なユーザー情報を引き出すのもサーバーが行う操作です。

このようにサーバーの役割は非常に広範囲に渡り、また役割ごとに異なる名称で呼ばれることが多いです。(データベースや機械学習サーバーなど)

image.png

話が少し脱線してしまいましたが、ウェブサイトとは

ページを表示するために必要なリソース群と、ユーザーからのリクエストに応じて適切なリソースを返してくれるサーバーのセット

と言えそうです。

ウェブサイトのイメージ
image.png

フロントエンドとバックエンド

webサイトを作るときは、各ページを表示するのに必要なリソース群リクエストに応じて適切なリソースを返すサーバーの両方を用意する必要があることがわかったと思います。

これらは分離して開発可能で、一般的にhtmlやjavascriptなどのwebページの表示に必要なリソースを開発する仕事(スマホアプリのUI開発なども)をフロントエンド開発、サーバープログラムを開発する仕事をバックエンド開発と呼びます。

ユーザーから見た時にユーザーにより近いところ(ユーザーの端末上)で動くので、htmlやjavascriptなどはフロントエンド、その対比でサーバーはバックエンド、と覚えるといいでしょう。

主にユーザーが目にするUIを扱いたい方はフロントエンドを、それ以外の裏側の仕組みを扱いたい方はバックエンドを勉強するといいでしょう。(それぞれどんな言語があるのかについては割愛します。)

デプロイ

さて、めでたく皆さんのPCの中でサーバープログラムとユーザーに渡すためのリソースが用意できました、サイトの完成です!

が、せっかく作ったサイトもこのままでは他の人に見てもらえません。

他の人がアクセスできる場所(主にインターネット上)に公開する必要があるのです。
ユーザーがサイトやアプリなどを利用可能な状態にする作業のことを、デプロイと呼びます。

Dockerはこのデプロイ作業時に発生しうる様々な問題点を解消してくれるのです。

ここからはデプロイの歴史を見ていきます。

デプロイの歴史 (@souchi00さんにコメントでご教授いただき加筆いたしました。 2020/06/06/23:30)

ひと昔前までは(こちらの記事によると1990年代頃までは)サーバーと言うと大型マシン一台がすべてのリクエストをさばいていました。(そもそもこの頃はインターネットは普及しておらず、社内システムがメイン)
しかし、これだとPCメーカーによる囲い込み(簡単に違うPCメーカーに乗り換えられなくなる)やその結果の高コスト、柔軟性や拡張性欠如の問題がありました。

その後技術が進歩し、小型PCの性能がup & 価格も安くなってくると、小型PCをつなぎ合わせて、システムや機能を分散配置する構築手法が広がりました。

この大型機から小型機を組み合わせた分散システムへ移行することはダウンサイジングと呼ばれ、当時のトレンドとなりました。
これ以降は、小型PCに適材適所に環境を構築することが主流となっていきます。

しかしこの変化は新たな別の問題を発生させました。

管理の複雑化・リソースの無駄遣い

まずサーバーを構成するPCが増えると管理と運用が大変なのは、想像に難くないですよね。
たとえばもし100台の小型PCを組み合わせる運用を考えた場合、当然100台分の環境構築や設定が必要になります。

一度設定してしまえば終わりというものでも有りません。プログラムのアップデートが入るとまた100台分プログラムをインストールし直す必要があります。(そして数が増えるほどミスが発生し、アップデートし忘れたサーバーなどが出てくる)
これは大変な手間ですね。

また、この複数のPCが常に100%稼働しているわけではなく、時間によっては遊んでいる(リクエストが全然来ない)PCが沢山出てきます

「暇なら一台のPCでたくさんのサーバープログラムを動かせばいいじゃん」とお思いになる方もいらっしゃると思います。

もちろんひとつのPCで複数のプログラムを同時に実行することは可能なのですが、いくつか懸念点が出てきます。

まずリソース(CPUやメモリなど)を共有するため、単純に各プログラムの処理速度が遅くなります。

沢山の人が同じ場所に詰めかけると渋滞が起こりますよね?
あれと同じでメモリなどに複数のプログラムが同時にアクセスしようとすると、待ち時間が発生するようになります。

またセキュリティや可用性(サーバーが安定して稼働し続ける能力のこと)に関しても気になる点があります。

例えばある1台のPCが10個のサーバープログラムを動かしていたとします。
仮にこのPCが悪意のあるユーザーから攻撃を受け、PCの管理者権限を乗っ取られてしまった場合、この10個のサーバープログラムでやり取りされたすべての情報が攻撃者に渡ってしまうことになります。

image.png

1つのサーバープログラムで100人分のユーザーのリクエストをさばいていた場合、100×10=1000人分の個人情報が流出することになります。

もしこれを10台のPCで分散して実行していたなら100*1=100人分の個人情報の流出ですむわけです。(十分アウトですが)

また攻撃だけではなく、プログラムのバグや大量のリクエストによる処理落ちでPCがフリーズした際、同じPCで10個のプログラムを実行しているとその全てが停止してしまうことになります。

実行環境の多様化

またPCの数が増えるにつれ、システムを構成する環境が複雑かつ多様化しました。
これにより各PCの環境の違いにも気を使う必要が出てきます。

開発時に用いたPC上では正しく動くプログラムでも、実行環境(OSやライブラリのバージョン)が異なるPC上では動かないことが多々あります。

オペレーティング・システム(Operation System、OS) ・・・ アプリやデバイスを動作させるための基本となるソフトウェアのこと。
ソフトウェア(みなさんが開発してるプログラムなど)とハードウェア(CPUやメモリなどの器械)の連携を司る中枢的な役割を果たす。
プログラムを実行する際、プログラムの実行に必要なCPUやRAMメモリなどがOSによって確保、割り当てられる。
OSの助けがないとプログラムはほぼ何もできない。(OSの機能を使わないとプログラムは標準出力機構にアクセスできないので、Hello Worldを画面に出力することさえできません!)
有名どころを上げるとwindowsやmacOS、Linuxなどが該当する。

実行環境 ・・・ 作成したプログラム、アプリケーションを実行するための環境のこと。
OSの種類や、ライブラリのversion、環境変数などが該当する。
上述したとおり実行環境が異なると、同じプログラムでも動かなくなったりする。

プログラムはOSの機能に依存しているのにそのOSの種類が開発時と異なったら、動かなくなるのはなんとなく想像つきますよね。

異なる環境でプログラムを動かそうとすると...
image.png

なので、プログラムの開発時に使用するPCの環境はサーバーとして使用するPCの環境に合わせる必要がありました。

仮想化とは

この悩みを解決してくれるのが、仮想化という技術です。

仮想化とは、ソフトウェアによって複数のハードウェアを統合し、自由なスペックでハードウェアを再現する技術で、限られた数量の物理リソース(CPU、メモリ、ストレージ、ネットワーク等)を、実際の数量以上のリソース(論理リソース)が稼働しているかのように見せかけることです。

引用元

  • CPU(Central Processing Unit) ・・・ コンピュータの制御や演算や情報転送をつかさどる中央演算処理装置。簡単に言うとCPUの性能によってどのくらい早く計算できるか(プログラムを動かすことができるか)を表す。CPUの性能指標について詳しくはこちら

  • メモリ(RAM、Random Access Memory) ・・・ データやプログラムを一時的に記憶する部品で、高速に読み書きできます。 プログラムやアプリケーションはこのメモリの上に読み込まれ、実行されます。簡単に言うとメモリが大きいほど同時にたくさんのアプリケーションを動かせます。(動画編集しながら、powerpointいじったり、ネットサーフィンしたり...etc)
    PCの電源を切るとメモリ(RAM)上に保持されていたデータは全て消えます。

  • ストレージ ・・・ データやプログラムを永続的に記憶する部品で、ストレージが大きいほどたくさんのデータを記憶することができます。(写真を100万枚保存できる、音楽を1万曲保存できる、など)使用されていないデータやアプリケーションは普段ストレージに保存されており、使用するとなった時にメモリ(RAM)にコピーされアプリケーションが実行されます。ストレージの種類としてはHDDやSSDなどがあります。
    PCの電源を切ってもストレージに保持されているデータは消えません。

実際には1つしかないのに複数あるように見せかける ということで、仮想化技術と呼ばれているのですね。(蛇足ですがメモリやストレージは一つのPCに複数搭載することもできます。複数搭載されているメモリやストレージを仮想化技術によって1つのメモリやストレージとして扱うこともできます。)

仮想マシン

最初に流行となった仮想化技術は仮想マシンというものでした。
これはPC上に仮想的なPCを立ち上げるという技術です。

例えば仮想マシンを用いると、1台しかPCが存在しないにも関わらずあたかも4つのPCが存在しているように振る舞うことができます。

image.png

また、この際に仮想マシンが使用するOSは自由に選択することができます
macOSの上でwindowsを動かす といったことができるのです。

macOS上で動くwindows
image.png

これにより開発用のPCとサーバー用のPCが別の環境であったとしても、仮想マシンを利用することで環境を揃えるということが可能になりました。

image.png

※図では、開発用PCの環境に、サーバー側が仮想化技術を用いて環境を合わせるように書いておりますが、実際は開発用のPC上でサーバーの環境を作り、その上でプログラムを開発することがほとんどです。
また、windowsOSやmacOSはサーバー用のOSではなく、サーバーには殆どの場合LinuxやLinuxディストリビューション(Linuxの亜種のようなもの)が用いられております
(@souchi00さん、ご指摘ありがとうございました)

また仮想化によって生成された仮想マシンは安全に分離されているので、1つの仮想マシンに異常が発生しても他の仮想マシンに影響が出るリスクを軽減できます。(実態のPCに異常が発生すると全ての仮想マシンに影響が出てしまうので、リスクを軽減できる という表現にとどめています。)

これにより、1台のPC上で安全に複数のプログラムを動かすことができるようになったのでした。

image.png
(詳細は割愛しますが、仮想マシンにはホスト型とハイパーバイザー型があり、ハイパーバイザー型のほうがサクサク動くため近年主流になっています。)

Docker

仮想マシンの登場によってデプロイ時の悩みの多くは解消されました。
しかし仮想マシンにも弱点は有りました。

それは目的のプログラムとは関係のないサービスなども多数動作することになるので、オーバーヘッド(立ち上げにかかる時間など)が大きく、リソースも無駄に多く必要になりがちだという点です。(OSに関するプログラムの分多くのメモリを消費する)

PCを起動すると、デスクトップが表示されるまである程度時間がかかるのはみなさんもよくご存知だと思います。

そこで誕生したのがDockerという新たな仮想化技術でした。(やっと本題です...)

Docker(ドッカー)は、コンテナ仮想化という技術を用いてプログラムを開発・実行環境から隔離することで、安全に素早く複数のプログラムを実行することができます。

DockerはOSを新たにインストールすることはしません。
もともとPCに備わっているOSをそのまま利用します。
OSがもつ「コンテナ」機能機能を使うことで、同じOS上でも互いに隔離されたプロセスを作ることができるのです。

image.png

だからコンテナ仮想化と呼ばれるわけですね。

新たにOSを立ち上げる必要がないため、仮想マシンに比べてアプリケーション(プログラム)の立ち上げが早く、またメモリも節約することができます。

Dockerfile

またDockerではDockerfileというファイルを元にコンテナを生成(アプリを実行)します。
Dockerfileは環境構築のレシピのようなもので、Dockerはレシピ通りに上から順番にコマンドを実行し、コンテナ内の環境を整えていきます。

Dockerfileの例
image.png

Dockerfileで環境を管理することで以下のようなメリットがえられます。

  • 簡単に何度でもコンテナを生成できる
    一度Dockerfileを作成してしまえば、コマンド一発で何度でもコンテナを生成できます。
    なので例えばサーバーが急に100台必要になっても、リソース(CPUやメモリなど)さえあれば簡単に用意することができるのです。

  • コンテナを持ち運びできる
    またDockerfileはただのソースコードなので、簡単に別のPCに移植したり第三者と共有することができます。
    Dockerfileを共有するためのDockerhubといったサービスも有り、手軽に他の方が生成したコンテナを利用することができます。
    例えば会社に新入社員が入ってきた際の環境構築も、Dockerfileを共有するだけで済むのです。

  • アプリケーションのバージョン管理が楽になる
    Dockerfileはただのソースコードなので、git等で差分管理ができます。
    なので例えば新しくリリースしたバージョンが何かしらの理由でバグっていた場合にも、確実に動いていた前のバージョンに戻すことができます。(プログラムのみをgitで管理していると、ライブラリのバージョンと言った環境依存のバグを解消できません。)

このような利便性からDockerは現在人気を博しているわけですね。

まとめ

Dockerとはコンテナ仮想化技術であり、OSなどの環境の違いを気にすることなくプログラミングできるようにしてくれる無償のソフトフェア。

Dockerを使うことで次のようなメリットがえられる。
- アプリケーションのバージョン管理が楽になる(アップデートによってアプリケーションが壊れても、すぐに動いてたバージョンに戻せる)
- 1台のPC上で簡単かつ安全に独立したサーバーを複製できる
- 相手がDocker(コンテナ技術)を使える環境であれば、確実に動かせるソフトウェアを作ることができる(環境の違いを吸収できる)

長らくお付き合いいただきありがとうございました。
なんとなくでもDockerがどういったものか理解していただけたでしょうか?

DockerはGitと並んでエンジニアにとっては習得必修の技術になりつつあります。
ぜひこの機会に腰を据えて勉強してみてください!

※ほかにも解説してほしい技術があればコメントなどで教えて下さい
twitterでも歓迎です!

おまけ1

環境の違いと言うと、フロントエンドエンジニアの方ならIEとChrome などと言ったブラウザの違いに苦しめらている方も多いと思います。
Dockerでは残念ながらこれらの違いを吸収することはできません。

DockerがカバーしてくれるのはOSや環境変数といったものの違いであるのに対して、IEとChromeの違いはブラウザの持つレンダリングエンジンやJavascriptエンジンの違いであるからです。

これらの違いを吸収してくれるソフトウェアが出たら嬉しいですね。

おまけ2

Dockerはもともと持っているOSを使い回すと説明した時に、
鋭い方は「あれ、これじゃOSの違いを吸収できなくね?」と思ったかもしれません。

すいません、こちら完全に嘘を教えておりました🙇‍♂️
旧説明文
現在代表的なOSというと大体windows、Linux、macOSの3種類が挙げらます。
この内macOSとLinuxはOSのコアの部分が非常に似ており(もしかしたら完全に同じかも)、macOSで動くものはだいたいLinux上でも動くのです。(逆もしかり)

macOSとLinuxは全くの別物であり、似てもいませんでした。(嘘を教えて申し訳ないです🙇‍♂️)

訂正した説明文
実はコンテナという機能はLinuxOSの機能であり、以前はDockerはLinuxでしか使えませんでした。
その後macOSやwindowsでもDockerが使えるようにと「Docker Desktop for Mac」や「Docker for Windows」といったソフトウェアが登場します。
これらはOSが異なるコンテナを実行する際、裏側でハイパーバイザー型の仮想マシン技術を使っています。
参考リンク

SatoshiSobue
2年目エンジニア 都内のStockmark .Inc という自然言語を扱うAIベンチャーで, 主にフロントエンドエンジニアやってます Javascript / Typescript / vue / python / node / ruby on rails / go / flutter / aws / bert
ユーザー登録して、Qiitaをもっと便利に使ってみませんか。
  1. あなたにマッチした記事をお届けします
    ユーザーやタグをフォローすることで、あなたが興味を持つ技術分野の情報をまとめてキャッチアップできます
  2. 便利な情報をあとで効率的に読み返せます
    気に入った記事を「ストック」することで、あとからすぐに検索できます
コメント
この記事にコメントはありません。
あなたもコメントしてみませんか :)
すでにアカウントを持っている方は
ユーザーは見つかりませんでした