Dokcerとは
Dokcer社が提供する「コンテナ型仮想化技術」で、コンテナ仮想化を用いてアプリケーションを開発・配置・実行をするためのオープンプラットフォームである。
アプリケーションを基盤から分離し、アプリケーションのコードの転送、テスト、デプロイ、コードの記述とコードの実行におけるサイクルを短くできるもので、基盤から分離することにより、OSやバージョンの違いといった開発環境及び動作環境と異なる環境においてでも、アプリケーションの動作が容易に実現できる技術である。
Dokcerの概念
従来の仮想化技術では、ホストOS(Windows、MacOS等)上で、仮想化ソフト/ハイパーバイザー(VirtualBox等)により別のOSを立ち上げるということをしていました。この場合、1台のPCで並列してOSを起動させており、動作が重くなるという欠点があります。また、チーム内でのファイル共有も手間がかかります。
Dokcerでは、それぞれ異なったホストOS上でDokcerエンジンと呼ばれるLinux仮想マシンのカーネル(OSの中核部で、システムのリソースやハードウェアとソフトウェアの連携を管理)を裏で動かすことで、各コンテナのアプリケーションを動かしています。
ホストOSのカーネルを各コンテナが共有することで、ホストマシンのリソース(CPU、メモリ)を節約しながら動作が可能になります。
これにより、動作が軽量になるということになります。
また、Dokcer HubといったコンテナネットワークにDockerイメージ(コンテナ)をPush(アップロード)及びPull(ダウンロード)することで、コンテナの共有を開発者同士で行うこともできます。
なぜ個々の環境が必要なのか
例えば、図のように環境AでアプリAを動かそうとしても、そもそもPythonのバージョンの違いではじかれ、アプリCではNumpyのバージョンが異なると言われるような事態が起こりえます。
逆のケースもあり、昔のソースコードを実行しようとしたらバージョンが新しくて実行できないことなどもあります。
この問題は、ローカル(個人)で開発環境を切り替えることで、基本的に解決できます。
しかし、複数人での開発の場合、それぞれ同じ開発環境に合わせていたとしても、ホストOSが異なっていたり、コンフィグ(設定)を多少いじっていたりと、ちょっとした依存関係の変化により、正常に起動しないことが発生します。
開発者にとっての問題だけではなく、ユーザ側も同じ環境構築をする場合があります。
提供者視点では、ユーザ側への環境構築サポートをしなければならないですし、
ユーザ視点では、アプリケーションを要求しているのに、環境構築も行なければならないのか、そのサポート費用も取られるのかといった疑問もあります。(ケースバイケース)
この状態では双方のコストパフォーマンスが悪いということです。
Dokcerを用いて、同じDokerイメージを共有することで、開発、運用を容易に行えるようになります。
要は、Dockerを使用することで開発環境を徹底的に揃えることができる ということです。
Dockerイメージとは
Dockerイメージは、何層にもなるレイヤが存在し、もとになるベースイメージにイメージ・レイヤを重ねることで、新たなDockerイメージを作成することができます。ベースイメージとはCentOSやUbuntuなどのOSやNginxやApacheなどのWebサーバなどになります。
Dockerコンテナの実行に必要な概念としてのパッケージ(ファイルやメタ情報の集まり)であり、仮想マシンイメージのように、実体としての1ファイルではありません。また、それぞれのレイヤに親子関係を持っています。
通常、Dockerイメージを自動構築できるように定義するのが Dockerfile と呼ぶ設定ファイルであり、このファイル内でイメージを構成する命令を書きます。この命令の1つ1つが、概念上のイメージレイヤに相当します。
1つのミドルウェアをインストールするたび、レイヤが積み重ねっていくイメージで、それぞれのイメージレイヤは編集不可(Read Only)であり、Dockerイメージからコンテナを起動した際に作成される、コンテナレイヤのみ編集可能になっています。
これは、コンテナ内で何かしらのミドルウェアをインストールした際に、そのコンテナレイヤに保存し、新たなイメージレイヤとするためであります。
実践
Macはこちら、WindowsはこちらからDockerをインストール
「WSL 2 installation is incomplete.」が表示された場合
以下をインストールし、Dockerを再起動
「Docker Desktop starting...」が表示されれば問題なし
Windows Subsystem for Linux
https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi
以下はWSLについてのドキュメント、見なくてもいい
WSLドキュメント
https://docs.microsoft.com/ja-jp/windows/wsl/install-manual#step-4---download-the-linux-kernel-update-package
動作確認
$ docker --version
Docker version 20.10.13, build a224086
動作テスト
基本的なコマンドとして
$dockerコマンド サブコマンド イメージ
これをターミナル、コマンドプロンプト等にて打ち込むことでコンテナを実行します。
テストとして、「hello-world」というコンテナを実行します(Dockerは常駐している上で)。
$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
2db29710123e: Pull complete
Digest: sha256:f861ba8563637d693e3043069b0a4ebf3d92c2e865b541379f6a6b8164b7c8bb
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
この一文が出力されていれば、「hello-world」のコンテナが実行できていることになります。
Hello from Docker!
コンテナが存在するのか、もう一度確認します。
# ダウンロードしたイメージの一覧を表示します
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest feb5d9fea6a5 5 months ago 13.3kB
# すべてのコンテナを表示します(デフォルトは実行中のコンテナのみ)
$ docker ps -all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
56f95902920e hello-world "/hello" 34 hours ago Exited (0) 34 hours ago mystifying_jemison
コマンドが返ってきて、hello-worldの表記があれば、問題ないです。
Dockerfileからイメージ作成
Dockerfileとは、Dockerイメージを作成する為に実行するコマンドをコード化して、一つのファイルにまとめたものです。
適当なディレクトリに"Dockerfile"という名前のファイルを作成します。以下のコードを記述し、保存します。
FROM centos:centos7
RUN yum -y install httpd php
COPY test.php /var/www/html/
CMD ["/usr/sbin/httpd","-DFOREGROUND"]
画面表示用に、phpファイルを同じ階層に作成し、以下のコードを記述します。
<?php
echo "Hello World!";
?>
この時点でのファイルの配置はこのようになっています。フォルダ名の"Docker"は任意です。
Docker/
├ Dockerfile
├ test.php
コマンドプロンプト、スクリプトを開いて、上記のDockerfileと同じ階層に行き、以下のコマンドを打ち込みます。
ここで、設定ファイルであるDockerfileからDockerイメージを作成します。
$ docker build -t testphpimg .
[+] Building 1.9s (9/9) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 164B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/centos:centos7 1.8s
=> [auth] library/centos:pull token for registry-1.docker.io 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 29B 0.0s
=> [1/3] FROM docker.io/library/centos:centos7@sha256:c73f515d06b0fa07bb18d8202035e739a494ce760aa73129f60f4bf2bd22b407 0.0s
=> CACHED [2/3] RUN yum -y install httpd php 0.0s
=> CACHED [3/3] COPY test.php /var/www/html/ 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:3e6d74481e3e3c1bbf796c8bf640c656d6515bf4b88efe95188292eb16c9b9bc 0.0s
=> => naming to docker.io/library/testphpimg 0.0s
Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them
Dockerイメージが作成されていることを確認します。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
testphpimg latest xxxxxxxxxxxx 47 minutes ago 414MB
hello-world latest xxxxxxxxxxxx 5 months ago 13.3kB
次に、作成したDockerイメージをコンテナとして動かします。
$ docker run -d -p 8080:80 --name testweb testphpimg:latest
//64文字の文字列が表示される
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
起動を確認したら、以下にアクセス
Hello World!が表示されていれば、正常にコンテナが動作しています。
コマンドからも動作していることが確認できます。
$ docker ps -all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
xxxxxxxxxxxx testphpimg:latest "/usr/sbin/httpd -DF…" 43 minutes ago Up 43 minutes 0.0.0.0:8080->80/tcp testweb
間違った場合には、イメージとコンテナの削除コマンドを使用します。
//Dockerイメージの削除
$ docker rmi [IMAGE ID]
//コンテナを削除
$ docker rm [CONTAINER ID]
順序はコンテナを立ち上げている場合には、コンテナ削除→Dockerイメージを削除の順番となります。
Dockerfileの記述
FROM
FROM [イメージ名]:[タグ名]
FROMで指定したDockerイメージをベースイメージとして用いることを宣言するコマンドです。
FROM centos:centos7
先ほどの例では、CentOSをベースイメージとして使用しています。
RUN
RUN [実行するコマンド]
FROMで指定したベースイメージに対してコマンドを実行させるために記述します。
RUN yum -y install httpd php
ここでは、ApacheとPHPの両方をインストールしています。
COPY
COPY [イメージ内にコピーしたいファイルのパス][コピー先のベースイメージ内のファイルパス]
作成したDockerイメージ内にホストPC上にあるファイルを転送したい場合に使用します。
COPY test.php /var/www/html/
ホストPCで作成したtest.phpをCentOS内の/var/www/html/にコピーしています。
CMD
CMD ["実行コマンド","引数"]
docker runコマンドで実行する際(立ち上げ後)のコマンドを指定します。
CMDコマンドはイメージからコンテナ作成時に1度だけ実行されます。
CMD ["/usr/sbin/httpd","-DFOREGROUND"]
ここでは、Apacheを起動させ、コマンド引数に-DFOREGROUNDを持たせています。
Dockerfileの挙動
これらの一連の動作を示した図です。
それぞれのコマンドは実行タイミングによる違いで、docker buildにより、Docker HubからCentOSのDockerイメージをピックし、このイメージをベースイメージとして、新たなイメージのtestphpimgを作成します。作成時に、RUN、COPYコマンドが実行され、testphpimgからコンテナを起動させる際に、CMDコマンドが実行されます。
つまりは、CentOSをベースイメージに、ApacheとPHPをインストールし、/var/www/html/にtest.phpをコピーしたイメージがtestphpimgであり、コンテナ作成時に、Apacheを起動させるといった流れになります。
Docker Hub
Docker Hubには様々なミドルウェアがインストールされたDockerイメージが存在します。
以下のコマンドを使用することで、Docker Hub上のDockerイメージを取得できます。
$ docker pull イメージ名
参考文献