はじめに
友人(@digital24s さん)に誘われて、クラウドサービスで仮想マシン環境を作ってみました。
Google Compute Engine に Windows 環境を作ってリモートデスクトップ接続してみた #GoogleCloud - Qiita
続いて、コンテナ型の仮想環境の Docker も使ってみたいと思いました。
Docker を使ってみる
Linux マシンを用意する
Docker は Linux OS で稼動します。そのため Linux マシンを用意します。
自分は Google Cloud の Compute Engine を使って Ubuntu OS の仮想マシンを作りました。
Docker エンジンをインストールする
Ubuntu OS マシンに Docker エンジンをインストールします。
Docker Engine インストール(Ubuntu 向け) | Docker ドキュメント
Docker コンテナを作ってみる
以下のサイトを参考にしました。
Dockerコンテナの作成、起動〜停止まで #Docker - Qiita
コンテナイメージをダウンロードする
Docker リポジトリからコンテナイメージをダウンロードします。
今回は CentOS を使ってみようと思います。
$ docker pull centos:latest
コンテナを作成する
イメージからコンテナを作成します。
$ docker create -it --name trydocker centos
-it
オプションをつけて作成します。こうしないと、コンテナを起動した後で OS のシェルにコマンドを入力して出力結果を確認することができません。
--name
オプションでコンテナに名前をつけておきます。名前は任意です。
作成されたコンテナが確認できます。
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d6d964941a51 centos "/bin/bash" a minute ago Created trydocker
コンテナを起動する
作成したコンテナを起動します。
$ docker start trydocker
コンテナの状態を確認してみます。
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d6d964941a51 centos "/bin/bash" a minute ago Up a minute ago trydocker
ステータスが「Up」になっています。つまり稼動しています。↑
コンテナ内で操作する
コンテナ内で OS が起動してシェルが使えるようになっています。これに接続します。
$ docker attach trydocker
コンテナ内の OS のシェルでコマンド入力できます。
# whoami
root
# cat /etc/*release
中略
NAME="CentOS Linux"
後略
Ubuntu OS 上の Docker 環境で CentOS が起動していることが分かります。使えるコマンドも違ったりします。
コンテナ内のシェルからホストのシェルに戻ります。↓
# exit
コンテナの状態を確認します。
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d6d964941a51 centos "/bin/bash" a minute ago Exited (0) a second ago trydocker
ステータスが「Exited」になっています。つまり停止しています。↑
もう一度、起動して接続します。
$ docker start trydocker
$ docker attach trydocker
以下のキー入力します。
ctrl+P → ctrl+Q
ホスト側に戻りました。コンテナの状態を確認します。
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d6d964941a51 centos "/bin/bash" a minute ago Up a minute ago trydocker
ステータスが「Up」になっています。つまり稼動しています。↑
コンテナ内のコマンドを実行する
コンテナ内のシェルに接続してコマンド入力しましたが、ホスト側でダイレクトに実行することができます。
$ docker exec trydocker cat /etc/*release
中略
NAME="CentOS Linux"
後略
参考:Dockerコンテナ内で操作 attachとexecの違い #Docker - Qiita
コンテナの実体を確認する
ホスト側のファイルを確認してみます。
参考:コンテナ仮想化Dockerの使い方 & 実体 | NagareLab
以下のディレクトリが確認できます。
/var/lib/
├─ docker/
│ ├─ builder/
├─ buildkit/
├─ containers/
│ ├─ d6d964941a51.../
│ │ ├─ checkpoints/
│ ├─ mounts/
│ ├─ d6d964941a51...log
│ ├─ config.v2.json
│ ├─ hostconfig.json
│ ├─ hostname
│ ├─ hosts
│ ├─ resolv.conf
│ └─ resolv.conf.hash
├─ image/
├─ network/
├─ overlay2/
│ ├─ 6d060f2e6ecc.../
│ │ ├─ diff/
│ ├─ work/
│ ├─ link
│ └─ lower
├─ plugins/
├─ runtimes/
├─ swarm/
├─ tmp/
├─ volumes/
└─ engine-id
コンテナ内でファイルを作成します。
# mkdir /home/docker
# echo "Hello, Docker!" > /home/docker/hello.txt
ホスト側のファイルを確認します。
├─ docker/
├─ overlay2/
│ ├─ 6d060f2e6ecc.../
│ ├─ diff/
│ ├─ home/
│ └─ docker/
└─ hello.txt
ここで確認できた hello.txt
をホスト側で編集してみます。
$ sudo echo "Hello, World!" > /var/lib/docker/overlay2/6d060f2e6ecc.../diff/home/docker/hello.txt
コンテナ内で確認します。
# cat /home/docker/hello.txt
Hello, World!
ターミナルで使えるファイル管理ソフトを導入する
cd
や ls
コマンドを使ってもいいのですが大変なので、ファイラ(ファイル管理ソフト)を導入します。幾つか試してみましたが ranger
がよさそうです。
ターミナルで使えるファイラrangerを使ってみる #Linux - Qiita
コンテナを停止する
実行しているコンテナを停止します。
$ docker stop trydocker
コンテナの状態を確認してみます。
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d6d964941a51 centos "/bin/bash" a minute ago Exited (0) a second ago trydocker
ステータスが「Exited」になっています。つまり停止しています。↑
コンテナを削除する
コンテナが不要になったら削除できます。
$ docker rm trydocker
docker run で実行する
Docker の運用で、上記のように crete
、start
、exec
することは、ほとんどないそうです。
run
コマンドで実行します。
$ docker run --name trydocker centos cat /etc/*release
中略
NAME="CentOS Linux"
後略
コンテナの状態を確認してみます。
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
746757caaf41 centos "cat /etc/lsb-releas…" a second ago Exited (1) a second ago trydocker
コンテナが作成されて停止しています。↑
コンテナは基本的に使い捨てるそうです。
なので、--name
オプションをつけないで、さらにコンテナが残らないように --rm
オプションをつけたりします。
$ docker run --rm centos cat /etc/*release
コンテナを起動してシェルに接続してみます。↓
$ docker run -it --rm centos /bin/bash
コンテナのデータを永続化する
docker run --rm
で実行されたコンテナで作成されたデータは、コンテナが使い捨てられるので残りません。
コンテナが作り直されても、データが残るようにする=永続化する仕組が用意されています。
参考:「そのコンテナのデータ、消えるよ……」とさせないための、イメージ図+実践で理解するDockerストレージ【Dockerコンテナ・グレートジャーニー③】 #Docker - Qiita
ホスト側のディレクトリをコンテナにマウントする
ホスト側に共有するディレクトリを用意します。
$ mkdir /home/docker/share
これをコンテナ内で利用できるようマウントします。
$ docker run -it --mount type=bind,src=/home/docker/share,target=/home/share --name trymount centos /bin/bash
コンテナ内でディレクトリを確認します。
# ls /home/share/
何も表示なし
ホスト側でファイルを作ります。
$ echo "Hello, Docker!" > /home/docker/share/hello.txt
コンテナ内でディレクトリを確認して、ファイルを変更します。
# ls /home/share
hello.txt
# cat /home/share/hello.txt
Hello, Docker!
# echo "Hello, World!" > /home/share/hello.txt
ホスト側でファイルの内容を確認します。
$ cat /home/docker/share/hello.txt
Hello, World!
ボリュームコンテナを作ってコンテナにマウントする
予めボリュームコンテナを用意します。ボリュームコンテナは使い捨てません。
$ docker volume create shared_volume
ホスト側のファイルを確認してみます。
├─ docker/
├─ volumes/
│ ├─ shared_volume/
これをコンテナ内で利用できるようマウントします。
$ docker run -it --mount type=volume,src=shared_volume,target=/home/share --name trymount1 centos /bin/bash
コンテナ内でファイルを作ります。
# echo "Hello, Docker!" > /home/share/hello.txt
上記のコンテナを破棄して、別のコンテナを実行します。
$ docker rm trymount1
$ docker run -it --mount type=volume,src=shared_volume,target=/home/share --name trymount2 centos
コンテナ内でファイルの確認します。
# cat /home/share/hello.txt
Hello, Docker!
Docker を理解する
自分は仕事でも趣味でも、Docker を使う機会はないと思っていました。なので、Docker について勉強してきませんでした。
とはいうものの、周囲の知人は Docker を使っていて、会話に出てくることがあります。このとき自分が話題についていけないのは、悔しいと思っていました。
よくある Docker の説明を見て考えたこと
入門といえる記事を検索して一通り読んでいきました。
ハイパーバイザ型の仮想マシンと比較してコンテナ型の Docker が説明されています。
参考:コンテナってなんだろう― 「コンテナ」の概要を知る | Think IT
これらの説明を読んで、次のように考えていました。
コンテナはホストの OS の機能を呼出するという。
であれば、ホストの OS に予めミドルウェアを入れれば、コンテナで利用できるのか。
コンテナとは、実行時に生成される仮想マシンなのか。それとも、ハイパーバイザ型の仮想マシンの仮想ディスクのようなものなのか。
空のコンテナを作って、コンテナ内で操作するとホスト側で差分情報が記録されて、これを配付して再利用できるのだろうか。
これらの疑問を Doker を利用している知人に聞いてみたが、どうも違っているらしい。けれど、説明を聞いてもよく分からない。使ってみれば分かるようになると言う。
自分は、Docker を使いたいのでなく、Docker がどんなものか分かりたいだけなので、上手い説明が欲しいと思っていました。
試してみて分かったこと。記事によっては書かれていなかったこと
実際に使って試しながら、他の記事を読んでいきました。その結果、分かったことがありました。いわゆる「入門」記事には書かれていなかったり、書かれていても分かりづらかったりしたことでした。
まず、UNIX 系 OS なら使えると思っていたが、Linux OS しか Docker は使えない。
ベースになるコンテナイメージが予め用意されていて、それを使ってコンテナを作る。
コンテナ内に OS のカーネルはなくて、ホスト機の OS のカーネルを呼出する。
ホスト機の OS のユーティリティソフトやミドルウェアは、コンテナから見えるようになっていない。コンテナ内にユーティリティソフトが用意される。
自分はユーティリティソフトを含めて OS(「広義の OS」)と言うスタンスなので、コンテナ内に OS がない説明を見て、勘違いしていた。
Docker のコンテナは、ホスト OS の所定のディレクトリにあるファイル群である。
コンテナ内で作成されたデータは、このディレクトリに作成される。
コンテナは基本的に使い捨てる運用する。
永続化したいデータはコンテナの外に置くようにする。