如何从 AWS SAM 本地 docker 实例连接到主机 MySQL?
Posted
技术标签:
【中文标题】如何从 AWS SAM 本地 docker 实例连接到主机 MySQL?【英文标题】:How do I connect to host MySQL from AWS SAM local docker instance? 【发布时间】:2018-12-29 14:21:27 【问题描述】:我正在尝试使用 sam local invoke
调用我的 Lambda 函数,但发现它无法连接到我的主机 mysql。我尝试添加--docker-network host
,但它也无法连接
Traceback (most recent call last):
File "/usr/lib/python3.6/site-packages/docker/api/client.py", line 229, in _raise_for_status
response.raise_for_status()
File "/usr/lib/python3.6/site-packages/requests/models.py", line 935, in raise_for_status
raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 400 Client Error: Bad Request for url: http+docker://localhost/v1.35/networks/6ad3bd87e8437e8410145d169a4edf68d1b0247a67257ce7dd1208dac3664c82/connect
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/bin/sam", line 11, in <module>
load_entry_point('aws-sam-cli==0.5.0', 'console_scripts', 'sam')()
File "/usr/lib/python3.6/site-packages/click/core.py", line 722, in __call__
return self.main(*args, **kwargs)
File "/usr/lib/python3.6/site-packages/click/core.py", line 697, in main
rv = self.invoke(ctx)
File "/usr/lib/python3.6/site-packages/click/core.py", line 1066, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/usr/lib/python3.6/site-packages/click/core.py", line 1066, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/usr/lib/python3.6/site-packages/click/core.py", line 895, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "/usr/lib/python3.6/site-packages/click/core.py", line 535, in invoke
return callback(*args, **kwargs)
File "/usr/lib/python3.6/site-packages/click/decorators.py", line 64, in new_func
return ctx.invoke(f, obj, *args[1:], **kwargs)
File "/usr/lib/python3.6/site-packages/click/core.py", line 535, in invoke
return callback(*args, **kwargs)
File "/usr/lib/python3.6/site-packages/samcli/commands/local/invoke/cli.py", line 47, in cli
docker_network, log_file, skip_pull_image, profile) # pragma: no cover
File "/usr/lib/python3.6/site-packages/samcli/commands/local/invoke/cli.py", line 79, in do_cli
stderr=context.stderr)
File "/usr/lib/python3.6/site-packages/samcli/commands/local/lib/local_lambda.py", line 80, in invoke
stdout=stdout, stderr=stderr)
File "/usr/lib/python3.6/site-packages/samcli/local/lambdafn/runtime.py", line 83, in invoke
self._container_manager.run(container)
File "/usr/lib/python3.6/site-packages/samcli/local/docker/manager.py", line 61, in run
container.create()
File "/usr/lib/python3.6/site-packages/samcli/local/docker/container.py", line 115, in create
network.connect(self.id)
File "/usr/lib/python3.6/site-packages/docker/models/networks.py", line 57, in connect
container, self.id, *args, **kwargs
File "/usr/lib/python3.6/site-packages/docker/utils/decorators.py", line 19, in wrapped
return f(self, resource_id, *args, **kwargs)
File "/usr/lib/python3.6/site-packages/docker/api/network.py", line 248, in connect_container_to_network
self._raise_for_status(res)
File "/usr/lib/python3.6/site-packages/docker/api/client.py", line 231, in _raise_for_status
raise create_api_error_from_http_exception(e)
File "/usr/lib/python3.6/site-packages/docker/errors.py", line 31, in create_api_error_from_http_exception
raise cls(e, response=response, explanation=explanation)
docker.errors.APIError: 400 Client Error: Bad Request ("container cannot be disconnected from host network or connected to host network")
我注意到最后一行:
docker.errors.APIError: 400 Client Error: Bad Request(“容器无法与主机网络断开连接或连接到主机网络”)
我该如何解决这个问题?
【问题讨论】:
将您目前拥有的内容与this github repo 进行比较可能会有所帮助 您能说明一下您的数据库在哪里运行吗?它是在云端还是在您的本地笔记本电脑或其他地方?你可以从容器外部连接到它吗? 【参考方案1】:连接mysql时无需配置,只需在主机下方添加
对于 Windows:docker.for.win.localhost
对于 mac:docker.for.mac.localhost
const con = require('serverless-mysql')(
config:
host : 'docker.for.win.localhost',
database : 'db-name',
user : 'root',
connectTimeout : 5000,
password : ''
);
【讨论】:
请注意docker.for.win.localhost
已弃用,新的官方 DNS 名称为 host.docker.internal
【参考方案2】:
您能发布一下您是如何在本地启动 mysql 容器的吗?如果没有更多信息,很难说出了什么问题。
这里有一些一般性的建议。
如果您在 Mac 上运行
在容器中配置 mysql 客户端时,您可以在本地使用特殊的主机名进行调用。它将在本地解析,不需要 --docker-network
标志。
例如:
host = 'docker.for.mac.localhost'
或者在新安装的 docker https://docs.docker.com/docker-for-mac/release-notes/#docker-community-edition-17120-ce-mac49-2018-01-19
host = 'docker.for.mac.host.internal'
前 python 代码。
import mysql.connector
host = 'docker.for.mac.host.internal'
cnx = mysql.connector.connect(user='scott', password='password',
host=host,
database='employees')
cnx.close()
如果你不在 Mac 上
然后确保您在启动 mysql 容器时传递了--docker-network
,它应该看起来像这样。
docker run -d -v "$PWD":/var/lib/mysql -p 3306:3306 \
--network lambda-local \
--name mysql \
mysql
然后在本地调用时
sam local invoke --docker-network lambda-local
然后在您的 lambda 代码中,您只需使用网络 --name
您将 mysql 容器作为主机名传递。
例如:
import mysql.connector
host = 'mysql'
cnx = mysql.connector.connect(user='scott', password='password',
host=host,
database='employees')
cnx.close()
【讨论】:
【参考方案3】:我不能说为什么--docker-network host
会产生这个错误,但我认为你不需要它。我可以从 SAM 本地连接到在我的本地计算机上运行的 MySQL,而无需任何网络覆盖。
我通过简单地使用我的本地 IP(而不是 localhost
或 127.0.0.1)连接到数据库来做到这一点。
下面的 lambda 函数可以很好地连接到我的本地 MySQL,只要我使用我的本地 IP,因为显示了像 ipconfig
这样的工具。
'use strict';
var mysql = require('mysql');
var connection = mysql.createConnection(
host : '192.168.1.6',
user : 'mike',
password : 'password',
database : 'logtest'
);
module.exports.hello = (event, context, callback) =>
connection.connect();
connection.query('SELECT 1 + 1 AS solution', function (error, results, fields)
if (error) throw error;
console.log('The solution is: ', results[0].solution);
const response =
statusCode: 200,
body: JSON.stringify(solution: results[0].solution)
;
connection.end();
callback(null, response);
);
;
部分ipconfig
输出:
Ethernet adapter Local Area Connection 6:
Connection-specific DNS Suffix . :
Link-local IPv6 Address . . . . . : fe80::95c2:495c:7226:8ac2%39
IPv4 Address. . . . . . . . . . . : 10.251.19.6
Subnet Mask . . . . . . . . . . . : 255.255.255.0
Default Gateway . . . . . . . . . :
Wireless LAN adapter Wireless Network Connection:
Connection-specific DNS Suffix . :
Link-local IPv6 Address . . . . . : fe80::496a:d34d:8380:3b1c%15
IPv4 Address. . . . . . . . . . . : 192.168.1.6
Subnet Mask . . . . . . . . . . . : 255.255.255.0
Default Gateway . . . . . . . . . : 192.168.1.1
在这种情况下,我的 lambda 函数可以使用 10.251.19.6 或 192.168.1.6 连接到本地 MySQL。
最小的example here。
【讨论】:
我同意这里的观点。虽然我不完全确定您的主机网络为什么不工作,但这不太可能与网络客户端功能相关。 这个问题我已经坐了好几个小时了。感谢您的回答!【参考方案4】:您可以按以下方式检查案例:
docker 端口是否有映射。 检查AWS安全组的端口。【讨论】:
以上是关于如何从 AWS SAM 本地 docker 实例连接到主机 MySQL?的主要内容,如果未能解决你的问题,请参考以下文章
如何从 cli 本地连接到现有的弹性 beanstalk 实例?
从 Table Plus 连接到我的本地 docker 数据库实例
AWS Lambda 无法连接到 RDS 实例,但我可以在本地连接?