LoginSignup
2
5

More than 3 years have passed since last update.

データコンテナを作ってみるDockerミニハンズオン

Last updated at Posted at 2020-01-19

「Dockerが何かは知っている・動かしてみたことはある」ぐらいの方以上を想定して

  • Dockerfileでimageを自作
  • docker-composeで複数コンテナを立ち上げ
  • サイドカーパターン

をつまみ食いしながらまとめていきます。

image.png
サイドカーパターンの図こちらのブログより転載させていただきました。
冒頭記載の対象読者層を超えてしまいますが、良い論文紹介記事です!

データを他のコンテナが共用で使っている様子が、まるでサイドカーみたいですね(棒)
今回はこの共用データを持つ役割もコンテナに担当してもらいます(データコンテナ)。

いきなり余談(?)

この記事を書くに至った経緯ですので飛ばしてもらっても構いません。

Composeファイルのフォーマットには2020年1月現在1.02.x3.xと複数のバージョンがあります。
docker-compose.yamlファイルの最初に

version: '3'

みたいに指定します。
インターンでデータコンテナを含む設計を触ることになったのでDockerの勉強から始め、docker-composeを3.x系で何の疑いもなく作ろうとしました。

しかし他のコンテナ名を指定して特定のボリュームを参照できるvolumes_fromが、3.xでは無くなっていました。
ここで悩んだ挙句に代替案が分からなかったので、一旦のまとめとしてこの記事を書いています。

2つ以上のコンテナでデータを共用したい場合

  • データ用のコンテナを1つ作り、特定のディレクトリを他のコンテナからも覗けるようにする
  • ホスト側にデータを保存しみんなで参照する永続化ボリュームを確保する

のいずれかの構成にすることが多いかと思います。

業務ではKubernetesでサイドカーパターンのPodをスケーリングさせる予定だったので、2つめの永続化ボリュームを使う設計では新しいボリュームがどんどこ作られてつらい事態に陥りそうと考え1つめのデザインパターンを試しました。

なおKubernetesでは各Podに専用の空ディレクトリを作成すればよさそうなので、結局はDockerのおべんきょうができただけでした。

sample.yaml
apiVersion: v1
kind: Pod
metadata:
  name: test-pod-1
spec:
  containers:
  - image: centos:latest
    name: test1
    volumeMounts:
    - mountPath: /test
      name: test-volume
    command: ["tail",  "-f", "/dev/null"]
  - image: centos:latest
    name: test2
    volumeMounts:
      - mountPath: /test
        name: test-volume
    command: ["tail",  "-f", "/dev/null"]
  volumes:
  - name: sample-volume
    emptyDir: {}

ハンズオン!

それでは

  • centosコンテナ
  • Dockerfileでつくってみるオリジナルcentos-volumeコンテナ
  • docker-composeでまとめて立ち上げ
  • 確認・お片づけ

の順でさくさくと試していきましょう。

DockerfileでオリジナルのDocker imageを作る

ざっっっくり言うと、Dockerコンテナを作る型抜きの原型がDocker imageです。
Docker Hubに公開されているものだけでなく、元となるファイル(名前をDockerfileにしておく)を自分で記述し新しいimageを作ることもできます。

今回は共有したいデータを持つ方のデータコンテナを自作で定義してみます。

Dockerfile
FROM centos

WORKDIR /mount-test
RUN echo "volume mount test" > mount_test.txt

なんとなくこういうルールなのかな、みたいなのは察していただけるかと思いますが
FROM:CentOSのimageであるcentosを元にして
WORKDIR:作業ディレクトリを移って
RUN:指定したコマンドを実行
のように順番に操作を書くのがDockerfileです。
既存のimageをベースに敷き、各コマンドの層を積み重ねていく感じで作られていきます。
今回はデータコンテナとしての役割を確かめるため、/mount-testディレクトリとその中にmount_test.txtファイルを作成しています。

このFROMRUNなどの命令は全部で20種類くらいあります。詳しくは公式のドキュメントなどをまた適宜ご覧ください。

参考
Dockerfile リファレンス

こうして書いたDockerfileをbuildすることで、Docker imageとして使えるようになります。

$ docker build ./ -t centos-volume

ここで./Dockerfileが今のディレクトリ階層にあり、-tbuildするimageに名前をつけることをそれぞれ指示しています。
以下のように表示されていれば成功です。

Sending build context to Docker daemon   42.5kB
Step 1/3 : FROM centos
 ---> <適当なハッシュ値1>
Step 2/3 : WORKDIR /mount-test
 ---> Running in <適当なハッシュ値2>
Removing intermediate container <適当なハッシュ値2>
 ---> <適当なハッシュ値3>
Step 3/3 : RUN echo "volume mount test" > mount_test.txt
 ---> Running in <適当なハッシュ値4>
Removing intermediate container <適当なハッシュ値4>
 ---> <適当なハッシュ値5>
Successfully built <適当なハッシュ値5>
Successfully tagged centos-volume:latest

これが最新バージョンだよ、と最後にはlatestタグまでつけてimage化してくれていますね。
タグとは例えば

$ docker pull centos:centos7

のように、Docker imageをバージョンなどの情報つきで指定する時に併記するために使います。
数字は中のミドルウェア・ソフトウェアのバージョンに対応してることが多いと思います。

ここでタグを指定しない時には、latestタグがついたimageを表します。
latestタグはそのimageを使いたい人みんなにとっていい感じの塩梅になるようなバージョンを選んでつけてくれている(?)とは思いますが、特定のバージョンを指定する必要がある場合も多いかと思います。

また今回は行いませんが、buildしたオリジナルのimageは$ docker pushを行うことでDocker Hubに登録することでオープンに共有ができます。
逆に自分だけが使えるようにしておきたい、あるいは業務などで特定の人にだけ限定公開したい場合は

  • Docker Hubにプライベートリポジトリを作成(2つ目以降は有料プラン)
  • クラウドのマネージドサービス(AWSならECR、GCPならGCRなど)を利用

のどちらかを選びます。

そして上記のbuildプロセスを見てお気づきかもしれませんが、Dockerfileから「コマンドを一行ずつ実行してはimage化」を繰り返して行われます。
そのため同じ命令がたくさんある場合には、中間生成されるimageが少なくて済むように\&&で繋いでひとまとめの命令にしておきましょう。
以下の例のようにRUN命令などが特に当てはまります。

RUN apt-get update && apt-get install -y \
  bzr \
  cvs \
  git \
  mercurial \
  subversion

参考・参照
Dockerfileを書くベストプラクティス

Docker Composeで複数コンテナをまとめて立ち上げる

Docker Composeは複数のコンテナをまとめて扱いたい時に便利です。
ファイル名をdocker-compose.yamlとしてComposeファイルのバージョンと各コンテナの定義を書いていきます。

docker-compose.yaml
version: '2'
services:

  data-container:
    image: centos-volume
    container_name: data-container
    tty: true
    volumes:
      - /mount-test

  centos1:
    image: centos
    container_name: centos1
    tty: true
    volumes_from:
      - data-container:ro

なんとなくimagecontainer_nameは分かりやすいかと思います。
versionはDockerではなくComposeファイルのバージョンです。
またtty: trueでポート待ち受けなど特に何もしないコンテナも立ち上げ後に起動させ続けることができます。
これが無いとコンテナがすぐに終了してしまいます。
そしてvolumes_fromではマウント元となるボリュームを読み取り専用でマウントするため、後ろに:ro(read only)とつけています。
マウント元のコンテナ名だけを書くか:rwと付けると読み書きできる権限が付与されます。

なおこのComposeファイルで指定できる項目はめちゃくちゃたくさんあるので、またドキュメントなどを適宜参照してください。

参考
Composeファイル バージョン2リファレンス
Composeファイル バージョン3リファレンス

あとはdocker-compose.yamlがあるディレクトリで

$ docker-compose up -d

とすれば、docker-compose.yamlと名前がつけられたファイルを探して読み込んでコンテナを立ち上げてくれます。
-dはバックグラウンド実行を指定しています。

Creating data-container ... done
Creating centos1        ... done

と表示されていればコンテナ作成は成功。

$ docker ps

で2つとも表示されていればちゃんと動いています。

続いて各コンテナが定義通り作られているかを確認してみましょう。
まずはデータコンテナの方に入り、Dockerfile内で作ったはずのmount_test.txtがあるかを見てみます。

$ docker exec -it data-container bash

[root@<皆さんのコンテナID> mount-test]# cat mount_test.txt 
volume mount test

ファイルはちゃんと作成されており、作業(カレント)ディレクトリがDockerfileの通り/mount-testになっていますね。
またこのディレクトリではvimなどでmount_test.txtを編集したり、新しいファイルを作ったりといった読み書き作業もできるかと思います。

次にexitコマンドでデータコンテナから抜け、データを覗く側のコンテナに入ります。

$ docker exec -it centos1 bash

[root@<皆さんのコンテナID> /]# cat mount-test/mount_test.txt 
volume mount test

データコンテナ(data-container)のディレクトリとその中身がちゃんと見えていますね。
今回はdocker-compose.yamlにてread onlyを指定しているので、マウントされたこの/mount-testディレクトリの中では既存ファイルの編集や新規ファイルの作成をしようとするとちゃんと怒られます。

最後に立ち上げたコンテナたちを停止、削除しましょう。
片付けるまでがハンズオンです。

$ docker-compose stop

docker-compose upしたコンテナ群をまとめて停止、

$ docker-compose rm

で削除できます。便利...。

さいごに

まだDocker始めて2週間ぐらいしか触ってないので、修正・追記すべき箇所などあるかと思います。
Compose3.x系ではこうすればいいよなどのアドバイスも含めありましたらよろしくお願いします^^

2
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
5