Monors Note

Pythonとそれ以外いろいろ

Dockerに今さら入門してみる(Part 1)~環境構築とコンテナの使用方法~

「Dockerを使えば簡単に環境構築出来るよ」と耳にタコが出来るほど聞くけど、「フーン、そうなんだ」と聞き流していました。 「新年度も始まったし新しいことに挑戦するか」ということで今さらですが、Docker入門をしてみました。

書いていることに誤りがある場合は、ご指摘頂けるとありがたいです。

Part 1では環境構築とコンテナの操作を行っています。

Dockerとは

Dockerとは、Linuxのコンテナ技術をベースに作成された、仮想化技術のことです。

  • コンテナとは?
    • ホストOS上のKernel機能を追加複数のrootファイルシステムを実行出来るようにするもの。
    • ザックリ言ってしまえば、Linux環境上で複数の環境を構築出来るということ。(多分。。)
    • コンテナはimageから生成される

また、公式ページでのコンテナの説明

A container is launched by running an image. An image is an executable package that includes everything needed to run an application--the code, a runtime, libraries, environment variables, and configuration files. コンテナはimage

何がうれしいの?

1, 軽量

Dockerが主流になる前までは、VirtualBoxなど従来のハイパーバイザ型の仮想化が主流でした。 (ハイパーバイザー)http://wa3.i-3-i.info/word12196.htmlという仮想マシンをホストOS上に作成するし、その上にホストOSを稼働させる方式です。 これによりホストOSとゲストOSの分離を実現していました。 しかし、仮想マシンとゲストOSの(イメージファイル)http://wa3.i-3-i.info/word15853.html必要になりオーバーヘッド増えます。

Dockerは各アプリケーションをLinuxのコンテナ技術によって、

ホストOSのKernelは共有しつつも、各コンテナ内のアプリケーションを分離した名前空間の中で実行できます。

さわって理解するDocker入門 第1回 | オブジェクトの広場

(コンテナで区切られた空間それぞれに別のバージョンのMySQLが存在しても競合しない) 単に名前空間を分離しているだけなので、仮想マシンのエミュレーションも行われないため、イメージサイズも抑えられ 軽量化が可能です。

f:id:jsakusan:20180429001720p:plain (https://www.ogis-ri.co.jp/otc/hiroba/technical/docker/part1.htmlより)

2. 様々な環境にデプロイできる

Windows, Macをはじめ、AWSなど様々な環境で動作させることが可能です。

環境構築

実行環境

DockerToolboxのインストール

ここから、DockerToolboxをインストール docs.docker.com

インストールのマニュアルは以下を参照 docs.docker.com

動作確認のためコマンドを入力

$ docker info
error during connect: Get http://%2F%2F.%2Fpipe%2Fdocker_engine/v1.37/info: open //./pipe/docker_engine: The system cannot find the file specified. In the default daemon configuration on Windows, the docker client must be run elevated to connect. This error may also indicate that the docker daemon is not running.

エラーが発生したため、、、 dockerでネットワークエラー - This is a Penを参考に解決。 1. Dockerマシンの再度作成

$ docker-machine rm default
$ docker-machine create default --driver virtualbox
  1. 環境変数を設定
eval` "$(docker-machine env default)"`

実行したら、以下の様なメッセージが出た。

Error checking TLS connection: Error checking and/or regenerating the certs: There was an error validating certificates for host "192.168.99.103:2376": x509: certificate signed by unknown authority
You can attempt to regenerate them using 'docker-machine regenerate-certs [name]'.
Be advised that this will trigger a Docker daemon restart which might stop running containers.

言われるがまま、docker-machine regenerate-certsを実行。 再度、環境変数の確認。

$ sudo eval` "$(docker-machine env default)"`
bash: export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://192.168.99.103:2376"
export DOCKER_CERT_PATH="C:\Users\Shusaku SAHASHI\.docker\machine\machines\default"
export DOCKER_MACHINE_NAME="default"
export COMPOSE_CONVERT_WINDOWS_PATHS="true"
# Run this command to configure your shell:
# eval $("C:\Program Files\Docker Toolbox\docker-machine.exe" env default): No such file or directory

その後、言われるがまま、

eval $("C:\Program Files\Docker Toolbox\docker-machine.exe" env default):

を実行したら治りました。

公式チュートリアルをやってみる。

Docker公式サイトのチュートリアルをこなしていきます。 docs.docker.com 公式文章を読んでいると、コンテナはimageから生成されるらしい。

Dockerのバージョンを確認する

> docker --version
Docker version 18.03.1-ce, build 9ee9f40

Dockerコンテナのインストール

Dockerのコンテナイメージのインストールを行う。 今回インストールを行うのはhello-world

> docker run hello-world

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
9bb5a5d4561a: Pull complete
Digest: sha256:f5233545e43561214ca4891fd1157e1c3c563316ed8e237750d59bde73361e77
Status: Downloaded newer image for hello-world:latest

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 a     mbitious, 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/engine/userguide/

Docker上でアプリケーションを動かく際の構成

Dockerでアプリケーションを作成する際には、場合により3つの階層構造を構成する必要があるみたいです。(下に行くほど低レイヤー)

  • Stack
    • サービスをどのようにインターラクションするか。
  • Service
    • プロダクト内の各コンテナをどの様に動かすかを決める。
  • Container <- ここからチュートリアルが始まります。

Dockerfileの作成

  • Dockerfileはコンテナ内の環境を定義するファイル。
  • ネットワークインターフェイスやデスクドライブはDockerホスト内にすでに存在する。
  • ポートマッピングやオレオレファイルのコピーは自分で行ってね! <- これを行うのがDockerfile
  • 一度Dockerfileを作ってしまえば、同様の設定を持つコンテナをコピーすることが可能。
  • Dockerfileで環境を作成した後に、Pythonなどのアプリ系をいれる。

Dockerfileを書いてみる。

Dockerfile リファレンス — Docker-docs-ja 17.06.Beta ドキュメントを参考にしならが、一部コマンドの解説を入れています。 下記の3ファイルを同じフォルダに格納する。

# Use an official Python runtime as a parent image
FROM python:2.7-slim

# Set the working directory to /app
WORKDIR /app

# Copy the current directory contents into the container at /app
ADD . /app

# Install any needed packages specified in requirements.txt
RUN pip install --trusted-host pypi.python.org -r requirements.txt

# Make port 80 available to the world outside this container
EXPOSE 80

# Define environment variable
ENV NAME World

# Run app.py when the container launches
CMD ["python", "app.py"]

FROM命令で(ベースイメージ)http://docs.docker.jp/glossary.html#base-imageを指定します。ベースイメージとは、親イメージを持たないイメージのことです。

RUN命令は既存イメージ上の新しい例やで、あらゆるコマンドを実行しその結果をコミットする命令です。

CMD命令は、コンテナ実行時のデフォルトを提供します 。 CMD ["パラメータ1", "パラメータ2"...]と指定することで起動時のパラメータを定義

Dockerは、カーネルの上に多階層のImageレイヤーがあり、一番下にベースとなるImageがあります。これは概ね、DebianとかUbuntuなどのOSに相当する部分です。そして、この上に、ミドルウェアの層が重なります。たとえば、emacsApacheなどです。それぞれのレイヤーは、下位のレイヤーを参照しています。下位のレイヤーは読み取り専用です。また、最上位のレイヤーは、書き込みできるようになっていて、下位のレイヤーに機能を付け足して独自のImageになりえます。この書き込む操作がCommitです。 https://cdn-ssl-devio-img.classmethod.jp/wp-content/uploads/2016/05/screenshot-2016-05-01-2.46.19-640x359.png https://cdn-ssl-devio-img.classmethod.jp/wp-content/uploads/2016/05/screenshot-2016-05-01-2.46.19-640x359.png dev.classmethod.jpより

requirements.txt

Flask
Redis

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)

Dockerfileからimgaeファイルの作成をする。また、requirement.txtapp.pyはADDコマンドに使用する。

Docker imageを作成する。

docker build -t friendlyhello .

Dockerでアプリを立ち上げる。

docker run -p 8000:80 driendlyhello -pオプションで、外部からアクセスされるポート番号:コンテナ側のポート番号を指定 今回の場合、PCのポートを4000として、コンテナ側のポート番号を80とている。

ブラウザでlocalhost:4000へアクセスしてみたが、このサイトにアクセスできませんと出た。 これは、Dockerのアドレスにアクセスしていないから。 (VirtualBoxを使用していない場合は、localhost:4000でアクセス可能。)

qiita.com

上記を参考に、dockerのアドレスを取得

docker-machine ip
192.168.99.103

http://192.168.99.103:4000で起動を確認できた。

本来は-bオプションを付けていないのでCTRL + Cでストップするはずなのだが、 Windowsの場合は明示的にstopコマンドを入力しないとコンテナが止まらないらしい。

コンテナをバックグラウンドで実行・停止

-bコマンドでバックグラウンド実行が可能。 docker run -b -p 4000:80 friendlyhello

また、停止したいときはstopコマンドを使用する。 しかし、コマンドではcontainre idが必要なため、docker container lsでidを取得する。

$ docker container ls
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                  NAMES
af241aaad6d1        friendlyhello       "python app.py"     16 minutes ago      Up 16 minutes       0.0.0.0:4000->80/tcp   admiring_morse

$ docker stop af241aaad6d1
af241aaad6d1

参考