Docker超入門~通常レベルまで Part2

本記事の内容について

1. Part1の復習

コマンドの復習

dockerイメージをプルする

docker image pull イメージ名

dockerイメージをrunするコマンド

docker container run オプション イメージ名

part1では、dockerについての説明と、なぜ注目されているのか。dockerの仕組みについて説明しました。また、dockerイメージについて軽く説明しました。

本記事では、dockerのコマンドやimageについてもう少し深ぼって説明していきます。

2. dockerイメージ part2

dockerイメージについてコマンドを使いながら説明していきます。

2.1. イメージリストを表示させる

まずは、以下のコマンドを実行してみてください。

docker image ls

画像のように実行結果が表示されると思います。これは、あなたのパソコンのdockerに保存されているdockerイメージです。前回使ったものが入っていると思います。

オプションについて

[-all, -a]

すべてのイメージを表示する

[–digests]

ダイジェスト値を表示する

このコマンドを入れることで、ダイジェスト値を見ることができます。

ダイジェスト値に関しては、こちらを参考にしてみてください。

[-filter, -f]

指定した条件でフィルタ検索を実行する

[–help]

ヘルプコマンドと言って、指定しているコマンドの使い方についてを表示します。

たとえば、–formatを使ってみましょう。

docker image ls --format table
または、
docker image ls --format json

以下のように、dockerイメージの情報を指定したフォーマットで出力してくれます。

dockerに限らず、世の中のコマンドはhelpを用意しているので、ぜひ使ってみてください。

2.2. イメージを削除する

次に、イメージの削除をしてみましょう。

削除コマンドは、以下のとおりです。

docker image rm {IMAGE ID}

削除したいイメージIMAGE IDを指定すると消去することができます。

docker image rm dfbcc2701b93

このようにして削除することができます。

また、削除できない場合は、-fオプションを用いて、強制的に消去することもできます。

docker image rm -f {IMAGE ID}

[–help]

ヘルプコマンドを実行してみましょう。

docker image rm --help

出てきましたね。コマンド覚えていないなーと思った時は、まずドキュメントを検索する前に–helpをすることで時短になることもあるのでぜひ。

3. dockerコンテナ

さて、dockerがなぜ注目されているのか、dockerコンテナ。注目はコンテナであり、dockerのアイコンもコンテナが描かれています。part1では説明しませんでしたが、ホストOS型やハイパーバイザー型の方法と比べてこのdockerがすごいところは、組み換えが可能な点です。

dockerで作る開発環境は、コンテナで管理されています。コンテナを積んでは、消して。消しては積んで。そうやって環境を作っていきます。このコンテナの中にubuntuの環境、nodejsの環境、mysql、pstgresqlの環境など。コンテナごとで管理されます。

図で説明しましょう。たとえば、3つのコンテナ。3つの環境があったとしましょう。

開発途中で、やっぱりこの機能いらないから、環境を消すか。と言って該当する環境を簡単に消去できます。

また、別の環境が必要になった時、簡単に環境を導入することができます。

この、簡単に!!と言うのが結構重要なのです。

ホストOS型やハイパーバイザー型はアプリケーションごとに環境が成り立っているため、データベース周りの環境変えたいな。ちょっとバージョン変更したいな。ということがあった際に、アプリケーション全体のつながりを考えながら慎重に環境を整えて、チームメンバーへの共有、さらには本番環境の構築し直し。dockerに比べるとかなり大袈裟な作業になってしまいます。

3.1. ヘルプコマンドでcontainerが使えるコマンドリストを表示しよう

docker container --help

出力結果

Usage:  docker container COMMAND

Manage containers

Commands:
  attach      Attach local standard input, output, and error streams to a running container
  commit      Create a new image from a container's changes
  cp          Copy files/folders between a container and the local filesystem
  create      Create a new container
  diff        Inspect changes to files or directories on a container's filesystem
  exec        Execute a command in a running container
  export      Export a container's filesystem as a tar archive
  inspect     Display detailed information on one or more containers
  kill        Kill one or more running containers
  logs        Fetch the logs of a container
  ls          List containers
  pause       Pause all processes within one or more containers
  port        List port mappings or a specific mapping for the container
  prune       Remove all stopped containers
  rename      Rename a container
  restart     Restart one or more containers
  rm          Remove one or more containers
  run         Create and run a new container from an image
  start       Start one or more stopped containers
  stats       Display a live stream of container(s) resource usage statistics
  stop        Stop one or more running containers
  top         Display the running processes of a container
  unpause     Unpause all processes within one or more containers
  update      Update configuration of one or more containers
  wait        Block until one or more containers stop, then print their exit codes

Run 'docker container COMMAND --help' for more information on a command.

主に使いそうなコマンドだけ説明しますと、

run

これは、dockerイメージからコンテナを作成し、さらにコンテナを起動するときに使います。

start

コンテナを起動させるときに使います

stop

コンテナを停止させるときに使います

exec

実行中のコンテナ内でコマンドを実行することができます

rm

コンテナを削除することができます。

他のコマンドは自力で覚えてください。

3.2. おまけ

最近、筆者が勉強しているkubernetesで面白いなと思った技術がありそれに関係しそうなコマンドを教えます。それは、killです。

kubernetesには、グレースフルシャットダウンという仕組みがあり、これは立ち上がっているアプリケーションが予期せぬ事態で強制的にシャットダウンさせられた時、処理中のものでも問答無用で処理が止まってしまうことを防ぐための、その対策としてある仕組みです。なので、killコマンドは、コンテナを強制的に停止させるコマンドなので、関連します。

アルパカでもわかる安全なPodの終了

興味のある方は調べてみてください。

4. dockerボリューム

volumeについてのドキュメント

ボリュームの説明は簡単です。

まず、自分のパソコンで操作しているフォルダやファイルは、dockerで立ち上げたコンテナの中のファイルとは全く別物であるという認識が大事です。

では、環境を作った後どうやるのか。それは、コピーして使います。dockerの中にコピーします。

しかし、毎度毎度コピーすると、たとえば、とても重たいファイルなどがあったときに膨大なコピー時間を要するので大変です。

そこで、ボリュームという考えがあるのです。簡単にいうと、ボリュームというのは記憶領域のことです。コンテナとは別世界に存在します。

その前に、マウントという概念を知っておく必要があります。USBをパソコンに刺す感覚に似ています。全く異なるものではあるのですが、外部から、データを持ってきたときに、どのようにそのデータを読み込むのか。マウントというのは、読み込み方の一つで、パソコンにもともとあるフォルダやファイルに対して、以下の画像の赤い箇所のようにデータを紐づけている。これをマウントという。

では、ボリューム、バインドするとはいったいどういうことか。一言で言うとデータの共有です。

dockerには、3種類のマウント方法があります。ドキュメント

  • bind mount
  • volume
  • tmps mount

tmps mountは、なんとなくわかります。一時的にマウントするデータのこと。

bind mountとvolumeの違いはなんなのでしょうか

それは、管理するところがどこであるのかと言う違いです。

bind mountは、ホストOS側で管理しています。つまり、我々が普段触っているパソコン上のデータです。

volumeは、Dockerが管理しています。(厳密に言えば、dockerそのものもパソコン上のデータとして管理されているので、どちらもパソコン内に存在はしています。ここではあえて、二つを区別するためにそう言う違いとして扱います。)

図で示すと以下のようになります。

Volumesはコンテナで生成されたデータを永続的に保持するために使用しますbind mountはホストマシンのディレクトリ構造に依存しますがvolumesはDockerが管理します
そのため、バックアップや移行がしやすかったり複数コンテナ間で安全に共有できたりします
また、Docker Desktop上のボリュームはMacやWindowsからのbind mountに比べて性能が高いです

https://blog.shinonome.io/docker-container-mount/

4.1. 使いわけ

bind mount

bindmountは、プロジェクトコードをコンテナ内にマウントするときに使用します。

phpで開発します。それをコンテナの中にいちいちコピーして実行するのはめんどくさい。そんなときにbind mountを使用します。自分のパソコンで作業している内容がそのまま反映されるので便利です。

volume

volumeは、データベース関連の情報を保存するときに使います。データベース情報は自分のパソコン内で管理しなくてもよく、他人にも共有したいので、dockerに持たせておくのが良いでしょう。

長く説明しましたが、volumeの使用については、次の記事part3で書きます。

5. Dockerfile

dockerイメージを知っているのなら、簡単です。

Dockerfileとは、自身のパソコンで、dockerイメージを作成するために必要な設計書のことです。

たとえば、PHPの環境が備わったDockerコンテナを作りたい。となったとき、以下のように書きます。

FROM php:7.4-apache

COPY /test .
<?php
    phpinfo();

フォルダの構成は以下のようになります。

% tree                                                                                                   ✔  08:40:22 
.
├── Dockerfile
└── test
    └── index.php

では、以下のコマンドで、Dockerfileをビルドして、docker imageを作成しましょう。

docker build

以下のようにエラー起きます。

どうしてでしょうか?

これは、dockerの仕組みで、どのディレクトリをビルドするのかを指定してあげないといけません。

docker build .

ついでにタグで名前もつけます。タグは-tオプションでつけれます。

 docker build -t phpimage .

そうすると、dockerイメージが作成されているはずです。これを元にdockerコンテナを作成し、起動しましょう。

では、作成されたimageを用いて、コンテナを起動させましょう。

今回は、オプションがいっぱいあります。

docker container run -p 3030:80 --name phpcontainer01 phpimage

基本形式は、docker container run phpimageです。

それに、-p コマンドと、–nameコマンドがあります。-pは、接続ポートを指定します。これは、我々が、コンテナに対してアクセスしたいので、指定します。–nameは、コンテナの名前を決めるために指定します。

ポートの意味は、ドキュメントから確認してください。

今回は、3030:80という感じになっています。これは、私たちのパソコンからコンテナに対してアクセスするので、私たちのパソコンは、3030ポートから出入りします。コンテナは、80ポートを開けていて、3030から来たものを通してください。みたいな意味です。

http://localhost:3030こちらにアクセスすると以下のような画面が表示されるはずです。

5.1. おまけ

dockerのコマンドやdockerの実行は、restAPIを返して、dockerデーモンと呼ばれる色々やってくれるところへアクセスします。

画像引用: https://docs.docker.jp/v1.12/engine/understanding-docker.html

docker build .

これ、なんで ” . “をつけているのか気になりませんでしたか?

これは、restAPIってのが肝で、.以下のディレクトリをまとめて、RESTAPIでdockerデーモンさんへ送信します。って意味なんです。

結構大事なんすけど、たとえばディレクトリ構成を以下のように変更してください。

% tree                                                                                                   ✔  09:14:19 
.
├── dockertest
│   └── Dockerfile
└── test
    └── index.php

こうすると、Dockerfileから見て、index.phpの階層が変わりました。

これを再びイメージビルドするとエラーが起こるので、よって、Dockerfileを編集します。

FROM php:7.4-apache

COPY ../test .  ## 変更

これでおっけい。では、docker buildコマンドでビルドしてみます。

docker build ./dockertest
[+] Building 0.5s (6/6) FINISHED
 => [internal] load .dockerignore                                                                                                                  0.0s
 => => transferring context: 2B                                                                                                                    0.0s
 => [internal] load build definition from Dockerfile                                                                                               0.0s
 => => transferring dockerfile: 72B                                                                                                                0.0s
 => [internal] load metadata for docker.io/library/php:7.4-apache                                                                                  0.5s
 => [internal] load build context                                                                                                                  0.0s
 => => transferring context: 2B                                                                                                                    0.0s
 => [1/2] FROM docker.io/library/php:7.4-apache@sha256:c9d7e608f73832673479770d66aacc8100011ec751d1905ff63fae3fe2e0ca6d                            0.0s
 => ERROR [2/2] COPY ../test .                                                                                                                     0.0s
------
 > [2/2] COPY ../test .:
------
Dockerfile:3
--------------------
   1 |     FROM php:7.4-apache
   2 |
   3 | >>> COPY ../test .
--------------------
ERROR: failed to solve: failed to compute cache key: failed to calculate checksum of ref moby::u9ug3hj1ricge1612hoho9va2: "/test": not found

おかしい。”/test”: not foundになっています。

いいえ。。おかしくないんです。これは、dockerにとって正常なエラーなんです。

仕組みはこうです。!!

RESTAPIで送信する際に渡すディレクトリは、上記の写真のように指定したディレクトリ以下になります。つまり、階層を戻って、処理する。というような記述をすると、そんなデータはないですよ。と返ってくるのは当たり前なのです。ですが、結構はまりポイントであると思いますので、言語化しておくことは大事です。

6. 終わりに

Part2はここまでとします。

次回は、 Part3です。お楽しみに!

1 件のコメント

コメントを送信

You May Have Missed