Docker Compose 方式下的容器网络基础知识点

栏目: 服务器 · 发布时间: 5年前

内容简介:本周使用我在本地的机器上,一开始用 Compose 的方式创建了一个 MySQL 的容器了。然后在再利用另一份

Docker Compose 方式下的容器网络基础知识点

本周使用 Docker Compose 方式搭建了 sonarqube 的服务 ,并进行了总结。遇到的问题:

我在本地的机器上,一开始用 Compose 的方式创建了一个 MySQL 的容器了。然后在再利用另一份 docker-compose.yml 文件创建 sonarqube 容器时,尝试配置 MySQL 替代 sonarqube 默认采用的 H2 数据库。但是 sonarqube 却怎么也无法连接上 MySQL。

为了解决这个网络不通的问题,需要了解一下容器间网络通信的基础。

networks

关于 Compose 的网络,官网有专门的一节进行介绍。查看 Networking in Compose

By default Compose sets up a single network for your app. Each container for a service joins the default network and is both reachable by other containers on that network, and discoverable by them at a hostname identical to the container name.

Compose 默认给你的 app 设置一个网络。 service 中的每个容器默认都加入这个网络,容器之间彼此是互通的。并且,可以利用容器名字识别到。

Note: 你 app 的网络默认情况下是和你的 project name 有关的。这个 project name 其实就是你 docker-compose.yml 文件存放的那个目录的名字。比如,目录名叫 db ,那么默认情况下会创建一个叫 db_default 的网络。你可以使用 --project-nameCOMPSE_PROJECT_NAME 环境变量。

举个栗子, docker-compose.yml

version: "3"
services:
  web:
    build: .
    ports:
      - "8000:8000"
  db:
    image: postgres
    ports:
      - "8001:5432"

假设,上面这个文件放在 myapp 文件夹下。那么,当你 docker-compose up -d 之后:

  • 一个叫 myapp_default 网络被创建;
  • 一个使用 web 配置的容器会被创建,它以 web 的名字加入了 myapp_default 这个网络;
  • 一个使用 db 配置的容器会被创建,它以 db 的名字加入了 myapp_default 网络;
Each container can now look up the hostname web or db and get back the appropriate container’s IP address

现在,每个容器都可以查找主机名 webdb ,并获取相应容器的 IP 地址。例如, web 应用的代码可以使用 URL postgres://db:5432 连接数据库并使用它。

重要的是要注意 HOST_PORTCONTAINER_PORT 之间的区别。前者是指的是宿主机的端口,后者指的是容器中的端口。容器网络中的服务间使用的是 CONTAINER_PORT 通信。 HOST_PORT 定义了是为了容器网络外被调用的。所以,前面才使用的是 postgres://db:5432 而不是 postgres://db:8001 。因为他们属于同一个容器网络中。

在官网的 Compose file version 2 reference 一段中,也有相关网络介绍。

Networks to join, referencing entries under the top-level networks key.

这句话需要注意到, services 下级的服务中 networks 指定的网络不是指要创建的网络,而是这个服务要加入的网络。

所以说,这时候如果你指定了一个没有的网络,就会报错啦,类似这种:

ERROR: Service "mongodb" uses an undefined network "mogo_net"

需要定义才能加入。经过试验,我在 Compose 文件中,使用 top-level 的 networks 定义一下网络,运行时,会自动创建网络:

version: "2"
services:
    mongodb:
        image: mongo:4
        container_name: devops-mongo # 容器名
        ports:
            - "27017:27017"
        volumes:
            - "/data/docker_local/mongo/configdb:/data/configdb"
            - "/data/docker_local/mongo/data/db:/data/db"
        command: --auth # 开启授权验证
        networks:
            - mongo_net
networks:
  mongo_net:

Docker Compose 方式下的容器网络基础知识点

发现这时候没有报错了,但是它自动创建的网络好像也不叫 mong_net 而是根据规则,创建的 db_mongo_net 的网络。虽然不报错,但是我觉得有点别扭,查看了一下,可以利用 name 的标签定义一下网络。

version: "2.1"
services:
    mongodb:
        image: mongo:4
        container_name: devops-mongo # 容器名
        ports:
            - "27017:27017"
        volumes:
            - "/data/docker_local/mongo/configdb:/data/configdb"
            - "/data/docker_local/mongo/data/db:/data/db"
        command: --auth # 开启授权验证
        networks:
            - mongo_net
networks:
  mongo_net:
    name: mongo_net

这时候启动时,日志显示就比较符合预期了:

Docker Compose 方式下的容器网络基础知识点

「好奇心宝宝」附身,如果我 name 指定想要的值,上一层,有必要一致吗?

version: "2.1"
services:
    mongodb:
        image: mongo:4
        container_name: devops-mongo # 容器名
        ports:
            - "27017:27017"
        volumes:
            - "/data/docker_local/mongo/configdb:/data/configdb"
            - "/data/docker_local/mongo/data/db:/data/db"
        command: --auth # 开启授权验证
        networks:
            - mongo_net
networks:
  default:
    name: mongo_net

上面的这种改法会报错: ERROR: Service "mongodb" uses an undefined network "mongo_net" 。所以,顶层的 networks 下一层及的网络名称,要和服务中要加入的名称保持一致才行。这样一试,貌似对上面创建的 db_mongo_net 的网络而不报错的现象理解了。省略了 name , 那么 name 就按照默认规则创建网络了,其实就是类似于:

version: "2.1"
services:
    mongodb:
        image: mongo:4
        container_name: devops-mongo # 容器名
        ports:
            - "27017:27017"
        volumes:
            - "/data/docker_local/mongo/configdb:/data/configdb"
            - "/data/docker_local/mongo/data/db:/data/db"
        command: --auth # 开启授权验证
        networks:
            - mongo_net
networks:
  mongo_net:
    name: db_mongo_net

注意点:name 这个标签,这样的用法需要在 Compose 2.1 版本及以上才能使用

通过上面的对比,对 networks 有了初步了解了。那么,Compose 文件中式还不是一定要创建网络才行呢?可不可以利用已有的网络呢?后面的 external 会有介绍。

PS:通过 docker network ls/rm/create .. 等命令,可以查看或操作容器的网络。

links

Links allow you to define extra aliases by which a service is reachable from another service. They are not required to enable services to communicate - by default, any service can reach any other service at that service’s name. In the following example, db is reachable from web at the hostnames db and database:

通过链接,您可以给某个 service 定义别名,通过该别名可以从其他服务访问服务。默认情况下,任何服务都可以通过该服务的名称访问任何其他服务。下面的例子中, db 是一个服务名,在 web 服务中,给 db 定义了一个别名 database 。那么,在 web 服务中,既可以通过 db 又可以通过 databse 查找到主机名了。

version: "3"
services:

  web:
    build: .
    links:
      - "db:database"
  db:
    image: postgres

Specify custom networks

Instead of just using the default app network, you can specify your own networks with the top-level networks key. This lets you create more complex topologies and specify custom network drivers and options. You can also use it to connect services to externally-created networks which aren’t managed by Compose.

为了不使用默认的网络,你可以使用 compsose 文件的 top-level 关键字 networks 自定义网络。这让你可以创建更复杂的拓扑并指定自定义网络驱动程序和选项。 你还可以使用它将服务连接到不由 Compose 管理的外部创建的网络。

Here’s an example Compose file defining two custom networks. The proxy service is isolated from the db service, because they do not share a network in common - only app can talk to both.

这里有一个例子,自定义了两个网络。 proxy 服务和 db 服务是隔离的。因为它俩不共享一个网络,只有 app 服务能够和他俩都能通信。

version: "3"
services:

  proxy:
    build: ./proxy
    networks:
      - frontend
  app:
    build: ./app
    networks:
      - frontend
      - backend
  db:
    image: postgres
    networks:
      - backend

networks:
  frontend:
    # Use a custom driver
    driver: custom-driver-1
  backend:
    # Use a custom driver which takes special options
    driver: custom-driver-2
    driver_opts:
      foo: "1"
      bar: "2"

external

external: true 加上这行表示我这个服务用的网络是用外部的网络,不用自动创建。否则,会按照规则默认创建网络的,例如 db_defaultsonarqube_default 这些网络就是默认创建的。如果这个时候没有对应的外部网络,会弹出如下的提示:

Creating network "db_default" with the default driver
ERROR: Network mysql_net declared as external, but could not be found. Please create the network manually using `docker network create mysql_net` and try again.

Docker Compose 方式下的容器网络基础知识点

注意点:对于 compose 3.3 及更低版本,外部不能与其他网络配置键(driver,driver_opts,ipam,internal)一起使用。版本 3.4 及更高版本不再存在此限制。

external 标签 官网有详细介绍

Use a pre-existing network

如果你想要你的容器加入到一个已存在的网络中,使用 external 选项:

version: "3.7"

services:
  proxy:
    build: ./proxy
    networks:
      - outside
      - default
  app:
    build: ./app
    networks:
      - default

networks:
  outside:
    external: true

这时候不会去创建一个 [projectname]_outside 的网络, Compose 会去查找一个已存在的叫做 outside 的网络,并且将它和 proxy 服务相连。

参考


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Python Machine Learning

Python Machine Learning

Sebastian Raschka / Packt Publishing - ebooks Account / 2015-9 / USD 44.99

About This Book Leverage Python' s most powerful open-source libraries for deep learning, data wrangling, and data visualization Learn effective strategies and best practices to improve and opti......一起来看看 《Python Machine Learning》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换