コンテナ技術はよく仮想環境と比較されることが多いようですが、ウェブサーバー、アプリケーションサーバー、データベースサーバーの3階層システムで考えるとわかりやすいかと思います。
システムを構築するのに従来は、各サーバーごとにインフラ、OS、ミドルウェア、アプリと構築していましたが、仮想化の登場で1台のサーバーで3階層を構築することが可能になりました。そして、Dockerの登場で仮想化よりも管理するレイヤーが減り、ミドルウェアとアプリの2層だけになりました。この2層をコンテナとしてDockerEngineは管理しています。さらに先ほども言った通り、Dockerはこのコンテナをコードで管理しているのです。
###Immutable Infrastructure
一度セットアップしたサーバーには二度と変更を加えないというDockerの運用概念です。この概念のおかげでコンテナ内は不変のサーバー基盤環境として動作するので、開発者にとっては利便性が増します。
実際にコンテナの中身を覗いてみると、ファイルシステムが存在しています。
$ docker exec -it コンテナ名 ls /
#実行結果
bin etc lib mnt root sbin sys usr
dev home media proc run srv tmp var
もう一つは、自分でオリジナルな環境を構築したい(たとえば、自分でパッケージを厳選してダウンロードしたり、コンテナ起動時にはあるコマンドを実行したり)という場合にDockerfileを記述して、それをdocker buildのコマンドでイメージにしてコンテナを作る方法です。
以下は[チュートリアル](http://docs.docker.jp/get-started/part2.html)で使われていたDockerfileです。python:2.7-slimという親イメージをもとにオリジナルのコンテナ環境を作成しています。# 公式 Python ランタイムを親イメージとして使用
FROM python:2.7-slim
# 作業ディレクトリを /app に設定
WORKDIR /app
# 現在のディレクトリの内容を、コンテナ内の /app にコピー
ADD . /app
# requirements.txt で指定された必要なパッケージを全てインストール
RUN pip install -r requirements.txt
# ポート 80 番をコンテナの外の世界でも利用可能に
EXPOSE 80
# 環境変数の定義
ENV NAME World
# コンテナ起動時に app.py を実行
CMD ["python", "app.py"]
###~代表的なdockerコマンド~
docker pull <イメージ名>
DockerHubに公開されているイメージをローカルにダウンロード
docker push <ユーザー名>/<レポジトリ名>:<タグ名>
自分がDockerfileで作成したイメージなどをDockerHubに登録
docker images
リポジトリ内のイメージを表示
docker run <イメージ名>
イメージをもとにコンテナを作成、起動
docker build -t <イメージ名> .
カレントディレクトリの Dockerfile でイメージ作成
docker container ls or docker ps
全ての実行中コンテナを表示
##Docker Compose
複数のコンテナを起動するのに、1コンテナずつ起動していては面倒なので、docker-composeコマンドを利用しましょう。docker-composeコマンドはYAML形式で定義されたファイルをもとに複数コンテナを起動します。
version: '2'
services:
db:
#DockerHubからpostgresイメージからコンテナを起動
image: postgres
web:
#カレントディレクトリにあるDockerfileをもとにコンテナを起動
build: .
#コンテナ起動時のコマンド
command: python manage.py runserver 0.0.0.0:8000
#カレントディレクトリを/codeにマウント
volumes:
- .:/code
#ポートを公開する(ホスト:コンテナ)
ports:
- "8000:8000"
#dbへのコンテナ間通信を可能にする
links:
- db
Dockerネットワーク
Compose のネットワーク機能 — Docker-docs-ja 17.06.Beta ドキュメント
マルチホストでのDocker Container間通信 第1回: Dockerネットワークの基礎 - UZABASE Tech Blog
マルチホストでのDocker Container間通信 第2回 Port Forwarding と Overlay Network - UZABASE Tech Blog
マルチホストでのDocker Container間通信 第3回: Kubernetesのネットワーク(CNI, kube-proxy, kube-dns) - UZABASE Tech Blog
コンテナ間ネットワークについて
IPマスカレード(NAPT)…1つのグローバルIPアドレスを複数のプライベートIPアドレスと紐づけて変換する機能。
基本
- docker-composeの場合、同一ホスト上に存在するコンテナはデフォルト上のネットワーク(ディレクトリ名_default)でdocker0というブリッジ(bridge)を介して、すべてのコンテナ間で通信ができるようになリマス。ブリッジは外部通信との架け橋にもなります。ネットワーク確認コマンド
docker network ls
で見つけられる標準のネットワークは以下3つです。
- none...外部ネットワークなし。
- host...Dockerホストと同じIPアドレス、インタフェースを持つ。
- bridge...Dockerホストとは異なる内部ネットワークを構築し、vethでdocker0インタフェースとDockerホストのインターフェースと接続する。
-
コンテナに割り振られたIPアドレスは起動するたびに異なりますが、コンテナのホスト名で指定することで名前解決して通信を行えるようになります。
-
ports
で指定した場合はDockerホスト側のネットワークインターフェースからもアクセス可能です。 -
links
を使えばコンテナのホスト名にエイリアスを割り当てることが可能です。
ネットワークをカスタマイズする
ドライバーを適用してオリジナルのネットワークを作成することができます。
ドライバーのデフォルトは単一ホスト上ならbridge, Swarm上であればoverlayを使うと良いそうです。
(ネットワーク・プラグインを使えばDockerEngineが拡張されて、プラグインを使ったネットワークを構築することができるらしい…)
# カスタムネットワークを作成
$ docker network create --driver [ドライバー名] [ネットワーク名]
# コンテナをそのネットワークで動かす
$ docker run --net=[ネットワーク名]
docker-composeでカスタム・ネットワーク設定
基本的にディレクトリ名_defaultでネットワークを作成することができます。
それでも、オリジナルでネットワークを作成した場合は以下のサンプルを参照にしてください。
version: '2'
services:
proxy:
build: ./proxy
networks:
- front
app:
build: ./app
networks:
- front
- back
db:
image: postgres
networks:
- back
networks:
front:
# Use a custom driver
driver: custom-driver-1
back:
# Use a custom driver which takes special options
driver: custom-driver-2
driver_opts:
foo: "1"
bar: "2"
マルチホストでコンテナを管理する
Dockerネットワークはプライベートネットワークのため、異なるホストにあるコンテナには通常アクセスすることができません。
参考にさせていただいた記事では対応策としては以下が挙げられていました。
- Port Forwarding...接続元のContainerが接続先のContainerのホストのIPを知っていることが前提
- Overlay Network...Overlay Network構築して同じネットワークに属するようにする
- flannel...ホストに動的IPが割り振られている場合は適用不可
ただどれもイマイチなので、
=> Kubernetes の登場へと続く…
Docker SwarmもKubernetesと同じく、複数のDocker環境を管理できるオーケストレーションツールです。環境のスケールをより効率的に行うことができますが、Kubernetesの方が優勢です。
以下の記事でDocker Swarmの具体的なイメージがつかめるかと思います。
Docker Swarm 入門ハンズオン
ローカルでDockerを実行したい
リモート・システム上に Docker ホストをプロビジョンしたい
以下はDockerが使用できるAWS EC2環境をdocker-machineコマンドを用いて作成する手順です。(前提条件:アクセスキーとシークレットアクセスキーを取得するのは必須)
Docker Machine:Amazon Web Services (AWS) EC2 の例
#1,AWS EC2環境を作成
docker-machine create --driver amazonec2 --amazonec2-access-key YOUR_ACCESS_KEY --amazonec2-secret-key YOUR_SECRET_KEY aws-test
#2,Docker Machine環境をアクティブにする
eval $(docker-machine env aws-test)
#3,Docker Machine環境を停止する
docker-machine stop aws-test
#4,Docker Machine環境を再開する
docker-machine start aws-test
# TLS証明書を発行する
docker-machine regenerate-certs aws-test
# SSH接続する
docker-machine ssh aws-test