1. 简介

在本篇中,我们将深入探讨如何在 docker-compose.yml 文件中为同一个服务配置不同的名称。我们会先回顾 Docker 网络的基础知识,然后构建一个包含自定义配置的 Docker Compose 文件,最后通过一个实际案例验证配置是否生效。

如果你正在搭建多个容器服务,并希望它们之间可以通过更灵活的名称互相访问,这篇内容将对你非常有帮助。

2. Docker 网络基础回顾

Docker Compose 默认会为你的服务创建一个内部网络(通常是 bridge 类型),每个容器在这个网络中拥有自己的 IP 地址、网关、路由表以及 DNS 配置。

默认情况下,Docker 会将服务名自动注册为该容器的主机名(hostname),并将其添加到 Docker 内部的 DNS 服务中。这意味着其他容器可以通过服务名来访问该容器。

举个例子:

services:
  web:
    image: nginx

其他容器可以通过 http://web 来访问这个服务。

⚠️ 但要注意的是,容器内的 localhost 指向的是容器本身,而不是宿主机。所以在多个容器之间通信时,不能依赖 localhost 来访问其他服务。

3. 自定义容器的主机名

虽然服务名可以作为默认的主机名,但我们也可以通过 hostname 显式指定:

services:
  app:
    image: my-app
    hostname: myapp-host

这样,容器内部和同一网络中的其他容器都可以通过 myapp-host 来访问它。

⚠️ 注意:hostname 不会影响容器的名称(即 container_name),后者需要单独配置。

4. 为容器设置别名(Alias)

除了自定义主机名,我们还可以通过设置别名来让服务被其他容器用不同的名字访问。

别名是通过在 networks 中定义的,格式如下:

services:
  mock_api:
    image: kennethreitz/httpbin
    networks:
      custom_network:
        aliases:
          - prod_api

✅ 这样,其他容器就可以通过 prod_api 来访问这个服务。

别名的作用域是在网络级别的,也就是说:

  • 同一个服务可以在不同网络中使用不同的别名
  • 同一个服务可以在同一个网络中拥有多个别名

自定义网络配置

要使用别名,我们还需要先定义一个自定义网络:

networks:
  custom_network:
    driver: bridge

Docker 支持多种网络驱动,常见如下:

Driver 说明
bridge 默认网络驱动,适合大多数容器通信场景
host 容器与主机共享网络栈,无网络隔离
none 容器无网络连接
overlay 用于跨多个 Docker 主机通信
ipvlan 可精细控制 IPv4/IPv6 地址分配
macvlan 为容器分配 MAC 地址,使其看起来像物理设备

5. 实战验证配置

为了更直观地演示,我们构建一个包含三个服务的 Docker Compose 文件:

  • mock_db:使用 Redis 镜像,设置主机名为 prod_db
  • mock_api:使用 httpbin 镜像,设置别名为 prod_api
  • mock_nginx:使用 Nginx 镜像,设置容器名为 prod_nginx

所有服务都连接到一个名为 custom_network 的自定义桥接网络。

version: '3.8'

services:
  mock_db:
    image: redis
    hostname: prod_db
    networks:
      - custom_network

  mock_api:
    image: kennethreitz/httpbin
    networks:
      custom_network:
        aliases:
          - prod_api

  mock_nginx:
    image: nginx:latest
    container_name: prod_nginx
    networks:
      - custom_network

networks:
  custom_network:
    driver: bridge

启动服务

$ docker-compose up -d

输出如下:

[+] Running 3/3
 ✔ Container alias-mock_db-1   Started                                                               0.0s 
 ✔ Container alias-mock_api-1  Started                                                               0.0s 
 ✔ Container prod_nginx        Started                                                               0.0s

查看容器状态

$ docker ps

输出如下:

CONTAINER ID   IMAGE                  COMMAND                  CREATED              STATUS              PORTS                               NAMES
ae860f1b9764   kennethreitz/httpbin   "gunicorn -b 0.0.0.0…"   About a minute ago   Up About a minute   80/tcp                              alias-mock_api-1
63cdc9e7f086   nginx:latest           "/docker-entrypoint.…"   About a minute ago   Up About a minute   0.0.0.0:80->80/tcp, :::80->80/tcp   prod_nginx
d28b8b141c9f   redis                  "docker-entrypoint.s…"   About a minute ago   Up About a minute   6379/tcp                            alias-mock_db-1

可以看到,mock_nginx 的容器名确实为 prod_nginx,而其他服务使用默认命名规则。

测试通信

进入 prod_nginx 容器并尝试 ping 其他服务:

$ docker exec -it prod_nginx ping prod_db
PING prod_db (172.23.0.2) 56(84) bytes of data.
64 bytes from alias-mock_db-1.alias_custom_network (172.23.0.2): icmp_seq=1 ttl=64 time=0.364 ms
...

也可以使用服务名访问:

$ docker exec -it prod_nginx ping mock_db
PING mock_db (172.23.0.2) 56(84) bytes of data.
64 bytes from alias-mock_db-1.alias_custom_network (172.23.0.2): icmp_seq=1 ttl=64 time=0.182 ms
...

对于 API 服务,我们也可以通过别名访问:

$ docker exec -it prod_nginx ping prod_api
PING prod_api (172.23.0.3) 56(84) bytes of data.
64 bytes from alias-mock_api-1.alias_custom_network (172.23.0.3): icmp_seq=1 ttl=64 time=0.129 ms
...

或者使用服务名:

$ docker exec -it prod_nginx ping mock_api
PING mock_api (172.23.0.3) 56(84) bytes of data.
64 bytes from alias-mock_api-1.alias_custom_network (172.23.0.3): icmp_seq=1 ttl=64 time=0.085 ms
...

✅ 结果表明:在自定义网络中,服务可以通过服务名、主机名或别名进行访问,非常灵活。

6. 小结

通过本文我们掌握了以下内容:

  • Docker 默认会将服务名作为主机名并注册到内部 DNS
  • 可通过 hostname 显式指定容器的主机名
  • 使用 networksaliases 可为服务设置别名,方便其他容器访问
  • 别名是网络级别的,不同网络中可以不同
  • 容器间通信时,可以使用服务名、主机名或别名互换使用

这种机制非常适合用于模拟生产环境的命名结构,避免在应用中硬编码 URL,从而提升开发与测试的灵活性。


原始标题:Container Hostnames and DNS with Docker Compose