Goプログラミング

Go Dockertestでコンテナが突然起動しなくなる

Goのテストでdockertestというテスト用コンテナをさくっと立ち上げるツールを利用していたところ、今まで正常に起動していたコンテナが突然起動しなくなることがあったのでメモっておきます。

スポンサーリンク

事象

こちらの記事を参考にしながらMySQLやOpenSearchを立ち上げるテストコードを書いてました。

コンテナを立ち上げるタイミングでテストデータを入れようと試行錯誤していたところ、以下のようなエラーでテスト用Dockerが突然起動しなくなりました。

$ go test  -v ./testdir
...
...
[error] failed to initialize database, got error dial tcp [::1]:32837: connect: connection refused
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x2 addr=0x0 pc=0x10304d6bc]
goroutine 1 [running]:
testdir/app_test.setupDB()
/Users/zoo200/testdir/app_test.go:122 +0xbc
testdir/app_test.TestMain(0x1400007bec8?)
...
...
FAIL
$                                                                                                                                                         

原因

起動しなかったMySQLのDockerコンテナがまだ残っていたので、ログを確認すると “Check also that the disk is not full or a disk quota exceeded” とディスク容量が足りないメッセージが出力されていました。

$ docker ps -a
CONTAINER ID   IMAGE       COMMAND                  CREATED         STATUS                     PORTS     NAMES
c79b5f851666   mysql:8.0   "docker-entrypoint.s…"   9 seconds ago   Exited (1) 4 seconds ago             unruffled_proskuriakova
$
$ docker logs c79b5f851666
...
...
2023-02-11T12:28:10.602202Z 8 [ERROR] [MY-012144] [InnoDB] posix_fallocate(): Failed to preallocate data for file mysql.ibd, desired size 1048576 bytes. Operating system error number 28. Check that the disk is not full or a disk quota exceeded. Make sure the file system supports this function. Refer to your operating system documentation for operating system error code information.
2023-02-11T12:28:10.603515Z 8 [Warning] [MY-012637] [InnoDB] 1048576 bytes should have been written. Only 737280 bytes written. Retrying for the remaining bytes.
2023-02-11T12:28:10.603540Z 8 [Warning] [MY-012638] [InnoDB] Retry attempts for writing partial data failed.
2023-02-11T12:28:10.603544Z 8 [ERROR] [MY-012639] [InnoDB] Write to file mysql.ibd failed at offset 29360128, 1048576 bytes should have been written, only 737280 were written. Operating system error number 28. Check that your OS and file system support files of this size. Check also that the disk is not full or a disk quota exceeded.
2023-02-11T12:28:10.603550Z 8 [ERROR] [MY-012640] [InnoDB] Error number 28 means 'No space left on device'
2023-02-11T12:28:10.603559Z 8 [Warning] [MY-012145] [InnoDB] Error while writing 1048576 zeroes to mysql.ibd starting at offset 29360128
2023-02-11T12:28:10.604346Z 8 [ERROR] [MY-013132] [Server] The table 'time_zone_transition' is full!
ERROR 1114 (HY000) at line 98871: The table 'time_zone_transition' is full
$
                                                                                                                                                    

OSのディスク容量は問題ありませんでしたが、こちらの記事のようにDockerデーモンが使用しているボリュームが圧迫していたようです。

対応

docker volume pruneで不要なデータを削除すると正常にコンテナが起動してテストが走るようになりました。

$ docker volume prune
WARNING! This will remove all local volumes not used by at least one container.
Are you sure you want to continue? [y/N] y
Deleted Volumes:
5549754a64f0c947813ca8b7fb383bb8d2780954d2c3593835a942763f854afb
...
Total reclaimed space: 35.11GB
$

根本的には、テストデータを用意する処理のエラーハンドリングでコンテナのPurge処理が漏れており、テストのたびに不要となったコンテナ、ボリュームが残ってしまうことが原因でした。

        // 記載箇所によっては、t.Cleanup,defer だったり
	if err != nil {
		pool.Purge(container.Resource)  // これを忘れていた
		os.Exit(1)
	}

このPurgeがテスト用のコンテナとボリュームを削除しているようです。

今回は以上です〜ノシ

参考

(`・ω・´)ノ アリガトウゴザイマス!!

GoでSQLテスト
mysqlの容量エラーでコンテナが起動できない状態を解決する
no space left on device エラーはDocker使用量が多いのが原因