Skip to content

基礎から理解する Docker

  • Docker

📅 2020-06-27

⏱️ 10 min read

はじめに

業務で使用している Docker の仕組みや全体感といった基礎的な理解したかったのでまとめてみた。

内容としては、前半で理論的なことを軽くさらって、後半では公式のチュートリアルを題材として実際にローカルで Docker を動かしながら動かすといった形となっている。

key value
開発元 Docker, Inc.
公式サイト Empowering App Development for Developers | Docker
GitHub docker/docker-ce
プログラミング言語 Go
対応 OS Linux / macOS / Windows

対象読者

  • Docker を使ったことがない
  • 導入してみたいが学習コストを気にして導入に漕ぎ着けていない人
  • あまり理解していないがなんとなくで使ってるいる人

Docker とは何か

結論から言うと、Docker とは「コンテナ型仮想化技術」を利用してアプリケーションを開発・運用するためのプラットフォームだ。

いきなり「コンテナ型仮想化技術」という単語が出てきた。よく PC に仮想環境を構築するなど言うので、仮想化という単語は聞き覚えはあると思うが、「コンテナ型仮想化技術」は従来の仮想化とどう違うのだろうか。

これまでの仮想化技術、そしてコンテナへ

ここでは、PC(ホスト OS )に仮想化ソフトを使ってゲスト OS を配置する従来型の仮想化と、Docker が実現するコンテナ仮想化技術を比較することでコンテナ仮想化技術の理解していく。

従来型仮想化

traditional-virtualization

ホストマシン上にハイパーバイザーを通して、ゲストマシンを動かす。基本的にホストマシンのリソースをゲストマシンに共有する形になる。VirtualBox などの仮想化ツールを使用して行うことが多く、立ち上げたゲストマシンの中で実際に必要なミドルウェアやライブラリをセットアップしていくことになる。

コンテナ型仮想化

container-virtualization

一方でコンテナ型仮想化は、ホストマシンのカーネルを利用して、Docker Engine からコンテナを構築する。コンテナのプロセスやユーザは、ホストマシンとは隔離され独立して動作するので、あたかもホストマシン上でゲストマシンが立ち上がっているかのような振る舞いを見せる。

また OS を独自で準備する必要もなく、リソースを無駄に使うことがないので動作が軽く高速というのも特徴だ。

コンテナが解決する課題

さて、従来の仮想化と比較して構成にどういう違いあるのかが分かったところで具体的にコンテナを使うことで何が嬉しいのだろうか。調べると色々あったが中でも「環境構築のプロセスをコード化して、共有できる。」という点が非常に大きいのではないかと思う。

詳しく説明すると、従来の仮想環境構築ではゲスト OS に入ってからライブラリやミドルウェアをインストールする必要がある。その作業は、コマンドを叩いて手作業で行うため、ミスやバージョンの違いなどが発生する恐れがある。また、同じ開発チーム内のメンバー同士でもローカル環境に差異が生じてしまう可能性がある。

一方で Docker を用いたコンテナ仮想化ではコンテナの定義を Dockerfile という一つのファイルで定義する。開発チームでは、そのファイルを共有するだけで手元のローカルには同じ環境が作 ることができる。

この話は開発だけではなく、プロダクトの提供にも影響がありそうだ。一般的にプロダクトをリリースするとなると検証環境、ステージング環境、本番環境とインフラを用意することが多いと思います。しかし、デプロイフローをちゃんと決めていても検証環境、ステージング環境では起きないはずの障害がなぜか本番環境だけで起きてしまう、なんてことを経験した開発者は多いのではないだろうか。Docker を用いることで、全ての環境で同じコンテナが動作する環境が作ることができるため、論理的にはそのような現象は起きない。

実践してみる

いよいよ実際に Dockerfile を書いて動かしていきます。今回利用するソースコードは公式チュートリアル 1 にあるものをそのまま利用する。今回は基礎理解が目的なので、触りまでだがもっと先まで学んでみたいという方は是非そちらをご活用いただければと思う。

Hello world

何はともあれ Hello world 。

# ローカルのマシンに docker が入っているか確認
$ docker --version
Docker version 19.03.8, build afacb8b

# `docker run`イコマンドでメージからコンテナを起動
$ docker run hello-world
# ローカルに指定したイメージがない場合は、docker hub より自動でインストールされる
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
0e03bdcc26d7: Pull complete
Digest: sha256:d58e752213a51785838f9eed2b7a498ffa1cb3aa7f946dda11af39286c3db9a9
Status: Downloaded newer image for hello-world:latest
# イメージが作られ Hello world と出力された
Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

# `docker image` コマンドでイメージの一覧を確認
$ docker image ls
REPOSITORY            TAG                 IMAGE ID
hello-world           latest              bf756fb1ae65        1 minutes ago        13.3kB

# `docker ps` コマンドでプロセスを確認
$ docker ps --all
c0d1570f2fc2        hello-world           "/hello"                 8 minutes ago       Exited (0) 8 minutes ago

細かいところを全部理解しなくて良いので、ここではイメージを取得してコンテナを起動するというざっくりとした流れを掴むのが重要。

Dockerfile の作成

公式で用意されているイメージをカスタマイズしていく。その場合、カスタマイズする内容を Dockerfile というファイルを作成して定義する。

# 公式の Python がインストールされたベースイメージを利用
FROM python:2.7-slim

# コンテナ内の作業ディレクトリを /app に設定
WORKDIR /app

# 現在のディレクトリの内容を、コンテナ内の /app にコピー
COPY . /app

# requirements.txt で指定された必要なパッケージを全てインストール
RUN pip install --trusted-host pypi.python.org -r requirements.txt

# ポート 80 番をコンテナの外でも利用可能に設定
EXPOSE 80

# 環境変数を定義
ENV NAME World

# コンテナ起動時に app.py を実行
CMD ["python", "app.py"]

次は、コンテナ上で動かすアプリケーションとして Python ファイルを app.py という名前で作成し、下記のようにする。

from flask import Flask
from redis import Redis, RedisError
import os
import socket

# Connect to Redis
redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2)

app = Flask(__name__)

@app.route("/")
def hello():
    try:
        visits = redis.incr("counter")
    except RedisError:
        visits = "<i>cannot connect to Redis, counter disabled</i>"

    html = "<h3>Hello {name}!</h3>" \
           "<b>Hostname:</b> {hostname}<br/>" \
           "<b>Visits:</b> {visits}"
    return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname(), visits=visits)

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=80)

最後にコンテナ上にインストールしたいライブラリ、ミドルウェアを requirements.txt というテキストファイルに書き出して Dockerfile から参照できるようにしておく。

Flask
Redis

準備が整ったところで、それらを実行する。

# 現在このような状況になっている
$ ls
Dockerfile		app.py			requirements.txt

# 作った Dockerfile をビルドして、イメージを作成
# `--tag` オプション: イメージにタグを付与
$ docker build --tag=friendlyhello .
Sending build context to Docker daemon   5.12kB
Step 1/7 : FROM python:2.7-slim

...

略

...

Successfully built 8f74a6392754
Successfully tagged friendlyhello:latest

# ビルドが終わったら、一旦イメージの一覧を確認
$ docker image ls
REPOSITORY            TAG                 IMAGE ID
hello-world           latest              bf756fb1ae65
friendlyhello         latest              326387cea398

# イメージが作成されているのを確認できたらコンテナを起動
#  `-d` オプション: コンテナをバックグラウンドで実行
#  `-p` オプション: ポートの割り当てを指定
$ docker run -d -p 4000:80 friendlyhello

$ docker ps コマンドでステータスが Up になっていれば無事にコンテナが動いているはずだ。また、ブラウザで localhost:4000 にアクセスすると Hello world とコンテンツが表示されているのも確認できるかと思う。

Dockerfile を書いて、自分が用意したいアプリケーションの実行環境を( Docker イメージ )作り、コンテナ 上で動かすということを一通りできた。

まとめ

  • Docker とは「コンテナ型仮想化技術」を提供するソフトウェアプラットフォームである
  • コンテナ型仮想化技術とは、従来の仮想化技術に取って代わるデファクトスタンダードになりつつある
  • Docker は環境構築のプロセスをコード化し、効率化することを実現
  • またその仕組み上、軽量かつ高速なアプリケーション実行環境を提供

業務ではほとんどのプロジェクトで Docker を導入しており、今後も使う機会は増えてくると思うので、このタイミングで概念や良さについて振り返ることができて良かったと思う。

参考にさせていただいたサイト

← PrevNext →
  • © ysmtegsr 2019 - 2021