原创

Docker之容器的网络通信-单机版

在Docker中,容器之间的链接是一种很常见的操作:它提供了访问其中的某个容器的网络服务而不需要将所需的端口暴露给Docker Host主机的功能。本篇文章主要针对的是在同一台宿主🐔的情况下若何进行网络的通信,至于跨主机的容器通信,不做过多讲解。
在通过Docker部署Kafka时,由于需要使用Zookeeper,而在之前本地已经使用docker run构建了zookeeper服务并且已经能够使用,接下来我们来研究一下如何使他们进行网络通信。Kafka这里使用的时Docker Compose方式构建,而Docker Compose中对该特性的支持是很方便的。然而,如果需要链接的容器没有定义在同一个docker-compose.yml中的时候,这个时候就稍微麻烦复杂了点。

不使用Docker Compose时的通信方式

在不使用Docker Compose时,可以通过docker自身提供的--link参数进行连接,以nginx镜像为例:

$ docker run --rm --name test1 -d nginx  #开启一个实例test1
$ docker run --rm --name test2 --link test1 -d nginx #开启一个实例test2并与test1建立链接

此时链接建立,test2test1可以通过使用容器名的方式进行访问。不过问题是该方式只能在同一台宿主🐔上进行通信。在docker官方文档中已经不在推荐使用

使用自定义网桥

如果在默认网桥网络上运行相同的应用程序堆栈,需要在容器之间手动创建链接(使用旧的--link标志)。这些链接需要在两个方向上创建,因此可以看到,需要通信的两个以上的容器使这变得复杂。或者,可以操作容器中的/etc/hosts文件,但这会产生难以调试的问题。

管理自定义网桥

使用docker network create即可以创建自定义网桥,如果不同的应用程序组具有不同的网络需求,则可以在创建时分别配置每个用户定义的网桥。

$ docker network create docker-net

在创建过程时可以指定子网、ip范围、网关和其他。参看具体命令docker network create --help

注意:移除自定义网桥,移除前先将连接到当前网桥的容器取消连接。

$ docker network rm docker-net

连接容器到自定义网桥

在创建容器时可以使用--network进行创建

$ docker create \
    --name my-nginx \
  --network docker-net \
  --publish 8080:80 \
  nginx:latest

若当前容器已在运行,可以使用docker network connect连接到自定义的网桥,例如当前zookeeper容器已经存在,那么就可以使用以下方式。

$ docker network connect docker-net zoo-docker

容器互联

此时再将kafka连接到docker上即可,KAFKA_ZOOKEEPER_CONNECT配置可以直接指定zookeeper容器名。

$ docker run --name kafka-docker \
    -p 9092:9092 \
    -e KAFKA_ADVERTISED_HOST_NAME=localhost \
    --network docker-net \
    -e KAFKA_ZOOKEEPER_CONNECT=zoo-docker:2181 \
    -d  wurstmeister/kafka

使用Docker Compose时的通信方式

使用Docker Compose管理容器时同样可以使用自定义网桥的方式,进行容器间的通信,不过分为以下几种情况的通信。

当前容器同属于一个docker-compose.yml

若两个容器同属于一个文件时,不用其他的操作即可进行通信。

version: '2'
services:
    zookeeper:
    image: wurstmeister/zookeeper
    volumes:
      - $PWD/data:/data
    ports:
      - "2181:2181"
  kafka:
    image: wurstmeister/kafka
    ports:
      - "9092:9092"
    environment:
      KAFKA_ADVERTISED_HOST_NAME: 127.0.0.1
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
    volumes:
      - $PWD/data:/kafka
      - /var/run/docker.sock:/var/run/docker.sock
  kafka-manager:
    image: sheepkiller/kafka-manager
    ports:
      - 9000:9000
    environment:
      ZK_HOSTS: zookeeper:2181
    volumes:
      - $PWD/data:/kafka

注意:这里在kafka的environment配置种我们直接使用了zookeeper容器名。

容器不属于同一个docker-compose.yml

若像我前文中提到的我的zookeeper容器已经在运行了,不想在docker-compose.yml种再次使用时,那么就可以借助前面讲到的自定义网桥

此时假设我的网桥已经使用docker network create创建好了,并且zookeeper容器已经使用了docker network connect docker-net进行了连接。
那么docker-compose的配置参考以下例子。

version: '2'
services:
  kafka:
    image: wurstmeister/kafka
    ports:
      - "9092:9092"
    environment:
      KAFKA_ADVERTISED_HOST_NAME: 127.0.0.1
      KAFKA_ZOOKEEPER_CONNECT: zoo-docker:2181
    volumes:
      - $PWD/data:/kafka
      - /var/run/docker.sock:/var/run/docker.sock
    networks:
      - default
      - docker_net
  kafka-manager:
    image: sheepkiller/kafka-manager
    ports:
      - 9000:9000
    environment:
      ZK_HOSTS: zoo-docker:2181
    volumes:
      - $PWD/data:/kafka
    networks:
      - default
      - docker_net
networks:
  docker_net:
    external: true

注意⚠️:不同于上边的配置新增了

networks:
  docker_net:
    external: true

以及每个容器的网路配置

networks:
    - default
    - docker_net

至此参考以上配置,这样你的每个容器间即可互相的通信,这里主要介绍的官方文档中提到的bridge networks网络模式,同时文档中还介绍了overlay networks``host networking macvlan networks等,后面在了解~。

关于跨主机的容器通信方案有很多种。

  • 利用k8s
  • 利用Weave
  • 利用Swarm
  • 利用Overlay network
  • 将多个物理机的容器组到一个物理网络来
    1. 创建自己的网桥br0
    2. 将docker默认网桥绑定到br0
  • 修改主机docker默认的虚拟网段,然后在各自主机上分别把对方的docker网段加入到路由表中,配合iptables即可实现docker容器跨主机通信

参考

docker官方文档
Docker Compose:链接外部容器的几种方式

sev7e0
Write by sev7e0
end
本文目录