从未通过安全组的 Docker 容器中访问 RDS?
Posted
技术标签:
【中文标题】从未通过安全组的 Docker 容器中访问 RDS?【英文标题】:Accessing RDS from within a Docker container not getting through security group? 【发布时间】:2015-12-29 21:06:15 【问题描述】:我正在尝试在 docker 容器内运行一个使用带有 EC2 的 RDS 数据库的网络服务器。
我已设置安全组,因此允许 EC2 主机的角色访问 RDS,如果我尝试直接从主机访问它,一切正常。
但是,当我在主机上运行一个简单的容器并尝试访问 RDS 时,它会被阻止,就好像安全组不允许它通过一样。经过一堆试验和错误之后,似乎容器请求确实不是来自 EC2 主机,所以防火墙说不。
我可以通过在 docker 容器上设置 --net=host 在短期内解决这个问题,但是这破坏了很多很棒的 docker 网络功能,比如能够映射端口(即,现在我需要确保容器的每个实例手动侦听不同的端口)。
有没有人找到解决这个问题的方法?如果您实际使用任何 AWS 资源,那么在 AWS 中运行容器似乎是一个很大的限制。
【问题讨论】:
如果您无法控制容器的运行方式,也就是您无法发出docker run
命令,您如何使用--net
来运行容器?跨度>
当我尝试连接到 docker 容器内的 AWS RDS 时,我收到了 Access denied for user 'username'@'xxx.xx.xxx.x' (using password: YES)
错误。为了解决这个问题,我做了以下两种方法: 1.我创建了新用户并分配了授权。 ``` $ CREATE USER 'newuser'@'%' IDENTIFIED BY 'password'; $ GRANT ALL ON newuser@'%' IDENTIFIED BY 'password'; $刷新特权; ``` 2. docker 运行时将全局 DNS 地址8.8.8.8
添加到 docker 容器中。 ``` $ docker run --name backend-app --dns=8.8.8.8 -p 8000:8000 -d backend-app ```
【参考方案1】:
是的,容器确实会访问 RDS 的公共 IP。但是您不需要调整低级 Docker 选项以允许您的容器与 RDS 通信。 ECS集群和RDS实例必须在同一个VPC,然后可以通过安全组配置访问。最简单的方法是:
-
导航到 RDS 实例页面
选择数据库实例并深入查看详细信息
点击安全组ID
导航到“入站”选项卡并选择“编辑”
并确保有一个 mysql/Aurora 类型的规则和源自定义
输入自定义源时,只需开始输入ECS集群的名称,安全组名称将自动为您填写
This tutorial has screenshots 说明要去哪里。
全面披露:本教程介绍了来自 Bitnami 的容器,我为 Bitnami 工作。然而,这里表达的想法是我自己的想法,而不是 Bitnami 的意见。
【讨论】:
值得我自己托管运行 docker 的 ec2 机器,而不是使用 ECS(当时出于各种原因)。 我在这里是因为我的 ECS 任务无法连接到我在服务中为他们提供的安全组。我认为安全组是在启动时分配的。因此,如果您刚刚更新了 ECS 服务的安全组,我建议您重新启动您的任务。【参考方案2】:弄清楚发生了什么,在这里发布以防万一它帮助其他人。
来自容器内的请求访问的是 RDS 的公共 IP,而不是私有 IP(这是安全组的工作方式)。看起来 docker 容器内的 DNS 使用的是 8.8.8.8 google dns,这不会执行 AWS 将 rds 端点转换为私有 ip 的黑魔法。
例如:
DOCKER_OPTS="--dns 10.0.0.2 -H tcp://127.0.0.1:4243 -H unix:///var/run/docker.sock -g /mnt/docker"
【讨论】:
所以这个问题是有道理的,但是你能回答你是如何解决它的吗? 我也对您解决问题的方式感兴趣 我也遇到了同样的问题,对于没有看到 @alex-schokking 如何修复它感到有点失望,但对于遇到同样问题的其他人来说,这是我使用的修复:我发现 this article概述“VPC 的 DNS 解析器始终位于 +2 地址,因此如果 VPC 是 172.31.0.0/16,则 DNS 服务器将位于 172.31.0.2”,这给了我 DNS 服务器的 IP。然后我不得不将它添加到 docker 守护进程启动DOCKER_OPTS="--dns 172.31.0.2 --dns 8.8.8.8 --dns 8.8.4.4"
,重新启动它就可以了!
所以这对我在 EC2 中的 docker 容器中不起作用。它将主机名解析为内部地址,但拒绝访问。相同的 mysql 命令适用于 EC2 主机。
对不起,我错过了要求 dns 的 cmets,更新了当时最终为我工作的内容。【参考方案3】:
RDS 的入站规则应设置为 EC2 实例的私有 IP,而不是公共 IPv4。
【讨论】:
【参考方案4】:正如@adamneilson 所提到的,设置 Docker 选项是您最好的选择。这是discover your Amazon DNS server on the VPC的方法。此外,Amazon EC2 容器服务开发人员指南故障排除中的 Enabling Docker Debug Output 部分提到了 Docker 选项文件的位置。
假设您正在运行 10.0.0.0/24 的 VPC 块,则 DNS 将为 10.0.0.2。
对于 CentOS、Red Hat 和 Amazon:
sed -i -r 's/(^OPTIONS=\")/\1--dns 10.0.0.2 /g' /etc/sysconfig/docker
对于 Ubuntu 和 Debian:
sed -i -r 's/(^OPTIONS=\")/\1--dns 10.0.0.2 /g' /etc/default/docker
【讨论】:
【参考方案5】:当我尝试连接到 docker 容器内的 AWS RDS 时,我收到了 "Access denied for user 'username'@'xxx.xx.xxx.x' (using password: YES)"
错误。
为了解决这个问题,我做了以下两种方法:
我创建了新用户并分配了授权。
$ CREATE USER 'newuser'@'%' IDENTIFIED BY 'password';
$ GRANT ALL ON newuser@'%' IDENTIFIED BY 'password';
$ FLUSH PRIVILEGES;
在docker容器中添加全局DNS地址8.8.8.8
,使docker容器可以通过域名解析AWS RDS的IP地址。
$ docker run --name backend-app --dns=8.8.8.8 -p 8000:8000 -d backend-app
然后我从 docker 容器内部成功连接到 AWS RDS。
注意:首先,我尝试了第二种方法。但是我没有解决连接问题。当我尝试两种方式时,我成功了。【讨论】:
以上是关于从未通过安全组的 Docker 容器中访问 RDS?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Amazon EC2 容器服务 (ECS) 中使用不安全的 docker 注册表?