• Docker笔记-06 网络管理


    在实践中,经常会碰到需要多个服务组件容器共同协作的情况,这往往需要多个容器之间能够互相访问到对方的服务。本章主要介绍端口映射和互联的知识

    Docker除了通过网络访间外, 还提供了两个很方便的功能来满足服务访问的基本需求:

    • 一个是允许映射容器内应用的服务端口到本地宿主主机;
    • 另一个是互联机制实现多个容器间通过容器名来快速访问;

    1 端口映射实现访问容器

    1.1 从外部访问容器的应用

    在启动容器的时候,如果不指定对应参数,在容器外部是无法通过网络来访问容器内的网络应用和服务的。

    当容器中运行一些网络应用,要让外部访问这些应用时,可以通过-P-p参数来指定端口映射。

    1.1.1 -P参数

    当使用-P标记时,Docker会随机映射一个49000~49900的端口至容器内部开放的网络端口。如:

    (base) pang@pang-HP:~$ sudo docker run -d -P --name nginx nginx:alpine
    dec994c1daa5da850e6147ca2d9283739e8644c2d0b624c88fded1b806075b02
    (base) pang@pang-HP:~$ sudo docker ps -l
    CONTAINER ID   IMAGE          COMMAND                  CREATED         STATUS         PORTS                                     NAMES
    dec994c1daa5   nginx:alpine   "/docker-entrypoint.…"   4 seconds ago   Up 4 seconds   0.0.0.0:49153->80/tcp, :::49153->80/tcp   nginx
    (base) pang@pang-HP:~$ 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    可以看到,本地主机的49153被映射到了容器的80端口。访问宿主主机的49153端口即可访问容器内Web应用提供的界面。例如:访问http://127.0.0.1:49153/,可以打开nginx页面

    在这里插入图片描述

    同样的,可以通过docker logs命令来查看访问记录。

    (base) pang@pang-HP:~$ sudo docker logs nginx
    /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
    /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
    /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
    10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
    10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
    /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
    /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
    /docker-entrypoint.sh: Configuration complete; ready for start up
    2022/06/23 00:45:06 [notice] 1#1: using the "epoll" event method
    2022/06/23 00:45:06 [notice] 1#1: nginx/1.23.0
    2022/06/23 00:45:06 [notice] 1#1: built by gcc 11.2.1 20220219 (Alpine 11.2.1_git20220219) 
    2022/06/23 00:45:06 [notice] 1#1: OS: Linux 5.13.0-44-generic
    2022/06/23 00:45:06 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
    2022/06/23 00:45:06 [notice] 1#1: start worker processes
    2022/06/23 00:45:06 [notice] 1#1: start worker process 32
    2022/06/23 00:45:06 [notice] 1#1: start worker process 33
    2022/06/23 00:45:06 [notice] 1#1: start worker process 34
    2022/06/23 00:45:06 [notice] 1#1: start worker process 35
    2022/06/23 00:45:06 [notice] 1#1: start worker process 36
    2022/06/23 00:45:06 [notice] 1#1: start worker process 37
    2022/06/23 00:45:06 [notice] 1#1: start worker process 38
    2022/06/23 00:45:06 [notice] 1#1: start worker process 39
    2022/06/23 00:45:06 [notice] 1#1: start worker process 40
    2022/06/23 00:45:06 [notice] 1#1: start worker process 41
    2022/06/23 00:45:06 [notice] 1#1: start worker process 42
    2022/06/23 00:45:06 [notice] 1#1: start worker process 43
    2022/06/23 00:45:06 [notice] 1#1: start worker process 44
    2022/06/23 00:45:06 [notice] 1#1: start worker process 45
    2022/06/23 00:45:06 [notice] 1#1: start worker process 46
    2022/06/23 00:45:06 [notice] 1#1: start worker process 47
    172.17.0.1 - - [23/Jun/2022:00:47:08 +0000] "GET / HTTP/1.1" 200 615 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36" "-"
    172.17.0.1 - - [23/Jun/2022:00:47:08 +0000] "GET /favicon.ico HTTP/1.1" 404 555 "http://127.0.0.1:49153/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36" "-"
    2022/06/23 00:47:08 [error] 32#32: *1 open() "/usr/share/nginx/html/favicon.ico" failed (2: No such file or directory), client: 172.17.0.1, server: localhost, request: "GET /favicon.ico HTTP/1.1", host: "127.0.0.1:49153", referrer: "http://127.0.0.1:49153/"
    (base) pang@pang-HP:~$ 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    1.1.2 -p参数

    -p则可以指定要映射的端口,并且在一个指定端口上只可以绑定一个容器。支持的格式有:

    • ip:hostPort:containerPort
    • ip::containerPort
    • hostPort:containerPort

    1.1.2.1 映射所有接口地址

    使用hostPort:containerPort格式将本地的5000端口映射到容器的5000端口。如:

    (base) pang@pang-HP:~$ sudo docker run -d -p 80:80 --name nginx nginx:alpine
    668a2880fb9d1a7f533ec7f8b6ead2116265f9e501599c7342288244ca66dc13
    (base) pang@pang-HP:~$ 
    
    • 1
    • 2
    • 3

    此时会默认绑定本地所有接口上的所有地址。使用127.0.0.1:8010.30.185.122:80等地址均可以访问到nginx页面(注:这两个地址均为host主机的ip)。

    另外,多次使用-p标记可以绑定多个端口。如:

    sudo docker run -d -p 5000:5000 -p 3000:80 training/webapp python app.py
    
    • 1

    1.1.2.2 映射到指定地址的指定端口

    使用ip:hostPort:containerPort格式自动映射使用一个特定地址,比如localhost地址127.0.0.1:

    (base) pang@pang-HP:~$ sudo docker run -d -p 127.0.0.1:80:80 --name nginx nginx:alpine
    97433c963393aaf8316c4a4641d87ace1b4617c7349ddf896ae63a7a9b911a4f
    (base) pang@pang-HP:~$ 
    
    • 1
    • 2
    • 3

    此时只有使用127.0.0.1:80才能访问到nginx页面

    1.1.2.3 映射到指定地址的任意端口

    使用ip::containerPort绑定localhost的任意端口到容器的80端口,本地主机会自动分配一个端口:

    (base) pang@pang-HP:~$ sudo docker run -d -p 127.0.0.1::80 --name nginx nginx:alpine
    649e5327d550556c58cab3b5d133fb6f5203798452a58cd4fda1e71453728ce5
    (base) pang@pang-HP:~$ sudo docker ps -l
    CONTAINER ID   IMAGE          COMMAND                  CREATED         STATUS         PORTS                     NAMES
    649e5327d550   nginx:alpine   "/docker-entrypoint.…"   4 seconds ago   Up 3 seconds   127.0.0.1:49153->80/tcp   nginx
    (base) pang@pang-HP:~$ 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    还可以使用udp标记来指定udp端口:

    sudo docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py
    
    • 1

    1.1.3 查看映射端口配置

    使用docker port可以查看当前映射的端口配置,也可以查看到绑定的地址:

    (base) pang@pang-HP:~$ sudo docker port nginx
    80/tcp -> 127.0.0.1:49153
    (base) pang@pang-HP:~$ sudo docker port nginx 80
    127.0.0.1:49153
    (base) pang@pang-HP:~$
    
    • 1
    • 2
    • 3
    • 4
    • 5

    容器有自己的内部网络和IP地址,使用docker inspect+容器ID可以获取容器的具体信息(其中就包括网络信息等)。

    (base) pang@pang-HP:~$ sudo docker inspect nginx
    ...
                "Ports": {
                    "80/tcp": [
                        {
                            "HostIp": "127.0.0.1",
                            "HostPort": "49153"
                        }
                    ]
                },
    ...
                "Gateway": "172.17.0.1",
    ...
                "IPAddress": "172.17.0.3",
                "IPPrefixLen": 16,
                "IPv6Gateway": "",
                "MacAddress": "02:42:ac:11:00:03",
                "Networks": {
                    "bridge": {
                        "IPAMConfig": null,
                        "Links": null,
                        "Aliases": null,
                        "NetworkID": "ecb0e73ea7ad1f27cabb0946d73e3114ee620517bc36976e2f23b0affe49f27e",
                        "EndpointID": "8a5588841fca30da460ea6b2f1c16916647130d729819e6a0f48fb15e84349c7",
                        "Gateway": "172.17.0.1",
                        "IPAddress": "172.17.0.3",
                        "IPPrefixLen": 16,
                        "IPv6Gateway": "",
                        "GlobalIPv6Address": "",
                        "GlobalIPv6PrefixLen": 0,
                        "MacAddress": "02:42:ac:11:00:03",
                        "DriverOpts": null
                    }
                }
            }
        }
    ]
    (base) pang@pang-HP:~$ 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    2 互联机制实现便捷互访

    容器的互联(linking)是一种让多个容器中的应用进行快速交互的方式。它会在源和接收容器之间创建一个隧道,接收容器可以看到源容器指定的信息,而不用指定具体的IP地址。

    2.1 自定义容器命名

    连接系统依据容器的名称来执行。因此,首先需要自定义一个好记的容器命名,一般当创建容器的时候,系统默认会分配一个名字,但自定义名称容器有比较多的好处:

    • 自定义的命名,比较好记,比如一个Web应用容器我们可以给它起名叫web, 一目了然;
    • 当要连接其他容器时候(即便重启),也可以使用容器名而不用改变,比如连接web容器到db容器。

    使用--name标记可以为容器自定义名称:

    sudo docker run -d -P --name web training/webapp python app.py
    
    • 1

    使用docker ps来验证设定的命名:

    sudo docker ps -l
    
    • 1

    也可以使用docker inspect来查看容器的名字:

    sudo docker inspect -f "{{ .Name}}" xxxxxxxx (CONTAINER_ID)
    
    • 1

    容器的名称是唯一的,如果已经命名了一个叫web的容器,当你要再次使用web这个名称的时候,需要先用docker rm 来删除之前创建的同名容器。

    在执行docker [container] run的时候如果添加--rm标记,则容器在终止后会立刻删除。注意,--rm-d参数不能同时使用。

    2.2 容器互联

    2.2.1 使用–link参数

    使用--link参数可以让容器之间安全的进行交互。其命令格式为:

    --link name:alias
    
    • 1

    其中name是要链接的容器的名称,alias是这个链接的别名。如:

    1. 创建一个新的数据库容器:
    sudo docker run -d --name db training/postgres
    
    • 1
    1. 删除之前创建的web容器:
    sudo docker rm -f web
    
    • 1
    1. 创建一个新的web容器,并将它连接到db容器:
    sudo docker run -d -P --name web --link db:db training/webapp python app.py
    
    • 1

    此时,db容器和web容器建立互联关系。Docker在两个互联的容器之间创建了一个安全隧道,而且不用映射它们的端口到宿主主机上。在启动db容器的时候并没有使用-p和-P标记,从而避免了暴露数据库端口到外部网络上。

    Docker通过两种方式为容器公开连接信息:

    1. 配置容器的环境变量
    2. 更新容器的/etc/hosts文件

    使用env命令来查看web容器的环境变量:

    sudo docker run --rm --name web2 --link db:db training/webapp env
    ...
    DB_NAME;/web2/db 
    DB_PORT=cp://172.17.0.5:5432
    DB_PORT_5000_TCP=cp://172.17.0.5:5432
    DB_PORT_5000_TCP_PROTO=tcp 
    DB_PORT_5000_TCP_PORT=5432 
    DB_PORT_5000_TCP_ADDR=172.17.0.5
    ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    其中DB—开头的环境变量是供web容器连接db容器使用, 前缀采用大写的连接别名。

    除了环境变量,Docker还添加host信息到父容器的/etc/hosts的文件。 下面是父容器web的hosts文件:

    $ docker run -t -i --rm --link db:db training/webapp /bin/bash 
    root@aed84ee2lbde:/opt/webapp# cat /etc/hosts
    172.17.0.7 aed84ee2lbde
    ...
    172.17.0.5 db
    
    • 1
    • 2
    • 3
    • 4
    • 5

    这里有2个hosts信息,第一个是web容器,web容器用自己的id作为默认主机名,第二个是db容器的IP和主机名。

    可以在web容器中安装ping命令来测试跟db容器的连通:

    roo七@aed84ee2lbde:/opt/webapp# apt-get install -yqq inetutils-ping
    root@aed84ee2lbde:/opt/webapp# ping db 
    PING db (172.17.0.5): 48 data bytes 
    56 bytes from 172.17.0.5: icmp_seq=O ttl=64 time=0.267 ms 
    56 bytes from 172.17.0.5: icmp_seq=l ttl=64 time=0.250 ms 
    56 bytes from 172.17.0.5: icmp_seq=2 ttl=64 time=0.256 ms
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2.2.2 使用Docker网络实现互联

    随着Docker网络的完善,强烈建议大家将容器加入自定义的Docker网络来连接多个容器,而不是使用--link参数。

    2.2.2.1 新建网络

    下面先创建一个新的Docker网络。

    (base) pang@pang-HP:~$ sudo docker network create -d bridge my-net
    b04b7f0a305b1fa7440f1f865896af92632437fbdce9f7100cb6255656430d82
    (base) pang@pang-HP:~$ 
    
    • 1
    • 2
    • 3

    -d参数指定Docker网络类型,有bridge,overlay。其中overlay网络类型用于Swarm mode。

    2.2.2.2 连接容器

    运行两个容器并连接到新建的my-net网络

    (base) pang@pang-HP:~$ sudo docker run -d --name nginx1 --network my-net nginx:alpine
    8057bad85bda3852e7a220c8e3680dd1674db5546f40da0e825bc6aa0f7c4361
    (base) pang@pang-HP:~$ sudo docker run -d --name nginx2 --network my-net nginx:alpine
    399b0c6cd16ba517d1ce3b44c8563212d13827b01f66906f6c776c4f74bd0e0f
    (base) pang@pang-HP:~$ 
    
    • 1
    • 2
    • 3
    • 4
    • 5

    再打开一个新的终端查看容器信息

    (base) pang@pang-HP:~$ sudo docker container ls
    CONTAINER ID   IMAGE             COMMAND                  CREATED          STATUS          PORTS                                                                                  NAMES
    399b0c6cd16b   nginx:alpine      "/docker-entrypoint.…"   26 seconds ago   Up 25 seconds   80/tcp                                                                                 nginx2
    8057bad85bda   nginx:alpine      "/docker-entrypoint.…"   30 seconds ago   Up 29 seconds   80/tcp                                                                                 nginx1
    c7988f164f61   nginx:alpine      "/docker-entrypoint.…"   2 hours ago      Up 2 hours      0.0.0.0:80->80/tcp, :::80->80/tcp                                                      nginx
    9a102684ab20   sonatype/nexus3   "sh -c ${SONATYPE_DI…"   3 days ago       Up 6 hours      0.0.0.0:5000->5000/tcp, :::5000->5000/tcp, 0.0.0.0:8081->8081/tcp, :::8081->8081/tcp   nexus3
    (base) pang@pang-HP:~$ 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    进入nginx1容器中,然后ping nginx2检查网络连通性

    (base) pang@pang-HP:~$ sudo docker exec -it nginx1 /bin/sh
    / # ping nginx2
    PING nginx2 (172.18.0.3): 56 data bytes
    64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.130 ms
    64 bytes from 172.18.0.3: seq=1 ttl=64 time=0.115 ms
    64 bytes from 172.18.0.3: seq=2 ttl=64 time=0.130 ms
    64 bytes from 172.18.0.3: seq=3 ttl=64 time=0.070 ms
    ^Z[1]+  Stopped                    ping nginx2
    / # ^C
    / # exit
    (base) pang@pang-HP:~$ 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    这样,nginx1容器和nginx2容器建立了互联关系。

    2.2.2.3 Docker Compose

    如果你有多个容器之间需要互相连接,推荐使用Docker Compose

  • 相关阅读:
    代码随想录 单调栈part2
    Friedman检验和Nemenyi检验画图代码
    有趣的 Streamlit
    OpenFeign的学习总结
    Java项目:SSM在线蛋糕商城销售网站项目
    APT和Javapoet的精彩联动
    Netty 入门
    10大python加速技巧
    国内外开源数据可视化工具对比:DataEase相较于MetaBase有何优势
    北大肖臻老师《区块链技术与应用》系列课程学习笔记[1]
  • 原文地址:https://blog.csdn.net/qui910/article/details/125438990