Docker build時にmysqlで、permission deniedでエラーになる件
docker compose build --no-cacheを実施時のmysql起動時に、ホスト側(サーバー側)のUSERとDockerのコンテナ側のボリュームディレクトリのファイルの所有者、権限周りが異なりエラーになる件です。
エラーとなる流れを見ながら、解決方法について整理していきます。
failed to solve: error from sender: open /docker-mysql/db/data/#innodb_redo: permission denied
1.ボリュームディレクトリのおさらい
dockerを再起動すると、データなどを含むファイル群はリセットされてしまうので、永続化したい場合は、ボリュームディレクトリとして永続化設定をする必要がある。
docker-compose.yml
services:
# MySQL
db:
・・・(省略)
volumes:
- ./docker-mysql/db/data:/var/lib/mysql
- ./docker-mysql/db/my.cnf:/etc/mysql/conf.d/my.cnf
上記のように設定した場合、dockerコンテナ側で保存されたデータが、サーバー側のとあるファイルに同期され、dockerが再起動されてもデータが永続化されるイメージ。
以下のようなイメージで同期される
[サーバー側] docker-mysql/db/data -> [dockerコンテナ] /var/lib/mysql
[サーバー側] docker-mysql/db/my.cnf -> [dockerコンテナ] /etc/mysql/conf.d/my.cnf
上記「サーバー側」は、dockerFileがあるディレクトリ。
2.permission deniedエラーとなる流れ
2-1.dockerの初回起動時は正常終了する
初期状態は、ボリュームディレクトリがまだ存在していない状態なので、dockerの起動も正常終了しボリュームディレクトリも作成される
2-2.ボリュームディレクトリのファイル所有者は999で作成される
上記ボリュームディレクトリ作成時にファイル所有者がsystemd-timesync(999)で作成される
2-3.dockerを再起動すると所有者が異なりpermission deniedエラーとなる
dockerを停止し、dockerを再起動すると
docker compose build --no-cache
や
docker compose up -d
など
(ホスト側は、例としてuserが1000として稼働)、ホスト側のユーザーと、ボリュームディレクトリのファイル所有者が異なっているため、dockerビルドのmysql起動時にpermission deniedエラーとなってしまう。
3.permission deniedエラーの解決方法
3-1.docker-compose.ymlにてmysqlの起動userを指定する
docker-compose.ymlでuserを指定しないと、dockerのコンテナでmysqlを起動するuserが999になるので、docker-compose.yml側でuserを明示的に指定することで、dockerのmysqlが指定したユーザーで起動されるので、ボリュームファイルも指定したユーザーで作成してくれるということです。
services:
# MySQL
db:
・・・(省略)
volumes:
- ./docker-mysql/db/data:/var/lib/mysql # DB情報を永続化
- ./docker-mysql/db/my.cnf:/etc/mysql/conf.d/my.cnf
user: 1000:1000 →ここを追加
簡単に解決する場合は、上記の通り、普段サーバーで使用するuserをベタ書きで対応していますが、ちゃんとやるのであれば、動的にuserを取得し、dockerに反映させる形が良いかと思います。
# ユーザーID、グループID、所属グループなどの詳細情報を表示するコマンド
id
UID 1000の補足
通常、UID 1000 はシステム上の最初の通常ユーザーに割り当てられることが多いです。システム管理者(root)の UID は通常 0 で、UID 1~999 はシステムユーザーやデーモン(バックグラウンドプロセス)に予約されることが一般的です。UID 1000 以降は通常の一般ユーザーに割り当てられるため、初めて作成された一般ユーザーがこの UID を持つことがよくあります。
3-2.すでにボリュームディレクトリが作成済みの場合は、所有者を変更する
すでに、ボリュームディレクトリの所有者が999となっている場合は、上記docker-compose.ymlで指定したuserに合わせる形で、ファイルの所有者を変更(chown)していく必要があります。まだボリュームディレクトリが作成されていない場合(まだdockerを1回も起動していない場合)は不要です。
# ホスト側のボリュームディレクトリのファイル所有者がsystemd-timesync(999)になっているので、
# サーバーのuserの所有者にディレクトリごと変更する
# user hogeは1000とした場合の例
sudo chown -R hoge:hoge /docker-mysql/db/data/
上記で解決するはずです!
(トライアンドエラーで色々いじっていたので、途中chmodとかもしたかも。)