El error Plugin 'mysql_native_password' is not loaded significa que tu cuenta de MySQL usa un método de autenticación que el servidor ya no carga, y se arregla convirtiendo esa cuenta a caching_sha2_password con ALTER USER. MySQL 8.4 lo desactiva por defecto, MySQL 9.0 lo eliminó y la etiqueta mysql:lts de Docker Hub apunta hoy a la 9.7.4. Esta guía reproduce el error, convierte las cuentas desde la 8.4, recupera el acceso si root también se ha quedado fuera y explica los dos saltos que MySQL no permite deshacer. Lo probé el 2 de noviembre de 2026 en Linux arm64 con Docker 29.5.2 y Compose v2.40.3. Tienes la versión en inglés de esta guía.

Puntos clave

  • mysql:lts, mysql:9 y mysql:9.7 apuntan a la 9.7.4, y mysql:latest a la 26.10.0; la 8.0.46 es la última de la serie 8.0, que llegó a su fin de vida en abril de 2026.
  • En la 9.7.4, las 3 cuentas creadas con mysql_native_password (dos de root y la de la aplicación) quedaron bloqueadas, aunque el servidor arrancó y aceptaba conexiones.
  • La única versión que puede leer esas cuentas es la 8.4, arrancada con --mysql-native-password=ON; allí se convierten con ALTER USER … IDENTIFIED WITH caching_sha2_password.
  • Un --default-authentication-plugin en el compose tumba la 8.4, pero solo después de actualizar el directorio de datos, que la 8.0 ya no abre.
  • La 9.7 rechaza datos de la 8.0, y mysql:latest (26.10) no deja volver a la 9.7 sin un volcado.

¿Qué significa Plugin ‘mysql_native_password’ is not loaded?

Significa que el servidor arrancó bien pero no tiene cargado el método de autenticación con el que se guardó la contraseña de tu cuenta. Por eso el contenedor aparece en marcha y la aplicación no conecta. Este es el mensaje exacto con el cliente mysql de la imagen 9.7.4, con mysqli de PHP 8.5.12 y con PyMySQL 1.2.3:

ERROR 1524 (HY000): Plugin 'mysql_native_password' is not loaded

mysqli_sql_exception: Plugin 'mysql_native_password' is not loaded

OperationalError(1524, "Plugin 'mysql_native_password' is not loaded")

El registro del servidor avisa en el arranque, una línea por cuenta afectada. No es un error, es un [Warning], así que un docker compose logs db | grep ERROR no lo encuentra:

[Warning] [MY-010312] [Server] The plugin 'mysql_native_password'
used to authenticate user 'wpuser'@'%' is not loaded. Nobody can
currently login using this account.

En mi prueba salieron tres avisos: root@localhost, root@% y wpuser@%. Root también queda fuera, lo que complica el arreglo si ya estás en la 9.7 (lo resuelve la sección sobre --skip-grant-tables).

Qué versiones de MySQL provocan el error

El error aparece en cuanto una cuenta con mysql_native_password llega a la 8.4 o a cualquier 9.x. Las notas de MySQL 8.4.0[1] desactivaron el método por defecto, y las notas de MySQL 9.0.0[2] lo eliminaron con esta frase: "The mysql_native_password authentication plugin, deprecated in MySQL 8.0, has been removed, and the server now rejects mysql_native authentication requests from older client programs which do not have CLIENT_PLUGIN_AUTH capability". Así quedaban las etiquetas oficiales el 2 de noviembre de 2026:

Etiqueta Versión mysql_native_password
mysql:8.0 8.0.46 activo
mysql:8, mysql:8.4 8.4.13 desactivado, se activa con --mysql-native-password=ON
mysql:lts, mysql:9, mysql:9.7 9.7.4 eliminado
mysql:latest, mysql:innovation 26.10.0 eliminado

Descargué las imágenes a través de mirror.gcr.io/library/mysql, y sus resúmenes coinciden con los que publica Docker Hub para las mismas etiquetas. La 8.0 no recibirá más versiones: según las notas de la serie 8.0[3], "As of April 2026, with version 8.0.46, MySQL 8.0 reaches End of Life (EoL)". Quien siga en mysql:8.0 tiene que pasar a la 8.4 y, después, a la 9.7.

Tus cuentas usan mysql_native_password en dos casos. El primero es que vengan de una instalación anterior a la 8.0. El segundo es que tu compose arranque el servidor con --default-authentication-plugin=mysql_native_password, un truco que se copió durante años para clientes PHP antiguos. El propio entorno Docker de desarrollo de WordPress lo llevaba hasta que el ticket 61218 de WordPress[4] lo adaptó a MySQL 8.4 en octubre de 2024.

Arreglo: convierte las cuentas desde MySQL 8.4

El arreglo seguro pasa por la 8.4, porque es la última versión que todavía autentica esas cuentas. El plan tiene cinco pasos:

  1. Haz una copia con mysqldump mientras aún puedes entrar
  2. Arranca la 8.4 con --mysql-native-password=ON
  3. Lista las cuentas afectadas y conviértelas con ALTER USER
  4. Quita la opción y comprueba que tus clientes conectan
  5. Cambia la imagen a mysql:9.7.4

Copia de seguridad antes de tocar la imagen

Haz la copia antes de cambiar la etiqueta, porque cada salto de versión reescribe el directorio de datos sin preguntar. Este volcado se guarda en el host y lo cargué después en una 9.7 vacía sin errores:

docker compose exec -T db sh -c 'exec mysqldump -uroot \
  -p"$MYSQL_ROOT_PASSWORD" --all-databases --single-transaction \
  --routines --events' > backup.sql

Arranca la 8.4 con mysql_native_password activado

Cambia la imagen a mysql:8.4 y sustituye cualquier --default-authentication-plugin por la opción nueva. Es la que indica la documentación de autenticación nativa de MySQL 8.4[5]:

services:
  db:
    image: mysql:8.4
    command: --mysql-native-password=ON
    volumes:
      - db_data:/var/lib/mysql

Con esa opción, mi cuenta wpuser volvió a entrar y leyó sus 500 filas. El registro deja un aviso de método obsoleto en cada conexión, y es esperable.

Lista las cuentas y conviértelas

Esta consulta devuelve las cuentas que fallarán en la 9.7. En mi laboratorio salieron tres:

SELECT user, host FROM mysql.user
WHERE plugin = 'mysql_native_password';

Convierte cada una con su contraseña actual. ALTER USER necesita la contraseña en claro, porque el hash antiguo no sirve para el método nuevo; si no la conoces, pon una nueva y actualiza la aplicación:

ALTER USER 'wpuser'@'%'
  IDENTIFIED WITH caching_sha2_password BY 'contraseña_actual_de_wpuser';
ALTER USER 'root'@'%'
  IDENTIFIED WITH caching_sha2_password BY 'contraseña_actual_de_root';
ALTER USER 'root'@'localhost'
  IDENTIFIED WITH caching_sha2_password BY 'contraseña_actual_de_root';

Repite la consulta anterior: tiene que devolver cero filas. Después quita la línea command: y reinicia la 8.4. Si tus clientes conectan sin la opción, conectarán con la 9.7.

Pasa a la 9.7

Cambia la imagen a mysql:9.7.4 y arranca. Fija la versión completa en lugar de lts, para que el siguiente salto lo decidas tú. En mi prueba el registro mostró la actualización del diccionario de datos y del servidor, de 80413 a 90704. Las 500 filas conservaron la misma suma de comprobación CRC32, y mysqli y PyMySQL conectaron sin cambios.

Si tu compose usa –default-authentication-plugin

Esa opción no existe desde la 8.4, y el servidor se para al leerla. El problema es el orden: en mi prueba la 8.4 primero actualizó los datos de la 8.0 y solo después abortó. Este es el registro:

Server upgrade from '80046' to '80413' completed.
[ERROR] [MY-000067] [Server] unknown variable
'default-authentication-plugin=mysql_native_password'.
[ERROR] [MY-010119] [Server] Aborting

Volver a mysql:8.0 ya no funciona, porque el directorio se quedó en formato 8.4:

[ERROR] [MY-014061] [InnoDB] Invalid MySQL server downgrade: Cannot
downgrade from 80413 to 80046. Downgrade is only permitted between
patch releases.

No es grave si sigues adelante: cambia la opción por --mysql-native-password=ON y continúa con el paso de ALTER USER. En la 9.7 la trampa se repite con la opción nueva: --mysql-native-password=ON en la 9.7.4 termina igual, con unknown variable 'mysql-native-password=ON' después de actualizar los datos.

Si ya estás en la 9.7 y root tampoco entra

Si tu volumen ya pasó a la 9.7 con las cuentas antiguas, no puedes volver a la 8.4 para convertirlas. La salida es arrancar una vez sin tabla de permisos, convertir las cuentas y reiniciar normal. Funcionó en mi prueba con la 9.7.4:

services:
  db:
    image: mysql:9.7.4
    command: --skip-grant-tables
    volumes:
      - db_data:/var/lib/mysql

Con esa opción el servidor desactiva la red (el registro dice port: 0), así que solo entras desde dentro del contenedor. FLUSH PRIVILEGES recarga los permisos para que ALTER USER funcione en la misma sesión:

docker compose exec db mysql -uroot -e "
FLUSH PRIVILEGES;
ALTER USER 'root'@'localhost'
  IDENTIFIED WITH caching_sha2_password BY 'contraseña_actual_de_root';
ALTER USER 'root'@'%'
  IDENTIFIED WITH caching_sha2_password BY 'contraseña_actual_de_root';
ALTER USER 'wpuser'@'%'
  IDENTIFIED WITH caching_sha2_password BY 'contraseña_actual_de_wpuser';"

Quita command: y vuelve a arrancar. En mi prueba desaparecieron los tres avisos MY-010312 y PHP leyó las 500 filas. Mientras dure, el servidor acepta a cualquiera desde el contenedor, así que no lo dejes así más de lo necesario.

Por qué no puedes saltar de MySQL 8.0 a la 9.7

MySQL solo admite el salto a la siguiente versión de soporte a largo plazo (LTS, Long-Term Support), de la 8.4 a la 9.7, sin saltarse ninguna. Lo dice la página de versiones de MySQL[6], y el servidor lo aplica. Al arrancar la 9.7.4 sobre datos de la 8.0.46 obtuve esto:

[ERROR] [MY-014060] [Server] Invalid MySQL server upgrade: Cannot
upgrade from 80046 to 90704. Upgrade to next major version is only
allowed from the last LTS release, which version 80046 is not.

Este rechazo es inofensivo: la 9.7 no toca los datos y la 8.0 volvió a arrancar sobre el mismo volumen. Con mysql:latest pasa lo mismo, con otro texto: "The source and target must be in the same compatibility lineage, unless the source is the immediately preceding LTS for the target". Desde la 8.0, el camino siempre es 8.0 → 8.4 → 9.7.

Cómo comprobar que la migración funcionó

Comprueba con una conexión real y no con mysqladmin ping. Con las cuentas bloqueadas en la 9.7, mysqladmin ping imprimió el error 1524 y aun así salió con código 0. La documentación de mysqladmin[7] lo explica: el código "is 0 even in case of an error such as Access denied". Un healthcheck con mysqladmin ping marca el contenedor como sano mientras la aplicación no conecta.

Un SELECT 1 con la cuenta de la aplicación sí devuelve 1 cuando falla la autenticación. Este healthcheck dejó el servicio en healthy con la 9.7.4; los $$ evitan que Compose sustituya las variables:

    healthcheck:
      test: ["CMD-SHELL", "mysql -h127.0.0.1 -u\"$$MYSQL_USER\"
        -p\"$$MYSQL_PASSWORD\" -e 'SELECT 1'"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 60s

Si quieres más detalle sobre start_period y depends_on, tienes la guía de healthchecks y políticas de reinicio en Docker Compose. Por el lado de los clientes, mysqli de PHP 8.5.12 (mysqlnd) conectó con caching_sha2_password en la 8.4.13, la 9.7.4 y la 26.10.0. PyMySQL 1.2.3 conectó en la 8.4.13 y la 9.7.4 sin el paquete cryptography de Python, también tras reiniciar el servidor.

mysql:latest ya es la 26.10: un camino sin vuelta

mysql:latest y mysql:innovation apuntan a la 26.10.0, publicada el 20 de octubre de 2026 según sus notas de versión[8]. Es una versión Innovation: según la página de versiones de MySQL, cada una tiene soporte solo hasta la siguiente, y desde la 9.7 MySQL numera por año y mes. Para el problema de este artículo no cambia nada: los únicos métodos de contraseña cargados son caching_sha2_password y sha256_password.

El riesgo está en la vuelta atrás. Mis datos de la 9.7.4 se actualizaron a la 26.10.0 sin errores, pero al volver a mysql:9.7 el servidor se negó:

[ERROR] [MY-014061] [InnoDB] Invalid MySQL server downgrade: Cannot
downgrade from 261000 to 90704. Downgrade is only permitted between
patch releases.

La salida fue el volcado: cargué en una 9.7.4 vacía el backup.sql hecho en la 26.10.0 y las 500 filas volvieron con la misma suma. Si alguien de tu equipo usa latest o un actualizador como Watchtower para contenedores Docker, fija mysql:9.7.4 antes de que el volumen se actualice solo.

Cuándo compensa pasarte a MariaDB

Si dependes de clientes que solo hablan mysql_native_password, MariaDB sigue aceptando ese método. En la prueba de MariaDB 13 en Docker, las cuentas con mysql_native_password siguieron entrando tras la actualización. El cambio de motor no es trivial: necesitas un volcado y una carga, y conviene que revises las diferencias de SQL antes. Para empezar de cero tienes la guía para instalar MariaDB con Docker.

Preguntas frecuentes

¿Puedo volver a cargar mysql_native_password en MySQL 9.7?

No. La 9.0 eliminó el método del servidor junto con la opción --mysql-native-password, y en la 9.7.4 esa opción provoca unknown variable. Las notas de la 9.0 indican que sigue existiendo en el lado del cliente, pero eso no ayuda a una cuenta guardada en el servidor.

¿Tengo que cambiar las contraseñas?

No necesariamente. ALTER USER … IDENTIFIED WITH caching_sha2_password BY admite la misma contraseña, y mis clientes siguieron conectando con las credenciales de siempre. Necesitas conocerla en claro; si no la tienes, pon una nueva y cámbiala también en la aplicación.

¿Por qué arranca el contenedor si nadie puede entrar?

Porque una cuenta sin método de autenticación no es un fallo del servidor. MySQL lo registra como [Warning] y abre el puerto 3306 con normalidad. Por eso un healthcheck con mysqladmin ping no detecta el problema y uno con SELECT 1 sí.

Conclusión

Plugin 'mysql_native_password' is not loaded no se arregla con una opción en la 9.7: se arregla convirtiendo las cuentas, y la versión para hacerlo es la 8.4. El orden es copia con mysqldump, 8.4 con --mysql-native-password=ON, ALTER USER, prueba sin la opción y, al final, mysql:9.7.4 fijada. Si ya estás en la 9.7, --skip-grant-tables te da una sesión para convertirlas. Antes de tocar nada, ejecuta la consulta de mysql.user sobre tu servidor actual: si devuelve cero filas, puedes subir de versión sin este problema.

Fuentes: [1] MySQL, notas de la versión 9.0.0[2], [2] MySQL, notas de la versión 8.4.0[1], [3] MySQL 8.4, autenticación nativa enchufable[5], [4] MySQL, versiones LTS e Innovation[6], [5] MySQL, notas de la serie 8.0 y fin de vida[3], [6] MySQL, notas de la versión 26.10.0[8], [7] MySQL 9.7, mysqladmin y el código de salida de ping[7], [8] WordPress, ticket 61218 sobre MySQL 8.4[4], [9] Etiquetas de mysql en Docker Hub[9].

Fuentes

  1. notas de MySQL 8.4.0
  2. notas de MySQL 9.0.0
  3. notas de la serie 8.0
  4. ticket 61218 de WordPress
  5. documentación de autenticación nativa de MySQL 8.4
  6. página de versiones de MySQL
  7. documentación de mysqladmin
  8. notas de versión
  9. Etiquetas de mysql en Docker Hub