拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 为Docker 容器和Docker-Compose 分配静态IP

为Docker 容器和Docker-Compose 分配静态IP

白鹭 - 2022-09-24 2179 0 3

一、概述

当我们运行Docker 容器时,它使用IP 地址连接到虚拟网络。因此,我们希望服务能够动态获取配置。但是,我们可能希望使用静态IP 而不是自动IP 分配。

在本教程中,我们将看到内置配置和为容器分配手动IP 之间的区别。最后,我们将添加一些带有测试的Docker Compose 示例。

2.DHCP和DNS

让我们看看使用DHCP 和DNS 为容器分配Docker 内置IP 以解析主机名。

2.1。Docker 如何分配IP

Docker 首先为每个容器分配一个IP,充当DHCP 服务器。此外,还有多个DNS 服务器。

然后容器使用dockerd内的服务器处理DNS 请求,该服务器识别同一内部网络上其他容器的名称。这样,容器可以在不知道其内部IP 地址的情况下进行通信。尽管每次应用程序启动时内部IP 地址可能不同,但由于dockerd内部的内部DNS 服务器,容器仍然可以轻松地以人类可读的名称连接。

然后,dockerd将名称查找发送到CoreDNS(来自CNCF)。最后,请求会根据域名移动到主机。

docker.internal有一个侧面案例。它包括解析为当前主机的有效IP 地址的DNS 名称host.docker.internal它允许容器联系这些主机服务,而不必担心硬编码IP 地址。虽然不推荐,但它可以方便地用于开发目的。

2.2.网络示例

例如,我们可以为MySQL 服务运行一个容器。让我们看看Docker Compose YAML 定义:

services:
 db:
 image: mysql:latest
 environment:
 - MYSQL_ROOT_PASSWORD=password
 - MYSQL_ROOT_HOST=localhost
 ports:
 - 3306:3306
 volumes:
 - db:/var/lib/mysql
 networks:
 - network

 volumes:
 db:
 driver: local

 networks:
 network:
 driver: bridge

像往常一样,我们运行我们的容器:

docker-compose up -d

让我们从容器的角度检查网络,使用jq format语法来获取JSON 输出:

docker inspect --format='{{json .NetworkSettings.Networks}}' 2d3f4c69a213 | jq .

Docker Compose 根据当前目录分配网络名称。例如,如果我们在project目录中,我们可以看到类似的输出:

{
 "project_network": {
 "IPAMConfig": null,
 "Links": null,
 "Aliases": [
 "project-db-1",
 "db",
 "2d3f4c69a213"
 ],
 "NetworkID": "39ffbd8155d11ba03d0b548307f549f06790fe045e121a6d862b070d4fb67fa7",
 "EndpointID": "0eba235239b06f7e0cb5065b7f2ebd83e7d227f8cfad4df8de73260472737500",
 "Gateway": "172.19.0.1",
 "IPAddress": "172.19.0.2",
 "IPPrefixLen": 16,
 "IPv6Gateway": "",
 "GlobalIPv6Address": "",
 "GlobalIPv6PrefixLen": 0,
 "MacAddress": "02:42:ac:13:00:02",
 "DriverOpts": null
 }
 }

容器从网络创建的子网中获取私有172.19.0.2IP 地址。

最重要的是,我们可以看到有关IPAMConfig的信息,即IP 地址管理。当我们静态分配IP 时,这将是相关的。

现在,我们可以检查网络:

docker inspect network project_network

这一次,我们对网络有了更深入的了解:

[
 {
 "Name": "project_network",
 "Id": "39ffbd8155d11ba03d0b548307f549f06790fe045e121a6d862b070d4fb67fa7",
 "Created": "2022-09-09T16:19:26.27396468+02:00",
 "Scope": "local",
 "Driver": "bridge",
 "EnableIPv6": false,
 "IPAM": {
 "Driver": "default",
 "Options": null,
 "Config": [
 {
 "Subnet": "172.19.0.0/16",
 "Gateway": "172.19.0.1"
 }
 ]
 },
 "Internal": false,
 "Attachable": false,
 "Ingress": false,
 "ConfigFrom": {
 "Network": ""
 },
 "ConfigOnly": false,
 "Containers": {
 "2d3f4c69a2139dea9089a6d42907fdc085282c5df176b39bf7c20f5d0780179d": {
 "Name": "project-db-1",
 "EndpointID": "7447fe2550afb3f980f36449673724e9ed6dd16f41a085cc20ada3074a0d8e54",
 "MacAddress": "02:42:ac:13:00:02",
 "IPv4Address": "172.19.0.2/16",
 "IPv6Address": ""
 }
 },
 "Options": {},
 "Labels": {
 "com.docker.compose.network": "network",
 "com.docker.compose.project": "project",
 "com.docker.compose.version": "2.10.2"
 }
 }
 ]

值得注意的是,Docker Compose网络从版本2 开始就可用。

3.静态IP

了解更多关于自动IP 分配的知识后,我们现在将创建我们的网络子网。然后我们可以为我们的服务分配我们喜欢的IP。

3.1。分配静态IP

如果我们使用Docker CLI,我们将通过首先创建子网来实现此结果:

docker network create --subnet=10.5.0.0/16 mynet

然后,我们使用静态IP 运行容器,再次使用MySQL 服务:

docker run --net mynet --ip 10.5.0.1 -p 3306:3306 --mount source=db,target=/var/lib/mysql -e MYSQL_ROOT_PASSWORD=password mysql:latest

我们可以使用Docker Compose 完成一个完整的示例:

services:
 db:
 container_name: mysql_db
 image: mysql:latest
 environment:
 - MYSQL_ROOT_PASSWORD=password
 - MYSQL_ROOT_HOST=10.5.0.1
 ports:
 - 3306:3306
 volumes:
 - db:/var/lib/mysql
 - ./init.sql:/docker-entrypoint-initdb.d/init.sql
 networks:
 network:
 ipv4_address: 10.5.0.5

 volumes:
 db:
 driver: local

 networks:
 network:
 driver: bridge
 ipam:
 config:
 - subnet: 10.5.0.0/16
 gateway: 10.5.0.1

现在,我们已经通过ipam关键字定义了network的子网,并为服务分配了IPv4 地址。为了改变,我们使用10.5.0.5172.* 和10.* IP 地址通常用于专用网络。我们也可以使用IPv6地址,它的地址长度为128 位,由于效率更高,它将取代IPv4。

按照建议,我们将网关地址分配给数据库主机MYSQL_ROOT_HOST

最后,我们添加一个SQL 脚本来创建用户、数据库和表:

CREATE DATABASE IF NOT EXISTS test;
 CREATE USER 'db_user'@'10.5.0.1' IDENTIFIED BY 'password';
 GRANT ALL PRIVILEGES ON *.* TO 'db_user'@'10.5.0.1' WITH GRANT OPTION;
 FLUSH PRIVILEGES;

 use test;

 CREATE TABLE IF NOT EXISTS TEST_TABLE (id int, name varchar(255));

 INSERT INTO TEST_TABLE VALUES (1, 'TEST_1');
 INSERT INTO TEST_TABLE VALUES (2, 'TEST_2');
 INSERT INTO TEST_TABLE VALUES (3, 'TEST_3');

我们只想让用户访问该特定地址的数据库。

容器启动后,我们可以用docker ps查看它的定义:

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
 97812e199512 mysql:latest "docker-entrypoint.s…" 7 minutes ago Up 7 minutes 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp mysql_db

我们现在可以通过输入密码连接到数据库。我们使用容器名称或ID,因为它们解析为DNS 的别名:

mysql --host=mysql_db -u db_user -p

现在,使用status命令,我们可以测试我们的MySQL 主机是否解析为容器ID:

Connection id: 10
 Current database: test
 Current user: [email protected]
 SSL: Not in use
 Current pager: stdout
 Using outfile: ''
 Using delimiter: ;
 Server: MySQL
 Server version: 8.0.30 MySQL Community Server - GPL
 Protocol version: 10
 Connection: 97812e199512 via TCP/IP
 Server characterset: utf8mb4
 Db characterset: utf8mb4
 Client characterset: utf8mb3
 Conn. characterset: utf8mb3
 TCP port: 3306

3.2.与内置Docker IP 管理的区别

让我们检查一下容器。在静态IP 的情况下,我们可以看到IPAM配置现在有一个IPv4 地址:

{
 "project_network": {
 "IPAMConfig": {
 "IPv4Address": "10.5.0.5"
 },
 "Links": null,
 "Aliases": [
 "project_db",
 "db",
 "122c0c6bfcf9"
 ],
 "NetworkID": "7ac7a1d9e33dffc65bc867aee4db04b9b8fecaeb3bbb91c74c2f72e4611c6955",
 "EndpointID": "84145191a0327b777b6a31bacb2a0260d9a31e8c22cbfca1923775b3649b1d7e",
 "Gateway": "10.5.0.1",
 "IPAddress": "10.5.0.5",
 "IPPrefixLen": 16,
 "IPv6Gateway": "",
 "GlobalIPv6Address": "",
 "GlobalIPv6PrefixLen": 0,
 "MacAddress": "02:42:0a:05:00:05",
 "DriverOpts": null
 }
 }

从容器的角度来看,这是主要区别。

如果我们需要一个静态的私有IP 地址,我们应该考虑是否需要使用一个。大多数时候,我们希望静态IP 从另一个容器或主机与一个容器通信。Docker 的内置网络已经可以处理这个问题。

但是,我们可能想要手动指定一个私有IP 地址,例如,直接从主机访问容器。

值得注意的是使用Docker Swarm自定义网络的可能性。

4。结论

在本文中,我们了解了Docker 如何管理IP 分配以及如何向容器添加静态地址。我们还看到了运行MySQL 服务的Docker Compose 配置示例,有或没有静态IP。



标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *