Docker Compose 方式下容器网络

浪尽此生 提交于 2019-12-27 18:21:57

#Docker Compose 方式下容器网络

##背景

我们项目使用docker compose 部署服务,之前后端服务访问数据库都是通过数据库服务映射到主机的特定端口来访问。近期出于安全方面的考虑的,我们需要让后端服务和数据库通信走容器内部网络。

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

networks

container name

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

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

举个栗子,docker-compose.yml

 version: "2.1"
 services:
   web:
     image: nginx
     ports:
       - "8080:80"
   busybox:
     image: busybox
     entrypoint:
      - top

这个文件放在project目录下当我们执行了 docker-compose up -d 之后:

  • 一个叫project_default 的网络将会被创建。
  • web 和 busybox 容器将会被创建,并加入project_default 网络中
project $ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
f17520060e9d        bridge              bridge              local
a3028588ea24        host                host                local
d5f0e66b912f        none                null                local
5ecd6959d2a3        project_default    bridge              local

现在project_default 网络中的web 和 busybox 就可以通过container_name相互访问。例如,busybox 可以使用 web:80 访问web应用。

links

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

version: "3"
services:

  busybox:
    build: busybox
    links:
      - "web:nginx"
  web:
    image: nginx

Links are a legacy option. We recommend using networks instead.

###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.

Each service can specify what networks to connect to with the service-level networks key, which is a list of names referencing entries under the top-level networks key.

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

来个栗子:我们使用project_1和project_2目录中的compose文件,分别创建了两个服务。并使用top-level关键字networks定义了自定义网络custom_network

project_1 $ cat docker-compose.yml
version: "2.1"
services:
  web:
    image: nginx
    networks:
        - custom_network //添加到特定网络
networks:
  custom_network:
    name: custom_network

project_2 $ cat docker-compose.yml
version: "2.1"
services:
  busybox:
    image: busybox
    entrypoint:
     - top
    networks:
        - custom_network
networks:
  custom_network:
    name: custom_network

注意点:在 top-level关键字networks中, name 这个标签,需要在 Compose 2.1 版本及以上才能使用

我们来分别创建服务和网络,在创建project_2目录中的服务时,我们可以看到如果添加的网络已经存在,就不会再创建。

project_1 $ docker-compose up -d
Creating network "custom_network" with the default driver
Creating web ... done
project_1 $ cd ../project_2/
project_2 $ docker-compose up -d
Creating busybox ... done

我们来看结果:

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
8abdef4cc1ba        busybox             "top"                    17 minutes ago      Up 17 minutes                           busybox
40bb2e637286        nginx               "nginx -g 'daemon of…"   18 minutes ago      Up 18 minutes       80/tcp              web

$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
f17520060e9d        bridge              bridge              local
//刚创建的网络,如果查看网络的详细信息就会发现两个服务已经被添加进custom_network
f26744e467d4        custom_network      bridge              local 
a3028588ea24        host                host                local
d5f0e66b912f        none                null                local

external

external: true 加上这行表示我这个服务用的网络是用外部的网络,不用自动创建。docker-compose up不会创建该网络,如果不存在,则会引发错误。

举个栗子:

app1 $ cat docker-compose.yaml
version: "3.7"
services:
  web:
    image: nginx
    networks:
      - outside
      - default
  db:
    image: postgres
    networks:
      - default
networks:
  outside:
    external: true

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

因为我们没有创建outside网络,所以在启动的时候就出现了报错。

app1 $ docker-compose up -d
ERROR: Network outside declared as external, but could not be found. Please create the network manually using `docker network create outside` and try again.

下面我们来创建outside网络,并重新启动它

app1 $ docker network create outside
3ce8ad24edfcccb6f39c2feb7f849f3cb560f145af60f839c02e21db82bc6b47
app1 $ docker-compose up -d
Creating network "app1_default" with the default driver
Creating app1_web_1 ... done
Creating app1_db_1  ... done

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

##小结

我们可以看到容器间网络通信我们可以通过4种方法来实现:

  1. container name

  2. links

  3. Specify custom networks

  4. external

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!