dockerさん、勘違いしてました。

木曜日, 3月 25, 2021

docker

t f B! P L

私が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

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

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

つまり、pull(ベースとなるimageの取得)とcreate(imageからのcontainerの作成)とstart(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 ls -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 createコマンドに付与する引数を書くファイルです。

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