简体   繁体   English

了解Docker网络隔离

[英]Understanding Docker network isolation

I have created the following docker-compose file... 我创建了以下docker-compose文件...

version: '3'

services:
  db-service:
    image: postgres:11
    volumes:
      - ./db:/var/lib/postgresql/data
    expose: 
      - 5432
    environment:
      - POSTGRES_PASSWORD=mypgpassword
    networks:
      - net1
  pgadmin:
    image: dpage/pgadmin4
    volumes:
      - ./pgadmin:/var/lib/pgadmin
    ports:
      - 5000:80
    environment:
      - PGADMIN_DEFAULT_EMAIL=me@gmail.com
      - PGADMIN_DEFAULT_PASSWORD=mypass
    networks:
      - net1
networks:
  net1:
    external: false

From reading various docs on the docker site, my expectation was that the pgadmin container would be able to access the postgres container via port 5432 but that I should not be able to access postgres directly from the host. 通过阅读Docker站点上的各种文档,我期望pgadmin容器能够通过端口5432访问postgres容器,但是我不应该能够直接从主机访问postgres。 However, I am able to use psql to access the database from the host machine. 但是,我可以使用psql从主机访问数据库。

In fact, if I comment out the expose and ports lines I can still access both containers from the host. 实际上,如果我注释掉暴露和端口行,我仍然可以从主机访问两个容器。

What am I missing about this? 我为此而想念什么?

EDIT - I am accessing the container by first running docker container inspect... to get the IP address. 编辑-我正在通过首先运行docker container inspect...访问容器以获取IP地址。 For the postgres container I'm using 对于我正在使用的postgres容器

psql -h xxx.xxx.xxx.xxx -U postgres

It prompts me for the password and then allows me to do all the normal things you would expect. 它提示我输入密码,然后让我执行您期望的所有正常操作。

In the case of the pgadmin container I point my browser to the IP address and get the pgadmin interface. 对于pgadmin容器,我将浏览器指向IP地址并获得pgadmin界面。

Note that both of those are being executed from a terminal on the host, not from within either container. 请注意,这两者都是从主机上的终端执行的,而不是从任何一个容器中执行的。 I've also commented out the expose command and can still access the postgres db. 我也注释掉了暴露命令,并且仍然可以访问postgres数据库。

docker-compose creates a network for those two containers to be able talk to each-other when you run it, through a DNS service which will contain pointers to each service, by name. docker-compose为这两个容器创建了一个网络,以便您在运行该容器时可以通过DNS服务相互通信,该DNS服务将按名称包含指向每个服务的指针。

So from the perspective of the pgadmin container, the dbserver can be reached under hostname db-service (because that is what you named your service in the docker-compose.yml file). 因此,从pgadmin容器的角度来看,可以在主机名db-service下访问dbserver(因为这是您在docker-compose.yml文件中命名的服务)。

So, that traffic does not go through the host, as you were assuming, but through the aforementioned network. 因此,该流量不会像您假设的那样通过主机,而是通过上述网络。

For proof, docker exec -it [name-of-pg-admin-container] /bin/sh and type: ping db-service . 为了证明这一点,请使用docker exec -it [name-of-pg-admin-container] /bin/sh并键入: ping db-service You will see that docker provides a DNS resolution and that you can even open a connection to the normal postgres port there. 您将看到docker提供了DNS解析,您甚至可以在其中打开与普通postgres端口的连接。

Docker assigns an internal IP address to each container. Docker为每个容器分配一个内部IP地址。 If you happen to have this address, and it happens to be reachable, then Docker doesn't do anything specific to firewall it off. 如果您碰巧有这个地址,而且碰巧可以访问,那么Doc​​ker不会做任何专门针对它的防火墙。 On a Linux host in particular, if specific Docker network is on 172.17.0.0/24, the host might have a 172.17.0.1 address and a specific container might be 172.17.0.2, and they can talk to each other this way. 特别是在Linux主机上,如果特定的Docker网络位于172.17.0.0/24上,则该主机可能具有172.17.0.1地址,并且特定的容器可能是172.17.0.2,并且它们可以通过这种方式相互通信。

Using the Docker-internal IP addresses is not a best practice. 使用Docker内部IP地址不是最佳实践。 If you ever delete and recreate a container, its IP address will change; 如果删除并重新创建容器,则其IP地址将更改; on some host platforms you can't directly access the private IP addresses even from the same host; 在某些主机平台上,即使从同一主机也不能直接访问专用IP地址; the private IP addresses are never reachable from other hosts. 专用IP地址永远无法从其他主机访问。 In routine use you should never need to docker inspect a container. 在日常使用中,您永远不需要docker inspect容器。

The important level of isolation you do get here is that the container isn't accessible from other hosts unless you explicitly publish a port ( docker run -p option, Docker Compose ports: option). 您获得的重要隔离级别是,除非您明确发布端口( docker run -p选项,Docker Compose ports:选项),否则其他主机无法访问该容器。 The setup here is much more uniform than for standard applications: set up the application inside the container to listen on 0.0.0.0 (“all host interfaces”, usually the default), and then publish a port or not as your needs require. 与标准应用程序相比,这里的设置更加统一:在容器内设置应用程序以侦听0.0.0.0(“所有主机接口”,通常是默认值),然后根据需要发布或不发布端口。 If the host has multiple interfaces you can publish a port on only one of them (even if the application doesn't natively support that). 如果主机有多个接口,则只能在其中一个接口上发布端口(即使应用程序本身不支持该端口)。

The containers connect one with another by bridge network net1. 容器通过网桥网络net1相互连接。

When you expose port, you create port forwarding in your IPTABLES for connecting host network and net1. 公开端口时,可以在IPTABLES中创建端口转发以连接主机网络和net1。

Stop expose 5432 port in your db-service and you see that you can't connect from your host to db-service. 停止在db-service中公开5432端口,您会看到无法从主机连接到db-service。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM