LoginSignup
5

More than 3 years have passed since last update.

Github Actions上でDockerのmysqlイメージを使ってハマったこと

Last updated at Posted at 2021-02-17

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
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の準備完了を示すログを監視する
  • sleep
    • 当然だけど、成功したとしてたまたまでしか無い
    • 失敗しないように長めの秒数を取る?→利便性の低下&

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5