docker-compose
Docker操作の補佐をするPython製のツール(ver2ではGo製に変わっている)
Docker Engineの一部ではない。
docker-compose.yml内ではホスト側のシェルの環境変数が使える。
→つまり、host側で環境変数が設定されているためdirenvなどで読み込ませるのが良いのではないか?
設定した環境変数にどのような値が挿入されるかは、 docker-compose config
コマンドで確認ができる。
docker-compose はローカルで Docker のオーケストレーションを行うためのツールです。Docker のビルドから Network や Volume の管理をコードベースで定義して行ってくれます。
docker-compose.ymlをdocker-compose.ymlというツールで読み込ませて実行するとボリュームやネットワークが作られ、まとめてコンテナーが起動する。
docker-compose 優先度
docker run
と同様に、Dockerfileで指定されたオプションがデフォルトとして尊重されます(例:CMD,EXPOSE,VOLUME,ENV)
そのため、docker-compose.ymlで再び定義する必要はありません。
docker-composeでポート番号を考えなくてもよくなる方法
docker-compose で解決できるもの
Docker Composeを使えば、今までdocker runの引数で1つひとつ指定したり、起動後にdocker execでコマンドを実行していたりしたものをdocker-compose.ymlという1つの設定ファイルに集約できる。
docker-composeですむ場合
なるべくDockerfileを書きたくない 特殊なことをやっていないのであればdocker-composeから設定できるもので基本十分。
docker-compose depends_on
depends_onはあくまで起動状態を制御しているだけであり、dbがtcp受け付ける状態(mysqld)が起動するまで待つ。みたいなのができない。
以前までは、シェルで対応して欲しいと公式サイトが記載。
そのため幾つもプロジェクトはwait.shを使用し nc
コマンドなどでdbに意思疎通をしていた。
最新だと、それはしなくて良くなった。
Docker Compose の depends_on の使い方まとめ
注意
depends_on:
service_a:
condition: service_started
depends_on.condition.service_started
は1回非推奨になったが、3.8ぐらいでまた元に戻った。しかしdocker-compose 2系じゃないと使えない。
docker-compose オプション
基本オプション
-f, --f ファイル名
# プロジェクト名は現在いるディレクトリがデフォルトになるが明示的に指定することができる。
-p, --project--name プロジェクト
upオプション
# バックグランドで実行する。
-d, --detach
Docker自動起動
docker-composeを使ってサーバ環境を構築した際に、ホストOSを再起動時に自動でクライアント(子機?)も起動してほしい。k8sだのを使うべきとの意見もあるが、とりあえずDocker-composeのみで戦ってみる。 systemctlコマンドを利用して、自動起動の登録をしました。
docker-compose コマンド
docker-composeで作成したコンテナーはdockerコマンドではなく、docker-composeを使っ た管理(コマンド)に一元化すべき
$docker-compose down
はコンテナーやネットワークを停止するだけではなく、それらの破棄までしてくれる。
※規定ではボリュームは削除しない。
これのメリットとしてDBなどのキャッシュ問題を回避する。
dockerとの対比コマンド docker-composeで管理しているプロジェクトで、dockerコマンドを使用すると反故が生じる可能性もあるためdocker-composeコマンドを使用すること。
コンテナーは常に削除する方がいい
Docker開発を進めていく上でコンテナーは常に削除することをオススメ。
理由として
- psコマンドで確認すると一覧にコンテナーリストが溜まってくる
- コンテナーに直接インストールしたgemやパッケージがそのまま残ってしまう。 本番環境ではDockerfileから作成されたコンテナーをデプロイしますので、コンテナーに直接インストールしたものは反映されません。 常に本番環境と同じ状態で開発を進めるためにも、コンテナーは一度削除して再度立ち上げることを心がける。
docker-compose.yaml を読む
version: "3.7" # docker-composeのversionを指定。特にこだわりがなければ最新のものを記述する。
services: # 起動するコンテナーの定義を行う。
nginx:
build:
context: .
dockerfile: docker/nginx/Dockerfile
volumes:
- ./public:/var/www/html/public:ro
ports:
- 8080:80
environment:
PHP_HOST: app
app:
build:
context: .
dockerfile: Dockerfile
env_file:
- .env.example
# volumes:
# - .:/var/www/html:cached
mysql:
image: mysql:5.7 # コンテナーを起動するDocker imageを指定する。
volumes:
- ./mysql:/var/lib/mysql:delegated
command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
ports:
- 13306:3306
すべて3系として記載する。
-
version versionによって書き方が変わる。3系が最新。2系だと書き方が変わる。
-
services docker-composeでは、アプリケーションを動かすための各要素をサービスと読んでいる ComposeFile内の各サービス名は、わかりやすければなんでもいい。 ただ、ここで定義した名前は、dockerのログに表示されるので、わかりやすい名前にした方がいい
-
build docker buildの実行情報を記述する。ここで定義された情報を元にDockerをビルドし、そのビルドしたイメージを使用してコンテナーを起動するコーナー。 imageもしくはbuildどちらかを記述する必要がある。
コマンドの場合、
$ docker build -f docker/nginx/Dockerfile
. と同一。-
context docker buildコマンドを実行したときのカレントなワーキングディレクトリのことをビルドコンテキスト(build context)と呼ぶ。
-
dockerfile
-
-
image イメージが存在していなければ、Composeはpullを試みます。 しかしbuildを指定している場合は除きます。その場合、指定されたタグやオプションを使って構築します。 Docker Composeでビルド時に任意のイメージ名を指定する方法
-
stdin_open: true stdin_openとは標準入出力とエラー出力をコンテナーに結びつける設定です。
docker run -it <container_name>
の-i
にあたる設定
volumes
参考URL Docker for Mac のボリュームの遅さを cached オプションで解消
バインドマウントはローカルのファイルをマウントする。
ボリュームマウントはdockerシステム(ローカル)内に存在しているボリュームを指定。
存在しない場合は、指定した名称でボリュームが生成されます。
指定しない場合は、無名(無意味な文字列)でボリュームが生成されます。
ボリュームのマウントを行う。
volumesではパスを指定するとDockerエンジンはボリュームを作成する
コマンドの場合、
sh -v $(pwd)/public:/var/www/html/public:ro <IMAGE ID>
オプションと同一。
1行で記述 [SOURCE:]TARGET[:MODE]
services:
web:
image: nginx
volumes:
- type: volume
source: mydata # ホスト側
target: /data # targetはコンテナー側
volumes:
mydata:
sourceはホスト側で、targetはコンテナー側です、mydataはvolumeの名前でパスではない "/"から開始すると,絶対パスとなる。
version: "3"
services:
mysql:
container_name: sample
image: mysql:5.7
environment:
MYSQL_DATABASE:sample
MYSQL_USER: root
MYSQL_PASSWORD: root
MYSQL_ROOT_PASSWORD: root
ports:
- 4306:3306
##1
volumes:
- mysql-data:/var/lib/mysql
networks:
- default
##2
volumes:
mysql-data:
external:
name: project-mysql
services内で定義しているvolumes: は、いわゆるバインドマウントです。 実際のコンテナー内では、何を参照するか?をホスト側から明示しています。
2に関して トップレベルのvolumes: は、Dockerシステム(ローカル)内に存在しているボリュームを指定しています。いわゆるボリュームです。 external: の中にnameを指定することで、docker-compose外で作成したボリュームを指定できます。
volume trick
volumes:
- $PWD/backend:/app/backend:cached # バインドマウント
- node_modules_data:/app/backend/node_modules # バインドマウントするフォルダ中のnode_modulesのみvolumeマウントの対象とする
volumesのpathの指定
絶対パスではホストの環境が変わった時に動かなくなるため相対パスを指定するのが慣例。
相対パスはdocker-composeのymlファイルが基準となります。
このためホストの環境が変わっても問題ないですがプロジェクト内でのymlファイルの場所を変更する時は修正が必要になります。
volumes 省略記法
いつも上記の例のように記載するのは面倒なので短い表記法があります [SOURCE:]TARGET[:MODE]と指定します
たとえば以下でsourceの ./data
ディレクトリとtargetの/tmp/dataディレクトリを指定します
volumes:
- ./data:/tmp/data
docker-composeでのvolumes指定方法
- バインドマウント
- Docker内に存在しているボリューム ※external: の中にnameを指定することで、docker-compose外で作成したボリュームを指定できる。
注意 存在しない場合は、指定した名称でボリュームが生成される 指定しない場合は、無名(無意味な文字列)でボリュームが生成される
version: "3"
services:
mysql:
container_name: sample
image: mysql:5.7
environment:
MYSQL_DATABASE:sample
MYSQL_USER: root
MYSQL_PASSWORD: root
MYSQL_ROOT_PASSWORD: root
ports:
- 4306:3306
##1
volumes:
- mysql-data:/var/lib/mysql
networks:
- default
##2
volumes:
mysql-data:
external:
name: project-mysql
プロジェクトごとにMySQLのデータ用ボリュームを定義して使用し たい場合
externalをtrueにするとComposeの外部で作成されているボリュームを指定できます。
volumes:
mysql-data:
external: false
volume 一覧
services:
service_name:
volumes:
# ボリューム
- /var/lib/mysql # パス指定のみ。Engine にボリュームを生成させます。
- datavolume:/var/lib/mysql # 名前つきボリューム。
# バインドマウント
- /opt/data:/var/lib/mysql # 絶対パスのマッピングを指定。
- ./cache:/tmp/cache # ホストからのパス指定。Compose ファイルからの相対パス。
- ~/configs:/etc/configs/:ro # ユーザーディレクトリからの相対パス。
volumes:
dattavolume:
ports
ポートの開放を行う。 左にホストのポートを、右にコンテナーのポートを指定する。
コマンドの場合、 -p 8080:80 オプションと同一
※注意 左は外部から接続するポート 右はbridgeしたdocker networks内or自分自身を指すポート
docker-composeのportsとexposeの使い分け 参考URL
exposeはホストからアクセスできないポート portsはホストからアクセスできるポート
version: '3'
services:
postgres:
image: postgres:11-alpine
expose:
- "5432"
django:
image: django-web:latest
command: ash -c "
python3 manage.py migrate &&
python3 manage.py runserver 0.0.0.0:8000"
ports:
- "8000:8000"
postgresはdjangoからアクセスできればよいのでexposeを使用する。 djangoはホストのブラウザーからアクセスするのでportsを使用する。
ホストのポートを指定するのは必要がなければdocker-composeに一任するのがよいです.たとえば,ports: "5432:5432" と指定してpostgres を起動すると,複数のpostgresを使いたい時に,ポートで競合してエラーとなります.
Docker Compose の portsとexposeの違い
ports 指定したポートが外部に公開されるため、誰でもアクセスできる
expose ホストのみにポートを公開する
-
environment 起動するコンテナーへ環境変数を定義する。
コマンドの場合、 -e PHP_HOST=app オプションと同一で
DBについての環境変数設定(パスワード)だが、cfcのnuxtでもやっていたからそのコンテナーの環境変数を設定できそう。
-
env_file ファイルに定義された環境変数を読み取り、コンテナーへ定義する。
-
command Dockerfileで定義されているCMDの上書きを行う。
-
depends_on service同士の依存関係を記す docker-compose upを実行したら、依存関係のほうが先に実行していなければいけない。
-
external Docker compose管理外のネットワークやボリュームであることを示す。 これらのオプションが指定されたネットワークやボリュームはdocker-compose downによって削除されることはない。
-
links linksオプションはDockerで非推奨になっているためnetworksオプションに切り替える。
networks
参考URL networksを設定してネットワークを共有することで、複数のdocker-compose間での接続が可能になる。
tty(teletypewriter(テレタイプライター)
ttyがないと、コンテナーを起動させ続けるためのプロセスが存在しないためコンテナーが正常終了してしまう。
ttyとは
ttyとは、標準入出力となっている端末デバイス(制御端末、controlling terminal)の名前を表示するUnix系のコマンドである。元来ttyとはteletypewriter(テレタイプライター)のことを指す。
どうやらttyは標準入出力先のデバイスとのことです。 そして、その標準入出力先のデバイスを確認する方法が、ttyコマンドで、このコマンドはUnix系のコマンドであるため、ターミナルでttyとそのまま叩けます。