Docker容器间MySQL Access Denied for User
简介
Docker 是一种流行的容器化平台,可以轻松创建、部署和管理应用程序。在使用 Docker 部署多个容器时,可能会遇到容器间的访问权限问题。一种常见的问题是在容器间访问 MySQL 数据库时出现 "Access denied for user" 的错误。本文将介绍如何解决这个问题,并提供具体的代码示例。
解决方法
方法一:使用环境变量
一个容器中的环境变量可以通过 docker run
命令的 --env
参数设置。在容器启动时,可以通过设置环境变量来指定 MySQL 数据库的用户名和密码。下面是一个示例:
```bash
docker run --name mysql-container -e MYSQL_ROOT_PASSWORD=PASSWORD -d mysql:latest
在另一个容器中,可以使用类似的方法来连接到 MySQL 数据库:
```markdown
```python
import mysql.connector
mydb = mysql.connector.connect(
host=mysql-container,
user=root,
password=PASSWORD
)
print(mydb)
### 方法二:使用 Docker 网络
另一种方法是使用 Docker 的网络功能。可以创建一个 Docker 网络,并将多个容器连接到该网络中。这样,容器之间就可以使用容器名称来进行通信,而无需使用 IP 地址。下面是一个示例:
```markdown
```bash
docker network create my-network
docker run --name mysql-container --network my-network -e MYSQL_ROOT_PASSWORD=PASSWORD -d mysql:latest
docker run --network my-network my-container
在 my-container 中,可以使用容器名称 `mysql-container` 来连接到 MySQL 数据库:
```markdown
```python
import mysql.connector
mydb = mysql.connector.connect(
host=mysql-container,
user=root,
password=PASSWORD
)
print(mydb)
## 示例
为了更好地说明上述解决方法,下面是一个完整的示例。
### 类图
```mermaid
classDiagram
class MySQLContainer {
+__init__(name: str, password: str)
+start()
}
class AppContainer {
+__init__(name: str)
+start()
}
MySQLContainer --* AppContainer
序列图
sequenceDiagram
participant MySQLContainer
participant AppContainer
MySQLContainer->>AppContainer: Request
Note right of AppContainer: AppContainer.connect()
AppContainer->>+MySQLContainer: Request MySQL connection details
MySQLContainer->>-AppContainer: Response with connection details
AppContainer->>MySQLContainer: Connect to MySQL
Note left of AppContainer: AppContainer.run()
AppContainer->>MySQLContainer: Request data from MySQL
MySQLContainer->>AppContainer: Response with data
AppContainer->>MySQLContainer: Close MySQL connection
AppContainer->>-MySQLContainer: Response to client
代码示例
MySQLContainer.py
import docker
class MySQLContainer:
def __init__(self, name, password):
self.name = name
self.password = password
self.client = docker.from_env()
self.container = None
def start(self):
self.container = self.client.containers.run(
'mysql:latest',
name=self.name,
environment=[
f'MYSQL_ROOT_PASSWORD={self.password}'
],
detach=True
)
# Wait for MySQL to start
self.container.exec_run('mysqladmin --wait=30 ping')
print(f'MySQL container {self.name} started')
def stop(self):
if self.container:
self.container.stop()
self.container.remove()
print(f'MySQL container {self.name} stopped')
AppContainer.py
import mysql.connector
class AppContainer:
def __init__(self, name):
self.name = name
self.client = docker.from_env()
self.container = None
def start(self):
self.container = self.client.containers.run(
'app-image:latest',
name=self.name,
network='my-network',
detach=True
)
print(f'App container {self.name} started')
def stop(self):
if self.container:
self.container.stop()
self.container.remove()
print(f'App container {self.name} stopped')
def connect(self):
mysql_container = self.client.containers.get('mysql-container')
return mysql_container.attrs['NetworkSettings']['Networks']['my-network']['IPAddress']
def run(self):
mysql_ip = self.connect()
mydb = mysql.connector.connect(
host=mysql_ip,
user='root',
password='PASSWORD'
)