github actionsのubuntu環境でdocker-composeを用いてmysqlイメージを使うと問題が生じました
問題は2点でした
- volume mountでpermission denied
- container start 後にexecしたときに
no found container
(エラーはうろ覚え)
再現環境(うろ覚え)
- project
- docker-compose.yml
- .github
- workflows
- test.yml
- workflows
docker-compose.yml
verison: '3.8'
services:
db:
image: mysql
volumes:
- ./logs:/var/log/mysql
- ./my.cnf:/略/my.cnf
env:
略
.github/workflows/test.yml
# だめな例
name: workflow
on: push
jobs:
- test:
name: test
runs-on: ubuntu
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: start services
run: docker-compose up -d
- name: use db # データベースを利用する例、例えばsqlのimportなど
run: docker-compose exec -T db mydb < data.sql
volume mountでpermission denied
原因
- github actions の ubuntu上では、どうやらrootではなく,runner(1001):docker というuserで動作している
- github actions の ubuntu上ではdockerがインストールされておりrootで動作している(普通)
- dockerでhost-container間のvolume mountしたとき、hostに当該のディレクトリがない場合dockerがディレクトリを生成する(例で言う
./logs:/var/log/mysql
)- この時のディレクトリオーナーはrootになる
- mysqlイメージは起動時にログファイルを新規生成しようとするがその時の実行ユーザーはrootではない
- rootパーミッションの
./logs:/var/log/mysql
にログファイルを書き込めないとエラーになる
対策(案)
ログなどはstdoutなどに出してdocker-compose logsに集約する
良いと思うが成功していない
host-container間マウントをしない
良いと思う。
見たければmysqlサービスにexec ash
などで入って確認すればいい。
本番系ならマウントなどでなくてfluentdに転送するような気がするし、そもそもhost-container間マウントの必要性が感じられない。
hostでpermissonを調整したディレクトリを作っとく
hostにディレクトリがなければdockerがroot権限で勝手にディレクトリを作るが、もとからあるならそれを使う。
先の例だと
.github/workflows/test.yml
- # だめな例
+ # volume mountでpermission denied 解決版
name: workflow
on: push
jobs:
- test:
name: test
runs-on: ubuntu
steps:
- name: Checkout code
uses: actions/checkout@v2
+ - name: setup volume dir
+ run: |
+ mkdir logs #← runner(1001):dockerの7xxで作られる(うろ覚え)
+ chmod 777 logs # ← mysqlコンテナのログファイル書き込みプロセスが書けるようにガバガバにしておく(ciだし)。
+
- name: start services
run: docker-compose up -d
- name: use db # データベースを利用する例、例えばsqlのimportなど
run: docker-compose exec -T db mydb < data.sql
container start 後にexecしたときにno found container
原因
公式のmysqlイメージは、色々頑張っていて、コンテナ起動後に初期化処理にしばらく時間がかかる。
これを待つことはdockerの領域ではないため単純には不可能。
コンテナ=サービスはstartedだが実際にdbはまだ利用不可の瞬間がある。
対策
待つ
.github/workflows/test.yml
- name: start services
run: docker-compose up -d
+ - name: wait for db
+ run: |
+ while ! docker-compose exec -T db mysql -e "SELECT 1" >/dev/null 2>&1
+ do
+ sleep 1
+ done
+
- name: use db # データベースを利用する例、例えばsqlのimportなど
run: docker-compose exec -T db mydb < data.sql
試してみてダメだったこと
- TCPポートがlistenされるのを監視する
- その状態でも準備完了じゃないタイミングがあるっぽかったのでダメだった
- docker-compose logsの準備完了を示すログを監視する
- 参考: https://qiita.com/mpyw/items/a03941bc8bd2c95c1c66
- そのログが出たとしてもダメなタイミングがあった
- sleep
- 当然だけど、成功したとしてたまたまでしか無い
- 失敗しないように長めの秒数を取る?→利便性の低下&