go-cleanarchitectureにdocker-composeを導入した過程で学んだprofiles, volumes, networksの話。
https://github.com/IzumiSy/go-cleanarchitecture/blob/master/docker-compose.ymlgithub.com
profiles
ざっくり言うと、サービスをグループ化して部分的に起動できる。
そもそも、開発中のアプリケーションという"コロコロと中身の変化するもの"をDockerイメージにするのはあまりいいやり方ではない。少しでもコードが変更されるたびにdocker buildが必要で効率が悪い。なので、開発環境としてdocker-composeを使う場合にはミドルウェアだけをservicesとしてまとめて起動したほうがいい。
ただ、いかんともしがたい理由で開発中のアプリケーションもdocker-composeのサービスとして含めたいこともある。つまり、ローカルでアプリケーションを起動したいこともあればdocker-composeのイメージとしてアプリケーションを起動したいこともある、という場合にはprofilesが非常に便利。毎回、利用するprofileを指定する手間は若干あるが、逆に言えばそれだけでいい。
volumes
DockerでMySQLなどに対してボリュームを使いたい場合にはvolumesセクションで driver: local
なボリュームをあらかじめ作っておくといい。
# 以下で作ったボリュームは "mysqlvolume:/var/lib/mysql" みたいな感じで使える。 volumes: mysqlvolume: driver: local redisvolume: driver: local
ネットに転がっている記事では "./tmp/data/db:/var/lib/mysql"
のような記述でパス指定したボリュームをサービスに対して与えているものがあるが、この指定では ./tmp
ディレクトリのownerがrootになってしまう。すると、全サービスをdocker-composeで再起動したときに permission denied
なエラーがでて困る。
この権限周りとボリュームの話はよくあるエラーのようで、docker-composeを実行するときにユーザーを明示的に指定するなどの解決策があるらしい。が、最も簡単な解決策は明示的にホスト側のパスを指定せずボリュームを作ることだと思う。
元ネタとなる回答は以下のstackoverflowにある。
networks
docker-composeはデフォルトでそれっぽいネットワーク名をつけてくれるが、明示的にネットワーク名を指定すると便利なこともある。
# 以下で作ったネットワークは各サービスで app-network として指定すれば使える networks: default: external: name: bridge app-network: name: go-cleanarchitecture-network driver: bridge
たとえば自分のアプリケーションではマイグレーションにflywayを使っていて、ローカルにインストールせずDockerイメージとして起動するようにしている。この場合docker-composeで起動しているサービスに対してflywayのイメージが繋ぎにいくことになるわけだが、起動しているDockerコンテナ間で接続を行う際にはネットワーク名を指定しないといけない。
他にも、APIサーバに対するインテグレーションテストでdreddを利用していて、こちらも同様にDockerイメージとして利用している。
test/integration: docker run --net=go-cleanarchitecture-network --rm -it -v "$$(pwd):/app" -w /app apiaryio/dredd dredd \ api-description.apib http://app:8080 --hookfiles=./dredd_hook.js db/migrate: docker run --net=go-cleanarchitecture-network --rm -v "$$(pwd)/schemas/sql:/flyway/sql" -v "$$(pwd)/config:/flyway/config" \ flyway/flyway -configFiles=/flyway/config/flyway.conf -locations=filesystem:/flyway/sql migrate db/clean: docker run --net=go-cleanarchitecture-network --rm -v "$$(pwd)/schemas/sql:/flyway/sql" -v "$$(pwd)/config:/flyway/config" \ flyway/flyway -configFiles=/flyway/config/flyway.conf -locations=filesystem:/flyway/sql clean
docker-composeでグルーピングされたサービスとしては扱いたくないが局所的にテストやマイグレーションなどで使用する別のDocker-basedなツールがある、というケースであればネットワーク指定はあったほうが便利だと思われる。docker-composeで自動で付与されるネットワーク名を予想してもいいが、自分で指定したほうが確実。