コンテナ
- OSとカーネルは共有し、プロセスを分離する仕組み。
-
コンテナ上で実行されたソフトウェアは単に1つのプロセスとして稼働しているにも関わらず、
コンテナ内のソフトウェアから見ると独立したOS環境を占有しているように見える。
コンテナ vs サーバー仮想化
- サーバー仮想化は複数のOSを同一のハードウェア上で実行する仕組み。
- 「仮想マシン」上に「ゲストOS」を動作させる。
- 例: Virtual box
サーバー仮想化技術の基礎 - Qiita
各仮想化技術の違いをざっと理解するッ!! - Qiita
[Cloud] 仮想化技術について
コンテナのメリット
-
環境による差異の解消
- 開発環境やステージング環境、プロダクション環境等、複数の環境間のアプリケーションの依存関係(ライブラリのバージョンのずれ等)を全てコンテナ内で完結でき、意識する必要がなくなる。
-
構成管理の容易さ
- サーバー仮想化と比較するとゲストOSやハードウェアのエミュレートが不要となり、プロセス単位で稼働するため効率的。
- アプリケーションを動かすために必要となるコンピューティングリソースの消費は少なくなる。
- アプリケーションの起動も高速。
- サーバー仮想化と比較するとゲスト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 されるファイルやディレクトリのUID とGID は、すべて0 として生成される。ただしオプションとして --chown フラグを用いると、引数に与えたユーザー空間、グループ名、あるいはUID とGID の組み合わせによる指定が可能になり、特定の所有権を満たした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 内の後続の RUN 、CMD 、ENTRYPOINT の各コマンドにおいてこの情報を利用する。 |
WORKDIR | 書式: WORKDIR /path/to/workdir ワークディレクトリを設定する。 Dockerfile内にてその後に続く RUN 、CMD 、ENTRYPOINT 、COPY 、ADD の各命令において利用することができる。WORKDIR が存在しないときは生成される。WORKDIR はDockerfile内にて複数利用することができる。ディレクトリ指定に相対パスが用いられた場合、そのパスは、直前のWORKDIR からの相対パスとなる。 |
ARG | 書式: ARG <name>[=<default value>] 変数を定義して、ビルド時にその値を受け渡す。 これは docker build コマンドにおいて--build-arg <varname>=<value> フラグを利用して行う。Dockerfile内において指定したビルド引数(build argument )が定義されていない場合は、ビルド処理時に警告メッセージが出力される。オプションとしてデフォルト値を設定することができる。 ARG の変数スコープは、それが定義されたビルドステージが終了するときまで。複数のビルドステージにおいて ARG を利用する場合は、個々にARG を指定する必要がある。ARG やENV において変数を指定し、それを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
Dockerコマンドのサンプル
Docker 1.13から、Dockerコマンドが新しくなった。
現場では新コマンド
docker image build
docker image rm
docker container run
-
docker container rm
etc.
の代わりに、旧コマンド
docker build
docker rmi
docker run
-
docker rm
etc.
が引き続き使われていることも多い。
docker container / image コマンド新旧比較 - Qiita
Docker 1.13 – What’s New Including Docker Prune Features - Cloudshare
Dockerfile から Dockerイメージをビルドする
$ docker image build -t yokoto/ansible_image:latest(イメージ名[:タグ]) .(Dockerfile配置ディレクトリのパス)
docker image build - Docker Docs
-t(--tag): 作成するDockerイメージのタグを指定する。
Dockerイメージを削除する
$ docker image rm -f (イメージ名[:タグ])
$ docker image rm $(docker images -q) # 全てのイメージを削除
$ docker image prune # 使用していない全てのイメージを削除
-f(--force): コンテナが実行中の場合も、イメージを強制的に削除する。
docker image rm - Docker Docs
docker image prune
Dockerコンテナとイメージを全削除する - Zenn
Dockerイメージ、ボリューム、コンテナを簡単に削除する方法 - kinsta
新しいコンテナを作成・起動し、そのコンテナでコマンド実行する
$ 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 rm $(docker ps -aq) # 全てのコンテナを削除
$ docker container prune # 停止中の全てのコンテナを削除
docker container rm - Docker Docs
docker container prune - Docker Docs
Dockerコンテナとイメージを全削除する - Zenn
Dockerイメージ、ボリューム、コンテナを簡単に削除する方法 - kinsta
イメージ(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ワークフローとしても利用することができる。
- Dockerfileによって作成したイメージを組み合わせて1つのコマンド(
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のサンプル
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のデータを残すこと(永続化)ができる。
- 例: Docker Engineというデータ領域に確保したボリューム(例:
# ボリュームマウントする。ボリューム(`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
または
services:
db:
volumes:
- mysqlvolume:/var/lib/mysql
以下のように詳細に指定することもできる。
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: 開発時のソースコードなど、ホストマシンで変更したいがコンテナに随時反映したいものをコンテナ内のディレクトリにマウントする。
- バインドマウントは、実体の面倒を見ているのがホストマシン上である。
- 「仮想環境だから」と安易に削除すると、影響がホストマシンに波及する。
- まずはボリュームを検討し、どうしてもだめならバインドマウントを使う。
services:
web:
build: .
volumes:
- ".:/myapp"
以下のように詳細に指定することもできる。
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種類のネットワークドライバがある。
ドライバ | 説明 |
---|---|
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に代表されるコンテナオーケストレーションエンジンを利用することが一般的です。
クラスタ
- 1つ以上のマスターノードと1つ以上のワーカーノードから成り立つもの。
- コンテナ化されたアプリケーションを実行する、ノードと呼ばれるワーカーマシンの集合。
- すべてのクラスターには少なくとも1つのワーカーノードがある。
- Kubernetesクラスターは以下の2種類のリソースで構成されています
- マスターがクラスターを管理する
- ノードがアプリケーションを動かすワーカーとなる
標準化用語集 - Kubernetesドキュメント
Minikubeを使ったクラスターの作成 - Kubernetesドキュメント
Deployment
- アプリケーションのインスタンスを作成および更新する責務がある。
- コンテナのデプロイ状態。
- Kubernetesクラスター上にコンテナ化アプリケーションをデプロイするために必要な設定。
- アプリケーションのインスタンスを作成し、更新する方法を指示する。
- Deploymentを作成すると、KubernetesマスターはDeployment内に含まれるアプリケーションインスタンスをクラスター内の個々のノードで実行するようにスケジュールする。
- Deploymentを作成するときは、アプリケーションのコンテナイメージと実行するレプリカの数を指定する必要がある。
kubectlを使ったDeploymentの作成 - Kubernetesドキュメント
Deploymentのスケーリング
- トラフィックが増加した場合、ユーザーの需要に対応するためにアプリケーションをスケールする必要がある。
- スケーリングは、Deploymentのレプリカの数を変更することによって実現可能。
-
Deploymentをスケールアウトすると、新しいPodが作成され、使用可能なリソースを持つノードにスケジュールされる。
- スケールすると、Podの数が増えて新たな望ましい状態になる。
アプリケーションの複数インスタンスを実行 - Kubernetesドキュメント
ノード
- Podは常にノード上で動作する。
- ノードはKubernetesではワーカーマシンであり、クラスターに応じてVMまたは物理マシンになる。
- 複数のPodを1つのノードで実行できる。
- すべてのKubernetesノードでは少なくとも以下のものが動作する。
- Kubelet: Kubernetesマスターとノード間の通信を担当するプロセス。マシン上で実行されているPodとコンテナを管理します。
- レジストリからコンテナイメージを取得し、コンテナを解凍し、アプリケーションを実行することを担当する、Dockerのようなコンテナランタイム。
Podとノードについて - Kubernetesドキュメント
Pod
- 一番小さく一番シンプルな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
- クラスター外からクラスター内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