1. 概述
Docker 容器默认通过虚拟网络获取动态 IP 地址。但在某些场景下,我们可能需要为容器分配一个静态 IP,例如在宿主机中直接访问某个容器,或者多个容器之间需要通过固定 IP 进行通信。
⚠️ 但首先需要思考:是否真的需要静态 IP?Docker 本身提供的网络机制(如服务名称解析)已经可以很好地支持容器间的通信。只有在确实需要固定 IP 的时候,才建议手动配置静态 IP。
本文将从 Docker 默认的 DHCP 和 DNS 机制讲起,逐步演示如何为容器分配静态 IP,包括使用 Docker CLI 和 Docker Compose 的方式,并附有完整的示例代码。
2. Docker 的 DHCP 与 DNS 机制
Docker 在创建容器时,会自动为其分配一个私有 IP 地址,其作用类似于一个 DHCP 服务器。
容器内部通过 Docker 守护进程(dockerd)内置的 DNS 服务解析其他容器的名称,从而实现通信。这意味着即使每次启动容器时 IP 地址不同,也可以通过服务名访问目标容器。
此外,dockerd 会将 DNS 查询转发给 CoreDNS(CNCF 项目),再根据域名决定是否转发给宿主机。
特殊域名:host.docker.internal
这个 DNS 名称会解析为宿主机的 IP 地址,使得容器可以访问宿主机上的服务,而无需硬编码 IP。虽然不推荐用于生产环境,但在开发阶段非常实用。
3. Docker 网络示例
我们以一个 MySQL 容器为例,展示默认网络配置。
docker-compose.yml 示例
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
查看容器网络信息:
docker inspect --format='{{json .NetworkSettings.Networks}}' compo-db-1 | jq .
输出示例:
{
"project_network": {
"IPAddress": "172.19.0.2",
...
}
}
说明容器获得了 172.19.0.2
的私有 IP 地址。
查看网络详情:
docker inspect project_network
你会看到该网络的子网为 172.19.0.0/16
,网关为 172.19.0.1
。
4. 为容器分配静态 IP
4.1. 使用 Docker CLI
先创建自定义网络:
docker network create --subnet=10.5.0.0/16 custom_net
然后运行容器并指定 IP:
docker run --detach \
--net custom_net \
--ip 10.5.0.5 \
-p 3306:3306 \
--mount source=db,target=/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=password \
mysql:latest
✅ 注意:必须先创建网络,再指定 IP。
4.2. 使用 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:
custom_net:
ipv4_address: 10.5.0.5
volumes:
db:
driver: local
networks:
custom_net:
driver: bridge
ipam:
config:
- subnet: 10.5.0.0/16
gateway: 10.5.0.1
✅ 说明:
ipam.config.subnet
:定义网络子网ipv4_address
:在服务中指定具体 IP 地址gateway
:通常设置为子网的第一个地址(如10.5.0.1
)
4.3. 验证连接
创建 init.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');
启动容器后,使用如下命令连接数据库:
mysql --host=mysql_db -u db_user -p
使用 status
命令查看连接状态:
Connection id: 10
Current database: test
Current user: [email protected]
SSL: Not in use
Connection: 97812e199512 via TCP/IP
说明连接成功。
4.4. 查看容器网络信息
使用 docker inspect
查看容器网络详情:
docker inspect mysql_db
输出示例:
{
"project_custom_net": {
"IPAMConfig": {
"IPv4Address": "10.5.0.5"
},
"Gateway": "10.5.0.1",
"IPAddress": "10.5.0.5",
...
}
}
✅ 说明:
IPv4Address
字段表示静态 IP- 网络名称前会加上项目目录名(如
project_custom_net
)
5. 小结
本文介绍了 Docker 默认的网络分配机制,并演示了如何为容器分配静态 IP 地址,包括:
- Docker CLI 手动创建网络并分配 IP
- Docker Compose 中通过
ipam
和ipv4_address
配置静态 IP - 如何验证数据库连接及网络信息
静态 IP 在某些特定场景(如测试、调试、网络隔离)中非常有用,但在大多数情况下,使用 Docker 的服务发现机制(如容器名解析)更为灵活可靠。
完整示例可参考:GitHub 示例仓库