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 中通过 ipamipv4_address 配置静态 IP
  • 如何验证数据库连接及网络信息

静态 IP 在某些特定场景(如测试、调试、网络隔离)中非常有用,但在大多数情况下,使用 Docker 的服务发现机制(如容器名解析)更为灵活可靠。

完整示例可参考:GitHub 示例仓库


原始标题:Assign Static IP to Docker Container and Docker-Compose

« 上一篇: Docker 标签指南