dokcer-composeでちょっとハマったのでメモ
TLDR
- 単純に
docker-compose run service_name
すると設定したportがmappingされない docker-compose run --service-ports service_name
すれば良い
詳細
↓のようなdocker-compose.ymlがあったときに
version: '3.5' services: a: image: hoge ports: 1234:1234
service_aだけ実行したかったので、 $ docker-compose run a /bin/bash とaだけrunした。
プロセスをチェックしてみると、portsをmapping されていない。
$ docker-compose ps Name Command State Ports -------------------------------------------------------------------------------------------- reponame_a_1 /bin/bash Up
この問題に関してはGithubで質問されていたりして、詰まっている人は多いようだ。 Docker-compose run command doesnt map ports · Issue #1259 · docker/compose · GitHub
原因と解決策は、公式ドキュメントにしっかり書かれている。 run — Docker-docs-ja 17.06.Beta ドキュメント
使い方: run [オプション] [-e キー=バリュー...] サービス [コマンド] [引数...] オプション: -d デタッチド・モード: コンテナをバックグラウンドで実行し、新しいコンテナ名を表示 --name NAME コンテナに名前を割り当て --entrypoint CMD イメージのエントリーポイントを上書き -e KEY=VAL 環境変数を指定 (複数回指定できる) -u, --user="" 実行時のユーザ名または uid を指定 --no-deps リンクしたサービスを起動しない --rm コンテナ実行後に削除。デタッチド・モードの場合は無視 -p, --publish=[] コンテナのポートをホスト側に公開 --service-ports サービス用のポートを有効化し、ホスト側に割り当て可能にする -T 疑似ターミナル (pseudo-tty) 割り当てを無効化。デフォルトの `docker-compose run` は TTY を割り当て -w, --workdir="" コンテナ内のワーキング・ディレクトリを指定
のうち、↓を使えばよい。
--service-ports サービス用のポートを有効化し、ホスト側に割り当て可能にする
なので結論としては、
$ docker-compose run --service-ports service_name
とすればよい。
$ docker-compose ps Name Command State Ports -------------------------------------------------------------------------------------------- reponame_a_1 /bin/bash Up 0.0.0.0:1234->1234/tcp
正しくmappingされた🎉
「なんでそういう仕様なの?」という声も聞こえてきそうだが(Githubで「直したほうが良くね?」って言ってる人もいた)
理由もしっかり公式ドキュメントに書いてある。 run — Docker-docs-ja 17.06.Beta ドキュメント
2つめの違いとして、 docker-compose run コマンドはサービス設定ファイルで指定したポートを作成しません。これは、既に開いているポートとの衝突を避けるためです。
確かに?ただ docker-compose up
を2回すると衝突しそうだよな。と思って試したら新しくコンテナは作成されなかった。
公式ドキュメントにはその辺り明言されていないようにも見えるが雰囲気から、そういう仕様ということはわかる。
up — Docker-docs-ja 17.06.Beta ドキュメント もしサービス用のコンテナが存在している場合、かつ、コンテナを作成後にサービスの設定やイメージを変更している場合は、 docker-compose up -d を実行すると、 設定を反映するためにコンテナを停止・再作成します(マウントしているボリュームは、そのまま保持します)。Compose が設定を反映させないようにするには、 --no-recreate フラグを使います。
まとめ
公式ドキュメントをしっかり読むと色々わかるからしっかり読もう