Dockerで「docker-compose up」コマンドなどでコンテナを起動したときに、データベースに接続できないエラーが発生する場合がある、このエラーの原因と対処法について。
docker-compose.ymlで起動した、wordpressサイトで発生した事例をベースに解説する。
エラーの内容と原因
docker-compose.ymlを使ってコンテナを起動後に、ページにアクセスしようとすると以下のようなエラーが表示される。
Warning: mysqli_real_connect(): php_network_getaddresses: getaddrinfo failed: Temporary failure in name resolution in /var/www/html/wp-includes/wp-db.php on line 1653 Warning: mysqli_real_connect(): (HY000/2002): php_network_getaddresses: getaddrinfo failed: Temporary failure in name resolution in /var/www/html/wp-includes/wp-db.php on line 1653
php_network_getaddresses: getaddrinfo failed: Temporary failure in name resolution
Error establishing a database connection
This either means that the username and password information in your wp-config.php file is incorrect or we can’t contact the database server at db:3306. This could mean your host’s database server is down.
Are you sure you have the correct username and password?
Are you sure you have typed the correct hostname?
Are you sure the database server is running?
If you’re unsure what these terms mean you should probably contact your host. If you still need help you can always visit the WordPress Support Forums.
エラーの理由は、データベース接続の確立中にエラーが発生したこと。想定されうる原因として以下があげられている。
- wp-config.php ファイルのユーザー名とパスワードの情報が正しくない
- db:3306 のデータベース サーバーに接続できない
- ホストのデータベース サーバーがダウンしている可能性がある
- ユーザー名とパスワードは正しか?
- 正しいホスト名を入力しているか?
- データベースサーバーは稼働しているか?
つまり、どこかで設定をミスっているということ。
データベースが起動しているか確かめる
Dockerコンテナ上でデータベースサーバーが起動しているかを確かめる。起動中のコンテナ一覧を表示するコマンド↓
$ docker ps
実行例は以下。この中で、mysqlなどデータベースのコンテナが起動していれば、データベースとの接続ミスが原因とわかる。
> docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1a1a43d5daeb wordpress:latest "docker-entrypoint.s…" 55 minutes ago Up 55 minutes 0.0.0.0:10090->80/tcp, :::10090->80/tcp wp
1d26cc849fcc phpmyadmin/phpmyadmin:latest "/docker-entrypoint.…" 55 minutes ago Up 55 minutes 0.0.0.0:10099->80/tcp, :::10099->80/tcp phpmyadmin
0d5ed1bddc0c mysql:5.6 "docker-entrypoint.s…" 55 minutes ago Up 55 minutes 3306/tcp mysql
wp_config.phpのデータベースの接続情報を確認する
WordPressでデータベースに接続する場合、設定情報は wp_config.phpに記述してある。この内容が、docker-compose.ymlで指定している内容と一致しているかを確認する。
wp_config.phpはルートディレクトリ直下にある。基本的には自動生成されるので編集は不要。
例えば、以下のようにgetenv_dockerという関数で、docker-compose.ymlの環境変数をそのまま引っ張ってくる指示になっていれば、このファイルに問題はない。
// ** MySQL settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define( 'DB_NAME', getenv_docker('WORDPRESS_DB_NAME', 'wordpress') );
/** MySQL database username */
define( 'DB_USER', getenv_docker('WORDPRESS_DB_USER', 'example username') );
/** MySQL database password */
define( 'DB_PASSWORD', getenv_docker('WORDPRESS_DB_PASSWORD', 'example password') );
/**
* Docker image fallback values above are sourced from the official WordPress installation wizard:
* https://github.com/WordPress/WordPress/blob/f9cc35ebad82753e9c86de322ea5c76a9001c7e2/wp-admin/setup-config.php#L216-L230
* (However, using "example username" and "example password" in your database is strongly discouraged. Please use strong, random credentials!)
*/
/** MySQL hostname */
define( 'DB_HOST', getenv_docker('WORDPRESS_DB_HOST', 'mysql') );
docker-compose.ymlのデータベースの接続情報を確認する
続いて、docker-compose.ymlのデータベースの接続情報を確認する。
例えば、ファイル内容が以下の場合、確認するポイントは大きく2点。(1) depends_on (2)environment
version: "3.7" # docker-composeの書式のバージョン
services: # 以下にサーバ情報を記載
db:
image: mysql:5.6
container_name: wp_mysql
#restart: always
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: wp_db
MYSQL_USER: wp_user
MYSQL_PASSWORD: root
wp:
image: wordpress:latest
container_name: wp
#restart: always
depends_on:
- db
ports:
- "10090:80"
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wp_user
WORDPRESS_DB_PASSWORD: root
WORDPRESS_DB_NAME: wp_db
WORDPRESS_DEBUG : 1
volumes:
- ./html:/var/www/html
depends_on
depends_onディレクティブは依存関係にあるサービス名を指定する。こうすることでコンテナを起動する前に、依存関係のコンテナを先に起動する。
depends_onに記述する名前が、サービス名と一致している必要がある。
(※ここが異なっていると、コンテナ起動時にエラーが発生するので、本質的には今回のエラーと関係がない)
environmetのWORDPRESS_DB_NAME
environmetの「WORDPRESS_DB_NAME」の値は、「MYSQL_DATABASE」の値と一致している必要があります。
「docker-compose up」でコンテナを起動したときに、MySQLの中に生成されるのは「MYSQL_DATABASE」で指定した名前のデータベースです。
WordPressのサービスからMySQLに接続するときも、同じデータベース名を指定する必要があります。
例えば上記の場合MySQLの「MYSQL_DATABASE」は「wp_db」です。
MYSQL_DATABASE: wp_db
このため、WordPressで接続先に指定するデータベースの名前も合わせる必要があります。
WORDPRESS_DB_NAME: wp_db
environmentのWORDPRESS_DB_HOST
今回のエラーの原因になっている可能性が一番高いのが環境変数 environmentの設定。
まず、データベースのサービスと、アプリケーション(Wordpress)のサービスで、データーベース名、ユーザー名、パスワードが一致している必要がある。
また、ホスト名とデータベースのサービス名が一致している必要がある。
WORDPRESS_DB_HOST: DBのサービス名:docker内の接続ポート番号
例えば、「WORDPRESS_DB_HOST: db:3306」の場合は、データベースのサービス名がdbである必要がある。
ここがズレていると、Error establishing a database connectionのエラーが発生する。
▼NG事例
project-db:
image: mysql:5.6
container_name: wp_mysql
#restart: always
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: wp_db
MYSQL_USER: wp_user
MYSQL_PASSWORD: root
project-wp:
image: wordpress:latest
container_name: wp
#restart: always
depends_on:
- project-db
ports:
- "10090:80"
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wp_user
WORDPRESS_DB_PASSWORD: root
WORDPRESS_DB_NAME: wp_db
WORDPRESS_DEBUG : 1
volumes:
- ./html:/var/www/html
上記例の場合、データベースのサービス名は「project-db」だが、環境変数で指定しているホスト名が「db」のままになっている。これだとDBに接続できずエラーが発生する。
もし、サービス名を変更した場合は、以下例のようにする必要がある。
project-db:
image: mysql:5.6
container_name: wp_mysql
#restart: always
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: wp_db
MYSQL_USER: wp_user
MYSQL_PASSWORD: root
project-wp:
image: wordpress:latest
container_name: wp
#restart: always
depends_on:
- project-db
ports:
- "10090:80"
environment:
WORDPRESS_DB_HOST: project-db:3306
WORDPRESS_DB_USER: wp_user
WORDPRESS_DB_PASSWORD: root
WORDPRESS_DB_NAME: wp_db
WORDPRESS_DEBUG : 1
volumes:
- ./html:/var/www/html
WordPressのルートディレクトリに生成されてしまったディレクトリを削除して、再度「docker-compose.yml」を実行し、ブラウザのキャッシュ削除後にアクセスすれば問題なく表示される。