20
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

iRidgeAdvent Calendar 2018

Day 22

はじめてのDocker(基本編)

Last updated at Posted at 2018-12-22

この記事はiRidge Advent Calendar 2018の22日目の記事です。

はじめに

2018年8月に転職し、初めてDockerなるものを触ることになりました。
https://docker-curriculum.com/ に沿ってキャッチアップし、
その中で学んだ知識を整理しましたので共有したいと思います。私と同じようにDockerに入門する方の役に立てば幸いです。

用語

  • イメージ - コンテナの基礎をなすアプリケーションの設計図。
  • コンテナ - イメージから作成され、実際にアプリケーションが稼働する。
  • Dockerデーモン - Dockerコンテナの構築、実行、及び配布を管理する、ホスト上で実行されるバックグラウンドサービス。デーモンはクライアントと通信するOSで実行されるプロセス。
  • Dockerクライアント - ユーザがデーモンと対話できるようにするCLIツール。
  • DockerHub - Dockerイメージのレジストリ。必要に応じて独自のDockerレジストリをホストし、イメージを取得するために使用できる。

コマンド

  • docker pullコマンドでbusyboxという名称のimageをDockerレジストリから取得する。
$ docker pull busybox
  • docker imageコマンドで、取得したイメージをリスト表示する。
  • TAGはイメージの特定のスナップショットを参照していて、IMAGE IDはそのイメージのユニークな識別子となっている。
$ docker images
REPOSITORY                    TAG                 IMAGE ID            CREATED             SIZE
nginx                         alpine              d3dcc25e0dc4        12 days ago         17.8MB
busybox                       latest              59788edf1f3e        6 weeks ago         1.15MB
hello-world                   latest              4ab4c602aa5e        2 months ago        1.84kB
ubuntu                        latest              735f80812f90        3 months ago        83.5MB
nginx                         latest              c82521676580        3 months ago        109MB
python                        2.7.14-slim         a7804e68bf72        6 months ago        139MB
  • ubuntuの特定バージョンをpullしたい場合は、以下のようにする。
$ docker pull ubuntu:12.04
12.04: Pulling from library/ubuntu
d8868e50ac4c: Pull complete
83251ac64627: Pull complete
589bba2f1b36: Pull complete
d62ecaceda39: Pull complete
6d93b41cfc6b: Pull complete
Digest: sha256:18305429afa14ea462f810146ba44d4363ae76e4c8dfc38288cf73aa07485005
Status: Downloaded newer image for ubuntu:12.04
$ docker images ubuntu
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              latest              735f80812f90        3 months ago        83.5MB
ubuntu              12.04               5b117edd0b76        19 months ago       104MB
  • docker runコマンドでbusyboxイメージのDockerコンテナを起動する。
$ docker run busybox
$

このとき、Dockerクライアントはイメージを探し、コンテナ内でコマンドを実行する。
でも、上のコマンドでは実行するコマンドを与えていないので、コンテナが立ち上がったあと何もせずに終了した。

以下のコマンドは上と違って、echoコマンドが実行された後に終了した。

$ docker run busybox echo "hello from busybox"
hello from busybox
$ 
  • docker psコマンドは現在起動中の全てのコンテナを表示する。
$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
  • -aオプションを付けると実行済みのコンテナも含め全てを表示する。
$ docker ps -a
CONTAINER ID        IMAGE                         COMMAND                   CREATED             STATUS                        PORTS                  NAMES
43daaba225dd        busybox                       "echo 'hello from bu…"    5 minutes ago       Exited (0) 5 minutes ago                             quizzical_ptolemy
04c83ee35767        busybox                       "sh"                      30 minutes ago      Exited (0) 30 minutes ago                            clever_swirles
7952dfa41dc4        hello-world                   "/hello"                  33 minutes ago      Exited (0) 33 minutes ago                            reverent_euler
  • コンテナ内で複数コマンドを実行したい場合は-itオプションを使用する。インタラクティブttyをコンテナ内でアタッチする。
$ docker run -it busybox sh
/ # ls
bin   dev   etc   home  proc  root  sys   tmp   usr   var
/ # uptime
 03:19:03 up  9:28,  0 users,  load average: 0.02, 0.06, 0.02
/ #
  • docker run --helpで、全フラグの一覧を見ることが出来る。

  • docker runを何度も実行してそのままにしておくと、ディスク領域を食いつぶしてしまうので、docker rmコマンドを実行すればコンテナを削除できる。

$ docker rm b99636fc4c19
b99636fc4c19
  • 終了済みのコンテナをいっぺんに削除したいなら、docker rm $(docker ps -a -q -f status=exited)とする。
    • -qはIDだけを返却し、-fは指定した状態のみでフィルタリングしている。
$ docker rm $(docker ps -a -q -f status=exited)
f28e03403d45
2f12ba39987b
e942ae377ecf
43daaba225dd
04c83ee35767
34efcecec10d
7952dfa41dc4
8a911e50170a
14656bae8192
020dff00d96e
  • 実はdocker container pruneコマンドで同様の結果が得られる。
$ docker container prune
WARNING! This will remove all stopped containers.
Are you sure you want to continue? [y/N] y
Deleted Containers:
bb45579d3020722abc88fd570400c10641e3db0a51cad0a6afc34421af67963e
41c78c7ee3fcc88ec1cff64ca69e827b36fdeb433cc7832dea518dde5e8593d3

Total reclaimed space: 0B
  • また、docker runコマンドに--rmフラグを付与して起動すると、終了時にコンテナが削除される。

  • もう必要ないimageはdocker rmiで削除できる。

$ docker rmi hello-world
Untagged: hello-world:latest
Untagged: hello-world@sha256:0add3ace90ecb4adbf7777e9aacf18357296e799f81cabc9fde470971e499788
Deleted: sha256:4ab4c602aa5eed5528a6620ff18a1dc4faef0e1ab3a5eddeddb410714478c67f
Deleted: sha256:428c97da766c4c13b19088a471de6b622b038f3ae8efa10ec5a37d6d31a2df0b

Webアプリケーションをデプロイしてみる

このデモ用のアプリケーションがレジストリにホストされているのでそれをダウンロードしてdocker runしてみる。

$ docker run --rm prakhar1989/static-site

イメージがローカルになければ、クライアントはまずレジストリからイメージをフェッチしてきて、それから起動する。
うまく行けばNginx is running...とターミナルに表示される。
ただ、この場合、どのポートも公開されていないので、ポートを公開するために以下の通りdocker runコマンドを再実行する必要がある。

$ docker run -d -P --name static-site prakhar1989/static-site
721f9bed9efbe569e17361fa327d2719ef01246de8f8894850896ff13ace34ff
  • -d:ターミナルのデタッチ

  • -Pはランダムなポートを公開し

  • --nameは起動するコンテナに名前を付ける。

  • docker port [CONTAINER]コマンドで、ポートを確認することが出来る。

$ docker port static-site
443/tcp -> 0.0.0.0:32768
80/tcp -> 0.0.0.0:32769
  • -p 8888:80のようにすることで、クライアントが接続を転送するカスタムポートを指定することも出来る。
$ docker run -p 8888:80 prakhar1989/static-site
Nginx is running...
  • docker stopコマンドにコンテナIDを与えて実行すると、デタッチしたコンテナの停止が出来る。このとき、起動時に指定した名前を使うことも出来る。
$ docker stop static-site
static-site

これを実サーバにデプロイするなら、単にDockerをインストールし、その上でDockerコマンドを実行すればよい。

Dockerイメージの作成

新しいDockerイメージを取得したい場合、DockerHubのようなレジストリから取得することも、自分で作成することも出来る。
DockerHub上には多数のイメージがある。また、イメージはCLIからdocker searchで検索することも出来る。

  • baseイメージとchildイメージの違い

    • baseイメージは親イメージを持たないもので、ubuntu、busybox、debianなど。
    • childイメージはbaseイメージを元に作成され、機能が追加されたもの。
  • officialイメージとuserイメージの違い

    • officialイメージは公式にメンテとサポートされているもの。
      • 通常は一語で、pythonubuntubusyboxhello-worldなどがそれにあたる。
    • userイメージは一般ユーザにより作成されシェアされているもの。
      • baseイメージに機能を追加している。
      • 通常、user/image-nameというフォーマットである。

よりよく理解するために、簡単なFlaskアプリケーションのイメージを作成してみる。
ロード時に毎回ランダムな猫のgifをディスプレイに表示するFlaskアプリケーションが作成されているので、ローカルにリポジトリをクローンする。

$ git clone https://github.com/prakhar1989/docker-curriculum
$ cd docker-curriculum/flask-app
# この手順はローカルで実施すること。dockerコンテナ内ではない

そして、今クローンしたWebアプリケーションのイメージを作成するために、Dockerfileを作成する。

Dockerfileとは、シンプルなテキストファイルで、Dockerクライアントがイメージを作成する時にコールするコマンドが記述されている。
また、Dockerfileに記述するコマンドはほとんどLinuxコマンドと同等であり、これは新しい構文をDockerfile作成のために新たに覚える必要はないということになる。

まずはじめに、Flaskアプリケーションと同フォルダに、Dockerfileという名前で空ファイルを作成する。
baseイメージとしてはpython3を使用する。特に、python:3-onbuildのpythonイメージを使用する。

FROM python:3-onbuild

とする。次に公開するポート番号を指定する。Flaskアプリケーションは5000ポートで動くので、それを指定する。

EXPOSE 5000

最後に、アプリケーションの実行のためのコマンドを指定する。単にpython ./app.pyと書く、CMDコマンドを使うと

CMD["python", "./app/py"]

と書ける。CMDで、コンテナに対して、起動時に実行すべきコマンドを指示している。

これで、イメージをビルド出来る。docker buildコマンドでDockerfileからDockerイメージを作成する。
-tオプションにタグ名を与え、Dockerfileを含むディレクトリの場所を指定する。

$ docker build -t kamihara/catnip .
Sending build context to Docker daemon  8.704kB
Step 1/3 : FROM python:3-onbuild
3-onbuild: Pulling from library/python
1c7fe136a31e: Pull complete
ece825d3308b: Pull complete
06854774e2f3: Pull complete
f0db43b9b8da: Pull complete
2d21c767035c: Pull complete
e10b68fb77e6: Pull complete
e2c0fb34dff3: Pull complete
e96bc319bce0: Pull complete
490280dbcfb7: Pull complete
Digest: sha256:76df62c122c910751d8cd3101f8e3da39efd4ee828686b7ff0b5a5b1d967553f
Status: Downloaded newer image for python:3-onbuild
# Executing 3 build triggers
 ---> Running in 431f3c96d745
Collecting Flask==0.10.1 (from -r requirements.txt (line 1))
  Downloading https://files.pythonhosted.org/packages/db/9c/149ba60c47d107f85fe52564133348458f093dd5e6b57a5b60ab9ac517bb/Flask-0.10.1.tar.gz (544kB)
Collecting Werkzeug>=0.7 (from Flask==0.10.1->-r requirements.txt (line 1))
  Downloading https://files.pythonhosted.org/packages/20/c4/12e3e56473e52375aa29c4764e70d1b8f3efa6682bef8d0aae04fe335243/Werkzeug-0.14.1-py2.py3-none-any.whl (322kB)
Collecting Jinja2>=2.4 (from Flask==0.10.1->-r requirements.txt (line 1))
  Downloading https://files.pythonhosted.org/packages/7f/ff/ae64bacdfc95f27a016a7bed8e8686763ba4d277a78ca76f32659220a731/Jinja2-2.10-py2.py3-none-any.whl (126kB)
Collecting itsdangerous>=0.21 (from Flask==0.10.1->-r requirements.txt (line 1))
  Downloading https://files.pythonhosted.org/packages/76/ae/44b03b253d6fade317f32c24d100b3b35c2239807046a4c953c7b89fa49e/itsdangerous-1.1.0-py2.py3-none-any.whl
Collecting MarkupSafe>=0.23 (from Jinja2>=2.4->Flask==0.10.1->-r requirements.txt (line 1))
  Downloading https://files.pythonhosted.org/packages/08/04/f2191b50fb7f0712f03f064b71d8b4605190f2178ba02e975a87f7b89a0d/MarkupSafe-1.1.0-cp36-cp36m-manylinux1_x86_64.whl
Installing collected packages: Werkzeug, MarkupSafe, Jinja2, itsdangerous, Flask
  Running setup.py install for Flask: started
    Running setup.py install for Flask: finished with status 'done'
Successfully installed Flask-0.10.1 Jinja2-2.10 MarkupSafe-1.1.0 Werkzeug-0.14.1 itsdangerous-1.1.0
You are using pip version 10.0.1, however version 18.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
Removing intermediate container 431f3c96d745
 ---> c14f035b14b0
Step 2/3 : EXPOSE 5000
 ---> Running in 86d209c4dec8
Removing intermediate container 86d209c4dec8
 ---> 3e48f1f15bc9
Step 3/3 : CMD ["python", "./app.py"]
 ---> Running in 6afca14ae3fc
Removing intermediate container 6afca14ae3fc
 ---> 82068b34e99b
Successfully built 82068b34e99b
Successfully tagged kamihara/catnip:latest

もし、python:3-onbuildイメージを持っていなければ、はじめにそのイメージをpullしてから、自分のイメージが作成される。

docker runでイメージを実行して、実際の動作を確認できる。
以下のコマンドで、コンテナ内の5000ポートを使用し外部に8888ポートを割り当てた。ポート8888を使ったURLでアプリの動作が確認できる。

docker run -p 8888:5000 kamihara/catnip
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)

AWSへのデプロイ

AWSへのデプロイをする前に、AWSがアクセス出来るレジストリにイメージを公開する必要がある。
以下のコマンドでDockerHubに公開できる。username/image_nameの形式が重要。

$ docker push kamihara/catnip
denied: requested access to the resource is denied

これが終われば、イメージをDockerHub上で見ることが出来る。
今イメージがオンライン上にあり、Dockerがインストール済みの人は誰でも、一コマンドでアプリを実行できる。

$ docker run -p 8888:5000 kamihara/catnip

Beanstalk

Elastic BeanstalkはAWSが提供しているPaaSで、もしHeroku、GAEなどを使っていたことがあれば馴染み深い。
EBは非常に直感的なCLIを備えているが、いくつかの設定が必要だ。簡単にするために、Web UIを使用してアプリケーションを起動する。

ここでのAWSコンソールの細かい操作説明は省略(※元サイトをご覧ください)するが、基本的にはいま作成したアプリケーションはコンテナ化されているので、ElasticBeanstalkに対してはコンテナの情報を伝えればよい。
Dockerrun.aws.jsonを簡単に見てみよう。ここではEBが使用するイメージ名とコンテナが開くポート番号を提供している。

Dockerrun.aws.json
{
  "AWSEBDockerrunVersion": "1",
  "Image": {
    "Name": "kamihara/catnip",
    "Update": "true"
  },
  "Ports": [
    {
      "ContainerPort": "5000"
    }
  ],
  "Logging": "/var/log/nginx"
}

このファイルをアップロードすればアプリケーションが準備できているはずだ。
EBのページを見れば、アプリが起動している事を示す緑のチェックマークがついているはず。

まとめ

Dockerの基本コマンドから始まり、簡単なDockerfileの作成、AWSのElasticBeanstalkへのアプリケーションデプロイまでをやりました。軽い気持ちで和訳メモを作り始めて、ボリュームの多さに心折れかけてました。
https://docker-curriculum.com/ のすごいところは、これで終わりではなくマルチコンテナ環境もカバーしているところです。
というわけで、明日はその2としてマルチコンテナ環境への入門編を書きたいと思います。

20
15
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
20
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?