search
LoginSignup
0

posted at

updated at

Docker, Docker Compose, Kuberenetes用語ベース入門

コンテナ

  • OSとカーネルは共有し、プロセスを分離する仕組み。
  • コンテナ上で実行されたソフトウェアは単に1つのプロセスとして稼働しているにも関わらず、
    コンテナ内のソフトウェアから見ると独立したOS環境を占有しているように見える

コンテナ vs サーバー仮想化

  • サーバー仮想化は複数のOSを同一のハードウェア上で実行する仕組み。
    • 「仮想マシン」上に「ゲストOS」を動作させる。
    • 例: Virtual box

サーバー仮想化技術の基礎 - Qiita
各仮想化技術の違いをざっと理解するッ!! - Qiita
[Cloud] 仮想化技術について

コンテナのメリット

  • 開発環境やステージング環境、プロダクション環境等、複数の環境間のアプリケーションの依存関係(ライブラリのバージョンのずれ等)を全てコンテナ内で完結でき、意識する必要がなくなる。
  • サーバー仮想化と比較するとゲストOSやハードウェアのエミュレートが不要となり、プロセス単位で稼働するため効率的。
    • アプリケーションを動かすために必要となるコンピューティングリソースの消費は少なくなる。
    • アプリケーションの起動も高速。

Docker

  • DockerfileによりDockerイメージをビルドし、そのイメージが元となるコンテナ内で作業orコンテナを実行することができる
  • アプリケーションや必要なファイルを、Dockerイメージに同梱して、コンテナとして実行していく。
    • 例: Node.jsベースのイメージ(Node.jsが実行できるように環境を整えたLinux)を利用し、npmでのモジュールインストールやビルド処理をコンテナ内で実行する。
  • 環境による差異が解消されたり、構成管理の容易さなどのメリットがある。

入門 Docker
7nohe/docker-lessons
Orientation and setup - Docker docs
インフラエンジニアBooks 30分でわかる「Dockerコンテナ開発・環境構築の基本」

Dockerfile

  • Dockerイメージを作り上げるために実行するコマンドを含めたファイル。
  • 主に以下のコマンドから構成される。
コマンド 説明
FROM 書式: FROM [--platform=<platform>] <image> [AS <name>]

イメージビルドのための処理ステージを初期化し、ベースイメージを設定する。
正しいDockerfileはFROMから始めなければない。
RUN 書式:
RUN <command>
RUN ["executable", "param1", "param2"]

現在のイメージの最上位の最新レイヤーにおいて、あらゆるコマンドを実行する。そして処理結果を確定する。結果が確定したイメージは、Dockerfileの次のステップにおいて利用されていく。
CMD 書式: CMD ["executable","param1","param2"]

Dockerfile ではCMDを1つしか記述できない。
CMDの主目的はコンテナの実行時のデフォルト処理を設定すること。
docker runにおいて引数を指定することで、CMDに指定されたデフォルトを上書きすることができる。
EXPOSE 書式: EXPOSE <port> [<port>/<protocol>...]

コンテナの実行時に、所定ネットワーク上のどのポートをリッスンするかを指定する。
実際にはポートを公開するものではなく、イメージ作成者とコンテナ実行者との間で取り交わすメモのようなもの。
どのポートを公開するつもりでいるのかを表わす。 コンテナーが実行されるときに実際にポートを公開するには、docker run-p フラグを利用する。
ENV 書式: ENV <key>=<value> ...

環境変数 <key><value> という値を設定する。
ビルドステージ内(FROM以降のコマンド)の環境において、環境変数の値は維持される。
COPY 書式: COPY [--chown=<user>:<group>] <src>... <dest>

<src>からファイルやディレクトリを新たにコピーして、コンテナ内のファイルシステムのパス<dest>に追加する。
<src>...として複数のファイルあるいはディレクトリが指定されている場合、そのパスはビルドコンテキストからの相対パスとして解釈される。
<dest>は絶対パスか、あるいは WORKDIRからの相対パスにより指定する。対象としているコンテナ内において、そのパスに対してソースがコピーされる。

ADDされるファイルやディレクトリのUIDGIDは、すべて0として生成される。
ただしオプションとして--chownフラグを用いると、引数に与えたユーザー空間、グループ名、あるいはUIDGIDの組み合わせによる指定が可能になり、特定の所有権を満たしたADDを行うことができる。
ENTRYPOINT 書式: ENTRYPOINT ["executable", "param1", "param2"]

コンテナを実行モジュールのようにして実行する設定を行うもの。

1. Dockerfile には、CMDまたはENTRYPOINTのいずれかが、少なくとも1つ必要。
2. ENTRYPOINTは、コンテナを実行モジュールとして実行する際に利用する。
3. CMDは、ENTRYPOINTのデフォルト引数を定義するために、あるいはその時点でのみコマンド実行を行うために利用する。
4. CMDはコンテナ実行時に、別の引数によって上書きされることがある。
EXPOSE 書式: EXPOSE <port> [<port>/<protocol>...]

コンテナの実行時に、所定ネットワーク上のどのポートをリッスンするかを指定する。
実際にはポートを公開するものではなく、イメージ作成者とコンテナ実行者との間で取り交わすメモのようなもの。
どのポートを公開するつもりでいるのかを表わす。 コンテナーが実行されるときに実際にポートを公開するには、docker run-p フラグを利用する。
USER 書式: USER <user>[:<group>] または USER <UID>[:<GID>]

ユーザー名(またはUID)と、オプションとしてユーザーグループ(またはGID)を指定する。
イメージが実行されるとき、Dockerfile 内の後続のRUNCMDENTRYPOINTの各コマンドにおいてこの情報を利用する。
WORKDIR 書式: WORKDIR /path/to/workdir

ワークディレクトリを設定する。
Dockerfile内にてその後に続くRUNCMDENTRYPOINTCOPYADDの各命令において利用することができる。WORKDIRが存在しないときは生成される。

WORKDIRはDockerfile内にて複数利用することができる。ディレクトリ指定に相対パスが用いられた場合、そのパスは、直前のWORKDIRからの相対パスとなる。
ARG 書式: ARG <name>[=<default value>]

変数を定義して、ビルド時にその値を受け渡す。 これはdocker buildコマンドにおいて--build-arg <varname>=<value>フラグを利用して行う。Dockerfile内において指定したビルド引数(build argument)が定義されていない場合は、ビルド処理時に警告メッセージが出力される。

オプションとしてデフォルト値を設定することができる。

ARGの変数スコープは、それが定義されたビルドステージが終了するときまで。
複数のビルドステージにおいてARGを利用する場合は、個々にARGを指定する必要がある。

ARGENVにおいて変数を指定し、それをRUNにて用いることができる。ENVを使って定義された環境変数は、ARGにおいて同名の変数が指定されていたとしても優先される。

FROMよりも前に宣言されているARGは、ビルドステージ内に含まれるものではない。したがってFROM以降の命令において利用することはできない。初出のFROMよりも前に宣言されたARGの値を利用するには、ビルドステージ内において`ARG 命令を、値を設定することなく利用する。

Dockerfile リファレンス - docker docs

CMD vs ENTRYPOINT

[docker] CMD とENTRYPOINT の違いを試してみた - Qiita
ENTRYPOINTは「必ず実行」、CMDは「(デフォルトの)引数」 - POCKETSTUDIO.NET

COPY vs ADD

DockerfileにてなぜADDよりCOPYが望ましいのか - Qiita

Dockerfileのサンプル

# Dockerfile
# syntax=docker/dockerfile:1
FROM ruby:2.5
RUN apt-get update -qq && apt-get install -y nodejs postgresql-client
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install

# コンテナが実行されるたびに毎回実行されるスクリプト
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

# イメージが起動中の時に実行するメインプロセスの設定
CMD ["rails", "server", "-b", "0.0.0.0"]
# entrypoint.sh
#!/bin/bash
set -e

# Railsのserver.pidが残っているかもしれないので、それを削除する.
rm -f /myapp/tmp/pids/server.pid

# コンテナのメインプロセス(DockerfileでCMDでセットされているもの)を実行する。
exec "$@"

Quickstart: Compose and Rails - Docker Docs

rails s -b 0.0.0.0 のオプション-bの意味 - Qiita
Railsのプロセスは、外部からのリクエストを受け付けるために、ホストが持っているIPアドレスに結び付けられる(デフォルトでは 127.0.0.1 )。
(コンテナのネットワーク上の)localhost(= 127.0.0.1)で立ち上がっているプロセスは、外部(コンテナのネットワーク上から見た時のホストのネットワーク上など)からはアクセスできない。
0.0.0.0 は全てのIPアドレスを表す。
Railsのプロセスを(コンテナのネットワーク上の)全てのIPアドレスにバインディング(-b '0.0.0.0')することによって、外部からアクセスできないIPアドレスである 127.0.0.1 だけではなく、外部からアクセス可能なIPアドレスでもRailsアプリケーションを立ち上げている。

Dockerfileのベストプラクティス

Dockerfile のベストプラクティス - Docker-docs-ja
コンテナ毎に1つのプロセスだけ実行、コンテナはエフェメラルであるべき、などのプラクティス。

社内のDockerfileのベストプラクティスを公開します - FORCIA CLUB

Dockerfileのベストプラクティス - 入門Docker

Dockerfileのベストプラクティス - Qiita

Dockerコマンドのサンプル

Dockerfile から Dockerイメージをビルドする

$ docker image build -t yokoto/ansible_image:latest(イメージ名[:タグ]) .(Dockerfile配置ディレクトリのパス)

docker image build - Docker Docs
-t(--tag): 作成するDockerイメージのタグを指定する。

新しいコンテナを作成・起動し、そのコンテナでコマンド実行する

$ docker container run -p 9000:8080(ホストポート:コンテナポート) --name ansible_container(コンテナの命名) yokoto/ansible_image:latest(イメージ名[:タグ]) 

docker container run - Docker Docs

Container networking - Docker Docs
ローカルホストのポートへの通信をコンテナポートへ転送するポートフォワーディングの解説。
ポートフォワーディングの設定により、コンテナポートにホストポートでの通信を許可する。

docker runとdocker execの違いの解説 - めもたんす
docker container run は以下と等しい。

$ docker container create -p 9000:8000 --name ansible_container yokoto/ansible_image:latest
$ docker container start ansible_container

docker container create - Docker Docs
新たなコンテナを生成します。
docker container start - Docker Docs
1つまたは複数の停止中コンテナを起動します。

実行中のコンテナでコマンド実行する

$ docker container run --name ansible_container yokoto/ansible_image:latest
$ docker container exec -it ansible_container /bin/bash 

docker container exec - Docker Docs

【Docker】「コンテナに入る」が何をしているか1分で理解する - Qiita
exec -itの解説。
-i: 標準入力を受け付けることを示すオプション。-iをつけないとキーボードからの入力を受け付けてくれない。
-t: tty。-tをつけないとコマンド入力用のターミナルが割り当てられない。
/bin/bash: 対話形式のbashシェルを起動する。

【docker】docker run と docker execの違いについて - 自由気ままに書いちゃおう
Dockerコンテナの作成、起動〜停止まで - Qiita

実行中のコンテナを停止する

$ docker container stop ansible_container
# or
$ docker container kill	ansible_container # 強制停止

docker container stop - Docker Docs
docker container kill - Docker Docs

コンテナを削除する

$ docker container rm ansible_container
$ docker container prune # 全てのコンテナを削除

docker container rm - Docker Docs
docker container prune - Docker Docs

イメージ(image)

  • コンテナを実行するために必要なビルド済みパッケージ。
  • レジストリにおいて、「タグ」によってバージョン管理されている。

ruby - Docker Hub
ansible - Docker Hub

DockerイメージのDockerfile。
ruby/3.0/alpine3.14/Dockerfile - GitHub
ansible/centos7/Dockerfile - GitHub

レジストリ

  • イメージのバージョン管理や配布を行えるサービス。
  • 例: Docker Registory、Docker Hub、Amazon Elastic Container Registry(ECR)、GCP Container Registry(GCR)

パブリックレジストリ vs プライベートレジストリ

  • リポジトリを非公開にしたり、イメージのプルに対するアクセス制御を行いたい場合は、プライベートリポジトリを作成する。
    • Docker Registry、ECR、GCPは、基本的にプライベートレジストリを作成する用途で利用される。

コンテナレジストリとは?パブリックレジストリとプライベートレジストリの違い
ECRをパブリックレジストリとして利用可能になりました! #reinvent
Amazon ECR プライベートレジストリ

リポジトリ

  • レジストリにおいて、各イメージが保管されている場所。

【Docker】レジストリとリポジトリ
Difference between Docker registry and repository - Stack Overflow

イメージ vs タグ vs リポジトリ

$ docker image ls # イメージの一覧
REPOSITORY               TAG     IMAGE ID       CREATED       SIZE
centos                   latest  91c95931e552   9 hours ago   812MB
ansible/centos7-ansible  latest  fb434121fc77   12 hours ago  605MB
tutum/centos             v1.1    1234abcd5678   21 hours ago  470MB
$ docker search centos # イメージの検索
NAME                     DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
centos                   The official build of CentOS.                   1034      [OK]
ansible/centos7-ansible  Ansible on Centos7                              43                   [OK]
tutum/centos             Centos image with SSH access. For the root...   13                   [OK]
...
# Image ID
centos # 91c95931e552
ansible/centos7-ansible:latest # fb434121fc77
ansible/centos7-ansible:v1.1 # fb434121fc77
tutum/centos:v1.1 # 1234abcd5678
用語 説明
イメージ Image ID(例: 91c95931e552, fb434121fc77, 1234abcd5678)によって一意に参照できるものを指す。
タグ Image IDのエイリアス。
デフォルトで latest となる。
latest,
v1.1
イメージ名 タグの全表記。
[REGISTRYHOST/][USERNAME/]NAME[:TAG]
centos,
ansible/centos7-ansible:latest ,
tutum/centos:v1.1
リポジトリ 1つ以上のイメージ(Image ID)を持つ。 centos,
centos7-ansible,
centos
リポジトリ名 ユーザー名を名前空間として持つリポジトリの名前。 centos,
ansible/centos7-ansible,
tutum/centos
ユーザー名 リポジトリ名の名前空間。
これにより、パブリックレジストリからリポジトリを検索する際に名前の競合を防ぐことができる。
ansible,
tutum

Docker初心者がイメージとリポジトリの違いが分からなくて混乱したこと - Qiita
What is the difference between an image and a repository? - Stack Overflow
Docker Hub 上のリポジトリ - Docker-docs-ja
Dockerのリポジトリ名とイメージ名って同じもの?

BuildKit

  • Dockerでは、BuildKitというビルドの拡張機能が18.09から導入された。

機密情報を受け渡す

  • これにより、docker build 時に --secret オプションを渡すことで、機密情報を受け渡せるようになった。
    • 機密情報は、最終的にイメージ内に保存されることはないので、安全に取り扱うことができる。
  • 機密情報には、Docerfile の RUN が実行される際にアクセスすることができる。
$ echo 'WARMACHINEROX' > mysecret.txt
# syntax=docker/dockerfile:1.2

FROM alpine

# デフォルトの機密情報の置き場所から機密情報を表示する
RUN --mount=type=secret,id=mysecret cat /run/secrets/mysecret

# カスタムの機密情報の置き場所から機密情報を表示する
RUN --mount=type=secret,id=mysecret,dst=/foobar cat /foobar
$  docker build --no-cache --progress=plain --secret id=mysecret,src=mysecret.txt .
...
#  [2/3] RUN --mount=type=secret,id=mysecret cat /run/secrets/mysecret
#       digest: sha256:5d8cbaeb66183993700828632bfbde246cae8feded11aad40e524f54ce7438d6
#          name: "[2/3] RUN --mount=type=secret,id=mysecret cat /run/secrets/mysecret"
#       started: 2018-08-31 21:03:30.703550864 +0000 UTC
#  1.081 WARMACHINEROX
#     completed: 2018-08-31 21:03:32.051053831 +0000 UTC
#      duration: 1.347502967s
#  [3/3] RUN --mount=type=secret,id=mysecret,dst=/foobar cat /foobar
#        digest: sha256:6c7ebda4599ec6acb40358017e51ccb4c5471dc434573b9b7188143757459efa
#          name: "[3/3] RUN --mount=type=secret,id=mysecret,dst=/foobar cat /foobar"
#       started: 2018-08-31 21:03:32.052880985 +0000 UTC
#  1.216 WARMACHINEROX
#     completed: 2018-08-31 21:03:33.523282118 +0000 UTC
#      duration: 1.470401133s
オプション 説明
id docker build --secret id=:id において受け渡される識別子。
Dockerfileの RUN --mount...,id=:id として関連づけられる。
※ これにより、Dockerfileの外の機密情報を含むファイル名を用いないようにしている。
dst Dockerfile内にて用いられる RUN コマンドにおいての機密情報ファイルの置き場所を、任意の置き場所に変更する。
dst を指定しない場合、デフォルトで /run/secrets/:id に機密情報ファイルが置かれる。
src docker build --secret において受け渡される、機密情報ファイルの指定。

BuildKit によるイメージ構築 - docker docs

特定のディレクトリをキャッシュする

  • コンパイラやパッケージマネージャ(bundler等)用のディレクトリをキャッシュすることができる。
  • キャッシュディレクトリの内容は、ビルド間で保持される。
  • キャッシュマウントは、パフォーマンスを向上させるためだけに使用する。
# syntax=docker/dockerfile:1
FROM golang
RUN --mount=type=cache,target=/root/.cache/go-build \
  go build ...
# syntax=docker/dockerfile:1
FROM ubuntu
RUN rm -f /etc/apt/apt.conf.d/docker-clean; echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
  --mount=type=cache,target=/var/lib/apt,sharing=locked \
  apt update && apt-get --no-install-recommends install -y gcc
オプション 説明
id 別々のキャッシュの識別子。
※ デフォルトでは target の値になる。
target[^1] マウントパス。
from キャッシュマウントのベースとして使用するビルドイメージ。
※ デフォルトでは空のディレクトリになる。
source マウントする from の中で指定するパス。
デフォルトでは from のルート。
mode 8進数で表される新しいキャッシュディレクトリのファイルモード。
デフォルトでは 0755
uid 新しいキャッシュディレクトリ用のユーザーID。
デフォルトでは 0.
gid 新しいキャッシュディレクトリ用のグループID。
デフォルトでは 0.

Docker のキャッシュを全力で使いこなそう - Zenn
Docker 18.09 新機能 (イメージビルド&セキュリティ) - Medium
buildkit/frontend/dockerfile/docs/reference.md - GitHub

マルチステージビルド

  • Dockerfileに FROM を複数記述することで複数のビルドを展開すること。
  • 1ビルドの単位をステージと呼ぶ。
  • イメージをビルドする際に、使用しないファイル等が減り、結果作成されるイメージサイズが小さくなる
# syntax=docker/dockerfile:1
FROM golang:1.16 AS builder
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html
COPY app.go ./
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
# COPY --from=builder: builderステージを利用してファイルをコピー
COPY --from=builder /go/src/github.com/alexellis/href-counter/app ./
CMD ["./app"]

ステージを指定してビルドする

  • builder と名付けたステージのみビルドする。
$ docker build --target builder -t alexellis2/href-counter:latest 

前にビルドしたステージを参照して用いる

# syntax=docker/dockerfile:1
FROM alpine:latest AS builder
RUN apk --no-cache add build-base

FROM builder AS build1
COPY source1.cpp source.cpp
RUN g++ -o /binary source.cpp

FROM builder AS build2
COPY source2.cpp source.cpp
RUN g++ -o /binary source.cpp

マルチステージビルドの利用 - docker docs
1つのDockerfileだけでGoの開発環境(ホットリロード)と本番環境(マルチステージビルド)を記述する - Qiita
Docker multi stage buildで変わるDockerfileの常識 - Qiita
至高のDockerイメージ生成を求めて -2019年版- - Qiita
Docker のマルチステージビルドで Rails イメージを軽くする - Zenn

Docker Compose

  • Docker Composeは、複数のコンテナで動作するDockerアプリケーションの定義・実行をするためのツール
    • Dockerfileによって作成したイメージを組み合わせて1つのコマンド(docker compose up など)で実行することができる。
    • コンテナだけではなく、Dockerのネットワークとボリュームも管理できる。
    • 本番環境、ステージング環境、開発環境において動作し、CIワークフローとしても利用することができる。

docker-compose.yml

  • docker-compose.ymlは、Dockerコンテナを用いるアプリケーションの設計図に相当する。
    • 複数のコンテナ実行を一括で管理できる、主に以下を定義しているyaml形式のファイル。
属性 説明
services 同じコンテナイメージ (および構成) を1回以上実行することによってプラットフォームに実装される抽象的な概念。
コンテナを実行するための実行時の制約と要件の定義。
services > build Dockerイメージを持つDockerfileへの相対パス。
services > image Dockerイメージ。
networks サービスが相互に接続できるようにネットワークを作成するレイヤー。
サービスコンテナが接続するネットワークの定義。
volumes 永続的なデータストア。
サービスコンテナ側にマウントするホスト側のパスまたは名前付きボリュームの定義。
configs サービスコンテナに付与できる、プラットフォームやランタイムに依存した http 等の構成データの定義。
secrets サービスコンテナに付与できる機密情報の定義。

docker-compose.ymlのサンプル

docker-compose.yml
version: "3.9" # YAMLのバージョン管理
services: # サービス(コンテナ)を定義するセクション
  db: # dbサービスの定義
    image: postgres # postgres公式イメージを使用
    volumes: # ボリュームに関する指定
      - ./tmp/db:/var/lib/postgresql/data # `./tmp/db` を `/var/lib/postgresql/data` コンテナ内のにマウント
    environment: # コンテナ内で利用できる環境変数の指定
      POSTGRES_PASSWORD: password # パスワードを指定
  web: # webサービスの定義
    build: . # Dockerfileのあるパスを指定
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" # デフォルトのコマンドを上書きする
    volumes:
      - .:/myapp # ホスト上の現在のディレクトリ `./` を `/myapp` にコンテナ内のマウント
      - logvolume01:/var/log # 名前付きボリューム `logvolume01` をコンテナ内の `/var/log` にマウント
    ports: # ポート公開指定
      - "3000:3000" # ホスト側のポート3000を、コンテナ内のポート3000にマッピング
    depends_on: # サービスの依存関係を指定
      - db # dbに依存している
  redis: # redisサービスの定義
    image: "redis:alpine" # redis公式イメージを使用
volumes: # ボリュームを定義するセクション
  logvolume01: {}

Docker Compose の概要 / Overview - Docker Docs
Docker Compose をはじめよう - Docker Docs
Compose specification - Docker Docs

Docker Compose - docker-compose.yml リファレンス - Qiita
Difference between Docker Compose Vs Dockerfile

Docker Composeコマンドのサンプル

サービスのビルド・再ビルド

$ docker compose build

docker compose build - Docker Docs
サービスのDockerfileを変更した場合、このコマンドでサービスを再構築する。

全てのコンテナを作成・起動する

$ docker compose up -d 
Creating network "wordpress_wordpressnet" with the default driver
Creating volulme "wordpress_wordpress_db_volume" with default driver
Creating wordpress_wordpress-db_1 ... done
Creating wordpress_wordpress-app_1 ... done

docker compose up - Docker Docs

全てのコンテナを一覧表示する

$ docker compose ps 

docker compose ps - Docker Docs
docker network ls - Docker Docs
docker compose logs - Docker Docs
docker volume ls- Docker Docs

全てのコンテナを停止・破棄する

$ docker compose down
Stopping wordpress_wordpress-app_1 ... done
Stopping wordpress_wordpress-db_1 ... done
Removing wordpress_wordpress-app_1 ... done
Removing wordpress_wordpress-db_1 ... done
Removing network wordpressnet

docker compose ps - Docker Docs

サービスとコンテナの違い

  • サービスは、1つまたは複数のコンテナで実行できる。

    • Docker で "コンテナ" を処理する。
    • Docker Compose で "サービス" を処理できる。
  • 以下の例では、2つのサービス持つDocker Composeが、
    1つのサービス(web)をスケーリングをスケーリングすることで、6つのコンテナを作成している。

$ docker ps -a
CONTAINER ID   IMAGE        COMMAND          ...      NAMES
1c1683e871dc   test1_web    "nginx -g"       ...      test1_web_1
a41360558f96   test1_db     "postgres -d"    ...      test1_db_1

$ docker compose up --scale web=5
Creating and starting 2 ... done
Creating and starting 3 ... done
Creating and starting 4 ... done
Creating and starting 5 ... done

$ docker ps -a  
CONTAINER ID   IMAGE        COMMAND         ...      NAMES
1bf4c939263f   test1_web    "nginx -g"      ...      test1_web_3
d3033964a44b   test1_web    "nginx -g"      ...      test1_web_4
649bbda4d0b0   test1_web    "nginx -g"      ...      test1_web_5
a265ea406727   test1_web    "nginx -g"      ...      test1_web_2
1c1683e871dc   test1_web    "nginx -g"      ...      test1_web_1
a41360558f96   test1_db     "postgres -d'   ...      test1_db_1

Difference between service and container in docker compose - stack overflow

永続化・ボリューム・マウント

  • Docker Compose では、サービスによって利用されているボリューム(Docker管理下のストレージ領域)をすべて維持する。
    • docker compose up が実行されたときに、コンテナーがそれ以前に実行されていれば、以前のコンテナーから現在のコンテナーに向けてボリュームをコピーする。
      • この処理において、ボリューム内に作り出されていたデータは失われることはない。

ボリュームマウント

  • コンテナの特定のディレクトリをボリュームとしてホストマシン側で管理すれば、コンテナが削除されてもデータが消失しなくなる。
    • 例: Docker Engineというデータ領域に確保したボリューム(例: mysqlvolume)を、mysqlコンテナの /var/lib/mysql ディレクトリにマウントして起動することで、コンテナを削除してもDBのデータを残すこと(永続化)ができる。
# ボリュームマウントする。ボリューム(`mysqlvolume`)が作られていないときは新規にボリュームを作成する。
$ docker container run --name db01 \
  --volume mysqlvolume:/var/lib/mysql \
  --env MYSQL_ROOT_PASSWORD=password \
  mysql:5.7
# ボリュームマウントする。ボリューム(`mysqlvolume`)が作られていないときは新規にボリュームを作成せずエラーを発生する。
$ docker container run --name db01 \
  --mount type=volume,src=mysqlvolume,dst=/var/lib/mysql \
  --env MYSQL_ROOT_PASSWORD=password \
  mysql:5.7

または

docker-compose.yml
services:
  db:
    volumes:
    - mysqlvolume:/var/lib/mysql

以下のように詳細に指定することもできる。

docker-compose.yml
services:
  db:
    volumes:
      - type: volume
        source: mysqlvolume
        target: /var/lib/mysql

実践 Docker - ソフトウェアエンジニアの「Docker よくわからない」を終わりにする本 Chapter 19 3部: Docker Compose - Zenn
第3章 コンテナアプリケーション開発のライフサイクル Build・Ship・Run 永続化データとネットワークモデル インフラエンジニアBooks 30分でわかる「Dockerコンテナ開発・環境構築の基本」 - SpeakerDeck
さわって学ぶクラウドインフラ docker 基礎からのコンテナ構築 5-2 データを独立させる
MySQLのデータディレクトリを移動する - Qiita
MySQLがデータを保管する場所 〜 データディレクトリ - 日常メモ
4.4.3 mysql_install_db — MySQL データディレクトリの初期化 - MySQL
Docker Machine 概要 Docker Engine と Docker Machine の違いは何ですか? -- Docker-docs-ja

バインドマウント

  • ホスト側のディレクトリをコンテナ内のディレクトリと共有する
  • ソースコードのディレクトリをコンテナにバインドマウントしてホストマシン側と共有すれば、ホストマシンでコードを変更した際に同期や転送が不要になる。
    • 例1: DBコンテナのイメージを配布する時点では用意できなかったDBの初期化クエリを、DBコンテナにマウントする
    • 例2: 開発時のソースコードなど、ホストマシンで変更したいがコンテナに随時反映したいものをコンテナ内のディレクトリにマウントする
  • バインドマウントは、実体の面倒を見ているのがホストマシン上である。
    • 「仮想環境だから」と安易に削除すると、影響がホストマシンに波及する。
  • まずはボリュームを検討し、どうしてもだめならバインドマウントを使う。
docker-compose.yml
services:
  web:
    build: .
    volumes:
      - ".:/myapp"

以下のように詳細に指定することもできる。

docker-compose.yml
services:
  web:
    build: .
    volumes:
      - type: bind
        source: "."
        target: "/myapp"

実践 Docker - ソフトウェアエンジニアの「Docker よくわからない」を終わりにする本 Chapter 16 3部: バインドマウント

ボリュームマウント vs バインドマウント

用語 説明
ボリュームマウント マウント元が「/」から始まらないとき。 -v(volume) mysqlvolume:/var/lib/mysql
バインドマウント マウント元が「/」から始まるとき。 --v(volume) /tmp/db:/var/lib/mysql

Docker の Volume がよくわからないから調べた - Qiita

コンテナのネットワーク(bridge, host, none)

  • コンテナはそれぞれIPアドレスを持つ。
  • コンテナ間で通信や負荷分散を行いたいとき、通信先のコンテナをIPアドレスを指定するのではなく、コンテナ名で指定することができる。
    • コンテナ間の通信でIPアドレスとコンテナ名の名前解決を行うには、自分で「ブリッジネットワーク」を作成する必要がある。
  • Dockerでは、複数のプロセス(コンテナ)を動かす必要がある時は、(ソケットではなく)ネットワークで通信を行うことが推奨されている。

ブリッジネットワーク

  • ブリッジとは、別々のネットワーク間で通信できるようにする働きを持つ一般的なネットワークの機能。
  • 同じブリッジネットワーク上に接続しているコンテナは、お互いに通信できる
    • コンテナ間で通信できるようにするためには、自分でブリッジ・ネットワークを作成する必要がある。

Docker Compose入門 (3) ~ネットワークの理解を深める~ - さくらのナレッジ
ブリッジネットワークの利用 - docker docs

ネットワークドライバ

  • Dockerのネットワークには3種類のネットワークドライバがある。

スクリーンショット 2022-10-17 21.02.19.png

ドライバ 説明
bridge Dockerコンテナ作成時に何も指定しない場合はこちらが選択される。
Linuxのブリッジ機能を使って仮想ネットワーク上(≠ホストのネットワーク上)にコンテナを作成する。
インターネットとの通信はNAT形式で行う。
host ホストのネットワーク上にコンテナが作成される。
= ホストと同じネットワークインターフェイス、IPアドレスをもつ。
none ネットワークを持たないコンテナが作成される。
= コンテナ間の通信ができない。

Dockerコンテナを任意のネットワークに参加させるコマンド

  • コンテナは、接続されているブリッジネットワークを通じて、割り当てられたIPアドレスを介して互いに自由に通信できる。
# 新しいブリッジネットワークを作成する
$ docker network create mybridge_network
# 作成したブリッジネットワークを指定して、コンテナを作成 or 実行する
$ docker container run --name mycontainer1 myimage --net mybridge_network
# or
$ docker container create --name mycontainer1 myimage --net mybridge_network
# 同じブリッジネットワークを指定して、コンテナを作成する
$ docker container create --name mycontainer2 myimage --net mybridge_network
# コンテナに対して通信する
$ docker container run --name mycontainer1 myimage --net mybridge_network ping mycontainer2
64 bytes from 172.25.0.3: seq=0 ttl=64 time=0.119 ms
64 bytes from 172.25.0.3: seq=1 ttl=64 time=0.127 ms
64 bytes from 172.25.0.3: seq=2 ttl=64 time=0.132 ms

Docker network 概論 - Qiita
network - 入門Docker
Docker の volume と network の初歩 - 30歳からのプログラミング

Dockerを使った基本的なRailsアプリケーションの作成/コマンドのリンク

クィックスタート: Compose と Rails - Docker-docs-ja
Quickstart: Compose and Rails - Docker Docs
docker-compose run - Docker-docs-ja
docker compose run - Docker Docs

$ docker compose run --rm web bundle exec rails console

web という名前のサービスに対して、 bundle exec rails console を実行する。
--rm オプションは、処理の実行が終了したらコンテナを削除する。

Dockerを用いてRuby on Railsの環境構築をする方法( Docker初学者向け ) - Qiita
Docker Compose でローカルの Rails 開発環境を作る - Qiita
DockerでRails開発環境を作るワンライナー [Rails7/M1 Mac対応] - Qiita

コンテナオーケストレーション

オーケストレータ

  • 本番環境では多くの場合、サーバーを複数台用意し、負荷分散を行ったり耐障害性を高めたりする構成を作るため、本番環境でコンテナを利用したい場合、複数のコンテナを連携させる必要が出てくる。
  • 多数のコンテナを、複数のホストから構成されたクラスターに対し、負荷分散やファイルオーバーを行うサービスをオーケストレータと呼ぶ。
  • 例: Kubernetes、Amazon Elastic Container Service(ECS)、Amazon Elastic Kubernetes Service(EKS)

Kubernetes

  • Kubernetesはコンテナ化されたアプリケーションのデプロイ、スケーリングなどの管理を自動化するためのプラットフォームであり、コンテナオーケストレーションエンジンです。
  • Docker単体では複数のホストで構成される一定規模以上のプロダクション利用に耐えうるシステムを構築するのは難しく、今日ではそのようなシステムを構築するには、Kubernetesに代表されるコンテナオーケストレーションエンジンを利用することが一般的です。

Kubernetes完全ガイド 第2版

クラスタ

スクリーンショット 2022-05-13 23.17.34.png

  • 1つ以上のマスターノードと1つ以上のワーカーノードから成り立つもの。
  • コンテナ化されたアプリケーションを実行する、ノードと呼ばれるワーカーマシンの集合
  • すべてのクラスターには少なくとも1つのワーカーノードがある。
  • Kubernetesクラスターは以下の2種類のリソースで構成されています
    • マスターがクラスターを管理する
    • ノードがアプリケーションを動かすワーカーとなる

標準化用語集 - Kubernetesドキュメント
Minikubeを使ったクラスターの作成 - Kubernetesドキュメント

Deployment

  • アプリケーションのインスタンスを作成および更新する責務がある。
  • コンテナのデプロイ状態。
  • Kubernetesクラスター上にコンテナ化アプリケーションをデプロイするために必要な設定。
    • アプリケーションのインスタンスを作成し、更新する方法を指示する。
    • Deploymentを作成すると、KubernetesマスターはDeployment内に含まれるアプリケーションインスタンスをクラスター内の個々のノードで実行するようにスケジュールする
    • Deploymentを作成するときは、アプリケーションのコンテナイメージと実行するレプリカの数を指定する必要がある。

kubectlを使ったDeploymentの作成 - Kubernetesドキュメント

Deploymentのスケーリング

  • トラフィックが増加した場合、ユーザーの需要に対応するためにアプリケーションをスケールする必要がある。
  • スケーリングは、Deploymentのレプリカの数を変更することによって実現可能
  • Deploymentをスケールアウトすると、新しいPodが作成され、使用可能なリソースを持つノードにスケジュールされる
    • スケールすると、Podの数が増えて新たな望ましい状態になる

アプリケーションの複数インスタンスを実行 - Kubernetesドキュメント

ノード

スクリーンショット 2022-10-14 1.24.29.png

  • Podは常にノード上で動作する。
  • ノードはKubernetesではワーカーマシンであり、クラスターに応じてVMまたは物理マシンになる。
  • 複数のPodを1つのノードで実行できる。
  • すべてのKubernetesノードでは少なくとも以下のものが動作する。
    • Kubelet: Kubernetesマスターとノード間の通信を担当するプロセス。マシン上で実行されているPodとコンテナを管理します。
    • レジストリからコンテナイメージを取得し、コンテナを解凍し、アプリケーションを実行することを担当する、Dockerのようなコンテナランタイム

Podとノードについて - Kubernetesドキュメント

Pod

スクリーンショット 2022-10-14 1.23.58.png

  • 一番小さく一番シンプルなKubernetesのオブジェクト。
  • クラスターで動作しているいくつかのコンテナのまとまり
  • Podの中でコンテナが起動する。
  • Podは常にノード上で動作する。
  • Podは通常Deploymentによって管理される。
  • Podは1つ以上のアプリケーションコンテナ(Dockerなど)のグループであり、共有ストレージ(ボリューム)、IPアドレス、それらの実行方法に関する情報が含まれています。
  • Podには以下のものが含まれます:
    • 共有ストレージ(ボリューム)
    • ネットワーキング(クラスターに固有のIPアドレス)
    • Dockerイメージのバージョンや使用するポートなどの、各コンテナをどう動かすかに関する情報
  • Podの例
    • Node.jsアプリケーションを含むコンテナとNode.js Webサーバによって公開されるデータを供給するコンテナを含んだオブジェクト
  • Kubernetes上にDeploymentを作成すると、そのDeploymentはその中に(コンテナを直接作成するのではなく)コンテナを持つPodを作成する
    • 各Podは、スケジュールされているノードに関連付けられており、終了(再起動ポリシーに従って)または削除されるまでそこに残る。
    • コンテナ同士が密接に結合され、ディスクなどのリソースを共有する必要がある場合は、コンテナを1つのPodにまとめてスケジュールする必要がある

標準化用語集 - Kubernetesドキュメント
Podとノードについて - Kubernetesドキュメント

マニフェスト

  • Pod等の定義の記述。
  • JSONまたはYAMLフォーマットでのKubernetes APIオブジェクトの定義。

Service

  • Podの論理セットを定義する。
    • それらのPodに対する外部トラフィックの公開、負荷分散、およびサービス検出を可能にする抽象化層
  • YAML(推奨)またはJSONを使って定義される。
  • Serviceによって、アプリケーションはトラフィックを受信できるようになります
    • 各Podには固有のIPアドレスがありますが、それらのIPは、Serviceなしではクラスターの外部に公開されません
    • ServiceSpecでtypeを指定することで、Serviceをさまざまな方法で公開することができる。
  • Serviceには、公開されたDeploymentのすべてのPodにネットワークトラフィックを分散する統合ロードバランサがある
  • Serviceは、エンドポイントを使用して実行中のPodを継続的に監視し、トラフィックが使用可能なPodにのみ送信されるようにする
  • ClusterIP (既定値)
    • クラスター内の内部IPでServiceを公開する。
    • この型では、Serviceはクラスター内からのみ到達可能になります。
  • NodePort
    • ClusterIPのスーパーセット。
    • NATを使用して、クラスター内の選択された各ノードの同じポートにServiceを公開する。
    • <NodeIP>:<NodePort>を使用してクラスターの外部からServiceにアクセスできるようにする。
  • LoadBalancer
    • NodePortのスーパーセット。
    • 現在のクラウドに外部ロードバランサを作成し(サポートされている場合)、Serviceに固定の外部IPを割り当てる。
  • ExternalName
    • 仕様のexternalNameで指定した名前のCNAMEレコードを返すことによって、任意の名前を使ってServiceを公開する。
    • プロキシは使用されない。
    • このタイプはv1.7以上のkube-dnsを必要とする。

Serviceを使ったアプリケーションの公開 - Kubernetesドキュメント
アプリケーションの複数インスタンスを実行 - Kubernetesドキュメント

Ingress

スクリーンショット 2022-10-17 21.33.49.png

  • クラスター外からクラスター内ServiceへのHTTPとHTTPSのルートを公開する。
    • トラフィックのルーティングはIngressリソース上で定義されるルールによって制御される。
  • Serviceに対して、外部疎通できるURL、負荷分散トラフィック、SSL/TLS終端の機能や、名前ベースの仮想ホスティングを提供するように設定できる。
  • NGINX Ingress Controller for Kubernetesを使用することで、Nginx Webサーバー(プロキシ)として動作することができる。

Ingress - Kubernetesドキュメント
Ingressコントローラー - Kubernetesドキュメント

参考リンク

Kubernetesドキュメント/チュートリアル - kubernetes
標準化用語集 - kubernetes
Kubernetesのしくみ やさしく学ぶ 内部構造とアーキテクチャー - slideshare
ECS / Fargate / EKS ハンズオン資料まとめ - Qiita
違いから見る Kubernetes #k8sjp / See Kubernetes through an Amazon ECS Lens - SpeakerDeck
EKSは本当にECSより難しいのか? - Classmethod
AWS EKSとECSの比較と選択基準 - Zenn
コンテナを使いこなすための心強い味方!「Kubernetes」(前編)
10分くらいでわかる、KubernetesとEKSの何が便利なのか - Qiita
数時間で完全理解!わりとゴツいKubernetesハンズオン!! - Qiita
Docker Composeユーザーに捧ぐKubernetes入門 - Zenn
AWS EKSとECSの比較と選択基準 - Zenn
違いから見る Kubernetes #k8sjp / See Kubernetes through an Amazon ECS Lens - Speaker Deck
Kubernetes道場 Advent Calendar 2018 - Qiita

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
What you can do with signing up
0