Dockerについてまとめてみた
Dockerとは
コンテナ型仮想環境を作成し、コンテナを実行/管理するためのプラットフォームで、Dockerを利用すればコンテナ上でプログラムを実行することが可能になります。Dockerソフトウエアを使うことで素早くコンテナを起動し、様々なアプリを実行でき、かつ異なる環境で同じ仮想環境を用意できるといった点が強みです。
Dockerユースケース
・開発環境を構築するといったケースでDockerが使用されています。開発者個人個人のPCで開発中のアプリケーションを全く同じ環境で用意することが可能です。
・Dockerで作成した環境・アプリケーションをDocker Imageに固め、Dockerリポジトリというイメージを管理するサーバへアップロードする。そのイメージをダウンロード&イメージからコンテナを起動する形で開発したときと同じ環境を持っていくことができます。(Dockerの可搬性)
・各種プログラミング言語の実行環境、ミドルウエアの環境構築といった様々なコンテナを立ち上げることができる。(例えば、Javaの実行環境が用意されたDockerImageをリポジトリから取得しコマンドを1つ打つだけでJavaがインストールされたLinux仮想環境を用意できます。)
・Webサーバ(Apache、nginx)、データベース(MySQL、PostgreSQL)の構築も用意。
Dockerのメリット
①プログラミングの実行環境を素早く立ち上げられる。
②設定ファイルを共有することでメンバー間で同じ環境を立ち上げられる。
(インフラ環境をコードで定義したものをInfrastracture as a codeと呼ぶ。設定ファイルを見ればインストールされているものもわかる。)
③開発者と同じ環境を一瞬でそろえられるので、環境の違いででる差異を解消できる。(再現性)
④インストールなどが必要なくホストのライブラリやミドルウエアが汚れない。
⑤ネットに便利なコンテナが提供されており、記述する必要がない。
コンテナとは
コンテナとは、プロセスの実行空間を隔離するための技術です。コンテナと似たような概念に「ホスト型仮想化」というのがあり、VMWareやVirtualBoxなどが代表的な例ですが、それらの違いを理解することが大切です。
コンテナを説明する前にまずホスト型仮想化について説明をし、コンテナとの違いを明確にすることで、Dockerを理解していきます。
インフラストラクチャー:PCやサーバなどのハードウエア層
ホストOS:物理的なPCやサーバにインストールされたOS、WindowsやMacOSなど、サーバでいうとWindowsServerやLinuxなどが一般的なホストOS。
ハイパーバイザ:ホストOS上に仮想マシンを動作せるためにホストOSとゲストOSの中間でやり取りを行う部分。仮想マシンのハードウエアのエミュレーションをしたりOSが使用するCPU、メモリ、ハードウエアなどを制御するソフトウエアとなります。
ホスト型仮想化環境
ホストOSのハイバーバイザ上で複数のVM(仮想環境)を動作させホストOSとVMのOSが隔離された環境で動作し、ホストOSがなんであるかによらずVMごとに任意のゲストOS(Windows、Linux)を動作せることができます。
個々のVMのOS上に任意のアプリケーションをインストールさせるので、物理的なサーバと同じように動作させることが可能です。
こういった構想の仮想化のことをホスト型仮想化と呼びます。
ホスト型仮想化環境のデメリット
・物理サーバにOSをインストールしたものと近い環境を作る代わりにイメージサイズが大きいため、VMの作成やイメージの移動に時間がかかる。
・通常のOS起動と同様にそれなりに時間がかかる。
コンテナ型仮想化環境
コンテナ型仮想化環境では、ゲストOSは動作させずホストOSの1プロセスとしてコンテナが動作します。完全なOSを用意する必要がないのでアプリケーションを実行するための最低限のライブラリやバイナリを用意すればよく、コンテナで用意するイメージサイズを少なくできます。
CentOSやUbuntuなどのイメージも提供されていますが、ゲストOSと違い、コンテナ上でゲストOSを動作させているのではなく、LinuxコマンドをホストOSのカーネルで実行しています。実行したいライブラリはコンテナ側に存在して、ホスト側のカーネルを使用して動作するという仕組みです。
※ホストOSのカーネルを使用してコンテナコマンド、ライブラリを実行するということは、カーネルを共有できないOS(Widnows環境)では動作させることができないということになる。Windows環境でどのようにしてLinux環境を動作させているかについては「WindowsでLinuxコンテナを利用できる理由」の欄をご覧ください。
ホスト型仮想化,コンテナ型仮想化の違い
ざっとホスト型仮想化環境とコンテナ型仮想化環境の違いをまとめましたのでご覧ください。
オーバーヘッド:リソース(CPU、メモリ使用率)が過度に使用してしまわないか。
再現性:アプリケーションを異なる環境で実行したときに、同じように動作するか。
WindowsでLinuxコンテナを利用できる理由
LinuxコンテナはLinuxOSのカーネル上でしかどうさせることができないはずですが、なぜWindowsでLinuxコンテナを使用できるのでしょうか。
PC環境ではまず以下のいずれかのソフトウエアをインストールしDockerを利用します。
・DockerDesktop
・DockerToolbelt
Docker Containerの作成・起動・停止・削除などはDockerEngine(上記ソフトウエア)を介して実行します。Docker Toolboxを使用する場合、Docker QuickStart Terminalといったツールを起動することでDockerEngineを起動する。
いずれをインストールした場合でもDockerデーモンは必ずLinux仮想マシン上で動作しています。ソフトウエアにはWindowsやMacで動作させるために内部的に軽量なLinuxOSであるtinyCoreLinuxというOSが含まれているのがLinuxコンテナを扱える理由だったんです。つまり、コンテナにゲストOSというものはなく、ホストOSのコア部分であるカーネルを使用してコンテナのアプリケーションを実行しています。
※仮想化ソフトウエアはインストールしたDockerソフトウエアによって何が使用されるかは異なります。
仮想化ソフトウエアは一般的に下記の通りです。
・MacOSのDockerDesktopではHyperKit
・WindowsのDockerDesktopではHyper-V
・DockerToolboxの場合はVirtualBox。
※VirtualBoxだけはOSに標準でインストールされていないので追加でインストールが必要です。サーバで動作させる場合、直接LinuxのホストOS上で動作させるが通常の流れです。
Docker Image
コンテナ実行に必要なファイルをまとめたファイルシステムです。オブジェクト指向でいうClassを指します。
Docker Container実行
Docker Image(仮想マシンでいうところのVMイメージ)は、Web上のDocker Hubで公開されています。Dockerイメージを取得してくれば、すでに必要なミドルウェアなどがインストールされた状態のDockerコンテナを起動でき、すぐに使用できます。
最新のイメージを取得~コンテナを起動~実行まで行うコマンド
(ローカルPC)
# docker run <コンテナ名>
# docker run hello-world
# docker run --name <コンテナ名> -v <ホスト側ディレクトリ>:<コンテナ側ディレクトリ> -d -rm -p <ホスト側のポート番号>:<コンテナ側のポート番号> <Dockerイメージ名>
# docker run --name test-nginx -v /Users/i3_l1/Desktop/Docker/html/index.html:/usr/share/nginx/html:ro -d --rm -p 8080:80 nginx
Dockerイメージをプル(PULL)
最新のイメージを取得するコマンド
(ローカルPC)
# docker pull <コンテナ名>
# docker pull hello-world
pullしてくるタグはlatestとは限らない。
Dockerコンテナのプロセス確認
コンテナのプロセスを確認するコマンド
(ローカルPC)
# docker ps -a
※「docker ps」(「-a」を付けない)と実行すると、停止中のコンテナは表示されない。
イメージ一覧取得
コンテナ仮想化環境に存在するイメージを確認するコマンド
(ローカルPC)
# docker images
※リポジトリ(REPOSITORY)から拾ったバージョン(TAG )、イメージID(IMAGE ID )、作成日(CREATED)、サイズ(SIZE)、が取得可能
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest bf756fb1ae65 10 months ago 13.3kB
イメージにタグ付けをする
同じイメージに対してイメージ名称を複数設定するコマンド
(ローカルPC)
# docker tag <元のイメージ名> <新しいイメージ名>
# docker tag hello-world my-hello
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest bf756fb1ae65 10 months ago 13.3kB
my-hello latest bf756fb1ae65 10 months ago 13.3kB
同じイメージに対して、タグ名称を分けて管理できる。
(ローカルPC)
# docker tag <元のイメージ名> <新しいイメージ名>:<新しいタグ名>
# docker tag hello-world my-hello:tst1
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest bf756fb1ae65 10 months ago 13.3kB
my-hello latest bf756fb1ae65 10 months ago 13.3kB
my-hello tst1 bf756fb1ae65 10 months ago 13.3kB
イメージの詳細取得
ホスト名、環境変数、os情報、サイズ、ファイルシステムなどのコンテナ詳細を表示するコマンド
(ローカルPC)
# docker inspect <コンテナ名>
# docker inspect hello-world
コンテナ削除
ローカルで起動しているコンテナを削除するコマンド
# docker rm hello-world
イメージ削除
Dockerイメージを削除するコマンド
# docker rmi <コンテナ名> または <IMAGE ID>
# docker rmi hello-world
> docker rmi hello-world
Untagged: hello-world:latest
Untagged: hello-world@sha256:e7c70bb24b462baa86c102610182e3efcb12a04854e8c582838d92970a09f323
> docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
my-hello latest bf756fb1ae65 10 months ago 13.3kB
my-hello tst1 bf756fb1ae65 10 months ago 13.3kB
イメージ強制削除
イメージを強制削除するコマンド。※複数のタグが存在する場合、latestタグのイメージが削除される。
(ローカル)
# docker rmi -f <コンテナ名> または <IMAGE ID>
# docker rmi -f my-hello
Untagged: my-hello:latest
> docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
my-hello tst1 bf756fb1ae65 10 months ago 13.3kB
イメージファイル作成
イメージを構築するにはdockerfileというイメージの定義ファイルを作成します。dockerfileからイメージファイルを作成することをイメージビルドと呼ぶ。
(Dockerfile)
FROM nginx:latest
COPY default.conf /etc/nginx/conf.d/default.conf
イメージビルド方法
イメージファイルのビルドを行うコマンド
(ローカル)
# docker build -t <タグ名称> <ビルドコンテキスト>
# docker build -t nginx:test1 .
「.」はビルドコンテキストを表しています。ビルドコンテキストとは、イメージを作成する際にアクセスできるディレクトリやファイルを表しています。イメージ内に含めたいファイル/ディレクトリがある場合は、ビルドコンテキストのファイルから参照できます。ビルドコンテキスト外のファイルはイメージ構築時に参照できません。
Dockerfileが作成されていることを確認します。
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx test1 7fbf7e04654c 7 minutes ago 133MB
ビルドコンテキストはイメージビルド時にビルドコンテキストのファイルやディレクトリがまとめてDockerデーモンに送信されるため大きなファイルがコンテキストに含まれると送信に非常に時間がかかります。不要なファイルは極力削除しておくことをお勧めします。
2回目以降のビルドについて
Dockerfileが更新された場合、ビルドすると更新部分以降のビルドが行われる。1から改めてビルドしたい場合は、--no-cacheコマンドを使用する。
# docker build --no-cache -t <タグ名称> <ビルドコンテキスト>
# docker build --no-cache -t nginx:test1 .
Docker Hub RepositoryへPush
リポジトリにイメージがないことを確認
レジストリサーバ(DockerHubもしくは他のリポジトリ)へログインする方法
# docker login
# docker login <レジストリサーバURL>
DockerHubリポジトリへプッシュ
# <Docker ID>/<イメージ名>:<タグ名>
# docker push nukoit/hello-world:latest
リポジトリにイメージが追加されている
リポジトリの内容を確認
リポジトリからプルしてみる
①Docker イメージをローカルから削除
# docker rmi nukoit/docker-nuko
Untagged: nukoit/docker-nuko:latest
Untagged: nukoit/docker-nuko@sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042
②Dockerイメージをリポジトリからプル
# docker pull nukoit/docker-nuko
Using default tag: latest
latest: Pulling from nukoit/docker-nuko
Digest: sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042
Status: Downloaded newer image for nukoit/docker-nuko:latest
docker.io/nukoit/docker-nuko:latest
③DockerImageが存在すること
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nukoit/docker-nuko latest bf756fb1ae65 10 months ago 13.3kB
ファイルコピー
(ホスト→コンテナ内)
# docker cp <ホスト側のファイル> <コンテナ名>:<コンテナ内のコピー先ディレクトリ>
# docker cp /Users/i3_l1/Desktop/Docker/html/index.html test-nginx:/usr/share/nginx/html
(コンテナ内→ホスト)
# docker cp <コンテナ名>:<コンテナ内のコピー元ファイル> <ホスト側のコピー先ディレクトリ>
# docker cp test-nginx:/etc/nginx/conf.d/default.conf ./
コンテナのライフサイクル
コンテナが起動している間はホストマシンの1プロセスとして動作します。コンテナが作成されてから削除されるまでにいくつかのステータスがあります。イメージ図をご覧ください。少しわかりずらいかと思うので少しずつ更新していきます。
以上、Dockerについてでした。またDockerについてUpしたいと思います。参考になったと思う方は是非いいねお願いいたします。(*'ω'*)