思わせぶりなdocker

木曜日, 3月 25, 2021

docker

t f B! P L

思わせぶりなdocker

docker「そんなにつもりなかったんだけど…」

思わせぶりなdockerちゃんに、私は無事勘違いさせられてしまいました。

ですがこれからも仲良くやって行きたいので、最初に知っておきたかった〜っていう知識をまとめました。

Dockerfileの書き方とかは他のブログ等に素晴らしい記事がたくさんあるのでそっちを見てね。

ちなみにdocker歴短いのでまだ間違ってるかもしれません。

Dockerfileではコンテナは作れない

イメージとコンテナの違いを理解していないことによる勘違いです。

基本的にはdocker hubに上がっているイメージをベースに、自分のアプリケーションに必要なパッケージなどを追加インストールするという処理をDockerfileに書きます。
こうすることで、環境構築をコードで管理することができる、というのがdockerを使う理由でもあります。

ただし!Dockerfileで作れるのは「イメージ」です!
docker hubのイメージをベースにした新しい何か作っているので、一瞬ここでコンテナなるものができるのか???と勘違いしてしまうところなのですが、Dockerfileではあくまでイメージしか作れません。

イメージというのは、例えばUbuntuなどを、dockerではなく普通のローカルマシンにインストールするときにダウンロードするあれ(isoファイル)です。

つまり、イメージはOSの素みたいなもので、それをコピーしていくつものマシンにインストールすることができます。

この「いくつものマシン」の部分をコンテナに読み替えます。
同じイメージAから、コンテナ1、コンテナ2、コンテナ3などの別々のコンテナを作れます。

docker runが有能すぎた

地味な方法でコンテナを作ってみましょう。

# docker hubからベースとなるイメージをpull
sudo docker pull hello-world:latest

# Dockerfileへ書き込む
echo 'FROM hello-world:latest' > Dockerfile

# あくまでイメージをビルドするだけ
sudo docker build -t hello-test:latest .

# いよいよイメージを素にコンテナを作る(nameは適当に)
sudo docker container create \
--name hello_test_0 hello-test:latest

# コンテナを起動する
sudo docker container start hello_test_0
# 一瞬で終了するけど

つまり、pull(ベースとなるimageの取得)とbulid(Dockerfileからマイimageの作成)とcreate(imageからのcontainerの作成)はそれぞれ別ということ。

しかし、docker runというコマンドは有能すぎるあまり

sudo docker run hello-world

この1行だけで、上記全部の処理を勝手にやってくれてしまう。

これはこれで便利なのだが、例えばdockerを使っている何らかのプロジェクトでは、READMEに起動方法としてdocker runしか書かれていないケースも多々ある。

docker runはcreateもしてくれるため、これを複数回実行すると毎回新しいcontainerできる。

例えば、runで作ったコンテナの中で作業して、コンテナの中に何らかのファイルを保存していたとする。

しかし、2回目以降のdocker runでは、別のコンテナが作成されるため、前のdocker runで作成したコンテナ内のファイルにはそもそもアクセスできない。

私は、2回目以降もdocker runをしてしまい、
前の作業結果消えてるやんけ!!!!
と混乱したことがある。

もちろん、別のコンテナを新しく作っているだけなので、コンテナの中身が消えているわけではないが。

とまぁ、このようにrunが有能すぎるあまり(3回目)、pull, bulid, createという流れが見えにくくなっている気がする。

コマンド体系がリニューアルされてる

謎にコマンドが2パターンある。

# 起動しているコンテナを見るとき
sudo docker container ps -a
sudo docker ps -a

# ローカルにあるイメージを見るとき
sudo docker image ls
sudo docker images

まぁコマンドが乱立してきたので整理しようということで、image関連のコマンドはimage下に、container関連のコマンドはcontainer下へ再編されたらしい(結構前に)。

詳しくは「docker コマンド 新旧対照表」とかでぐぐると良さそう。
基本的には新コマンドのimage, containerに再編されたコマンドを使うのが良さそう。

良さそう。

Dockerfileとdocker-compose.ymlの違いがよくわからない

よくわからないときた。もう勘違いですらない。

最初は、なぜ設定ファイルが2つもあるのか?とか1個にまとめろよ・・・とか思ってました。

役割が別です。
すごくざっくりいうと

Dockerfileは、上で説明した通り、imageを作成するためのものです。containerとは関係ありません。

対して、docker-compose.ymlは、containerを作成するためのものです。

docker-compose.ymlとは、つまるところコンテナ生成時のdockerコマンドに付与する引数を書くファイルです。

そもそも、docker create/runする際に、引数で色々指定できます。
私がよく使うところでいうと、コンテナ名(–name)、マウント(-v)、ポートマッピング(-p)などです。

docker create -p 9999:8888 \
-v /home/user/myspace:/workspace \
--name mycontainer1 myimage:latest

上記の例では、

  • ホストマシンの9999番ポートを、コンテナの8888番ポートにマッピング
  • ホストマシンの/home/user/myspaceを、コンテナの/workspaceにマウント
  • イメージmyimageを素に、コンテナ名mycontainer1というコンテナを作成
    ということをしています。

この引数たちをyamlで記述したファイルがdocker-container.ymlです。

いやいやシェルスクリプトでよくね?って思いまして、
ここで紹介した範囲だとシェルスクリプトでも対応可能なのですが、
docker-compose.ymlは、複数のコンテナの起動情報を1つのファイルで管理することを目的としているようです。

例えば、wordpressコンテナとmysqlコンテナとか同時起動したいですよね。
その設定をまとめてdocker-compose.ymlに書くわけです。

まぁこれすらシェルスクリプトでよくね?なんですが(複数行に分けて書けばいいので)
yamlで可読性高く書けるというのと、公式機能にあやかるほうが安牌というところだと思います。

QooQ