Docker 学习笔记(三):网络基础配置方法

在真正的容器生产环境中,若要对外提供服务,至少存在两种工作方式:

  1. 通过网络访问容器内部的应用和服务;
  2. 应用可能包含不止一个服务组件,这往往就需要多个容器通过网络互联,协同工作。

这就需要掌握容器网络的配置方法。这篇笔记记录两个最基本的知识点:

  1. 设置端口映射访问容器应用
  2. 设置容器互联实现容器间通信

一、设置端口映射访问容器应用

启动容器后,默认情况下,在容器外部,是无法通过网络访问容器内部的应用和服务的。这时,需要通过指定 “-P” 或 “-p” 选项进行端口映射。

  • -P:由 Docker 随机选定宿主机的端口映射到容器内部
  • -p:指定宿主机的端口映射到容器内部
随机选定宿主机端口进行映射

在 “docker run” 指令中使用 “-P” 选项,创建并运行容器后,能够看到本地的 “32679” 端口映射到该容器中的端口为 5000 的 “python” 服务上。

andy-zhang@localhost:~$ sudo docker run -d --name web-1 -P training/webapp python app.py
288bcfc7b84c1d5b0b16cb1ba9fbc5af6071377452f54b91675637e7bb975e9e

andy-zhang@localhost:~$ sudo docker ps -a
CONTAINER ID   IMAGE             COMMAND           CREATED          STATUS         PORTS                    NAMES
288bcfc7b84c   training/webapp   "python app.py"   10 seconds ago   Up 8 seconds   0.0.0.0:32769->5000/tcp  web-1

“0.0.0.0” 代表在外部通过本机任意可达的 IP 地址都能进行访问,宿主机的 IP 地址为 “192.168.198.129”,通过容器外部网络测试结果如下图所示:

随机选定宿主机端口进行映射

利用同样的方法,我们可以创建多个“宿主机-容器”的端口映射关系

andy-zhang@localhost:~$ sudo docker run -d --name web-2 -P training/webapp python app.py
adc2d9957013113b67ca6381d82b1a46e3a8f4af40ecbce3b460e127faa7f0d6

andy-zhang@localhost:~$ sudo docker run -d --name web-3 -P training/webapp python app.py
cf1b495166cc6b3965dc13d93f0b8d7226308c02e9070f9891cbd175df256855

andy-zhang@localhost:~$ sudo docker ps -a
CONTAINER ID   IMAGE             COMMAND           CREATED          STATUS         PORTS                     NAMES
cf1b495166cc   training/webapp   "python app.py"   6 seconds ago    Up 6 seconds   0.0.0.0:32771->5000/tcp   web-3
adc2d9957013   training/webapp   "python app.py"   11 seconds ago   Up 10 seconds  0.0.0.0:32770->5000/tcp   web-2
288bcfc7b84c   training/webapp   "python app.py"   14 minutes ago   Up 14 minutes  0.0.0.0:32769->5000/tcp   web-1

##############借助宿主机端口映射,访问内部每个容器################

andy-zhang@localhost:~$ sudo docker logs -f web-1
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
192.168.198.1 - - [05/Feb/2020 04:00:37] "GET / HTTP/1.1" 200 -
192.168.198.1 - - [05/Feb/2020 04:00:37] "GET /favicon.ico HTTP/1.1" 404 -

andy-zhang@localhost:~$ sudo docker logs -f web-2
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
192.168.198.1 - - [05/Feb/2020 04:09:23] "GET / HTTP/1.1" 200 -
192.168.198.1 - - [05/Feb/2020 04:09:23] "GET /favicon.ico HTTP/1.1" 404 -

andy-zhang@localhost:~$ sudo docker logs -f web-3
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
192.168.198.1 - - [05/Feb/2020 04:09:27] "GET / HTTP/1.1" 200 -
192.168.198.1 - - [05/Feb/2020 04:09:27] "GET /favicon.ico HTTP/1.1" 404 -

通过宿主机端口映射配置访问容器服务的网络架构如下图所示:

通过端口映射访问不同容器

容器网络层提供的 IP 地址分配机制,会为每个容器分配自己的 IP 地址 (172.17 私有网络),对使用者屏蔽。

指定宿主机端口进行映射

使用 “-P” 选项,宿主机映射端口由 Docker 平台随机分配,访问前需要进行查询,而采用 “-p” 选项,则可以通过人为设定而固化访问端口。

注意:一个端口只允许绑定一个容器

"-p" 选项支持的格式有:

  • host-port:container-port:映射宿主机所有地址的指定端口到容器的指定端口
  • host-ip:host-port:container-port:映射宿主机指定地址的指定端口到容器的指定端口
  • host-ip(localhost)::container-port:映射宿主机 localhost 地址(127.0.0.1)的任意端口到容器的指定端口

注意:宿主机的端口也不是随意指定的,不开放或不存在的端口号是无法使用的

按照上述不同的映射配置方式创建容器,示例如下:

#########host-port:container-port#############
andy-zhang@localhost:~$ sudo docker run -d --name web4 -p 5000:5000 training/webapp python app.py

#########host-ip:host-port:container-port#############
andy-zhang@localhost:~$ sudo docker run -d --name web5 -p 192.168.198.129:5001:5000 training/webapp python app.py

#########host-ip(localhost)::container-port#############
andy-zhang@localhost:~$ sudo docker run -d --name web6 -p 127.0.0.1::5000 training/webapp python app.py

#########host-ip(localhost)::container-port#############
andy-zhang@localhost:~$ sudo docker run -d --name web7 -p 127.0.0.1::5000 training/webapp python app.py

######################查看采用不同映射方式创建的容器###########################

andy-zhang@localhost:~$ sudo docker ps -a
CONTAINER ID   IMAGE             COMMAND          CREATED           STATUS          PORTS                            NAMES
529d6b5d1209   training/webapp   "python app.py"  3 seconds ago     Up 1 second     127.0.0.1:32772->5000/tcp        web-7
70c8ba9db20b   training/webapp   "python app.py"  15 seconds ago    Up 13 seconds   127.0.0.1:32768->5000/tcp        web-6
accc1bc01f0a   training/webapp   "python app.py"  38 seconds ago    Up 36 seconds   192.168.198.129:5001->5000/tcp   web-5
738a70955c23   training/webapp   "python app.py"  2 minutes ago     Up 2 minutes    0.0.0.0:5000->5000/tcp           web-4

上述方式中,“web-4” 和 “web-5” 映射到了外部可达的地址,即 “192.168.198.129”,因此能够在外部进行访问:

可以成功访问web-4的服务
可以成功访问web-5的服务

而 “web-6” 和 “web-7” 只映射到本地地址,即 “127.0.0.1”,因此只能在本地进行访问:

andy-zhang@localhost:~$ curl 127.0.0.1:32768
Hello world! 
无法访问web-6的服务

最后,可以通过 docker port CONTAINER 指令查询容器映射的端口情况

andy-zhang@localhost:~$ sudo docker port 738a70955c23
5000/tcp -> 0.0.0.0:5000
andy-zhang@localhost:~$ sudo docker port accc1bc01f0a
5000/tcp -> 192.168.198.129:5001

二、设置容器互联实现容器间通信

使用 “--link” 选项,能够实现容器间的安全通信。命令格式为:docker run --link NAME:ALIAS,代表将一个容器 “链接” 到另外一个容器上。可以称链接者为 “子容器”,被链接者为 “父容器”

容器链接

下面通过一个 Web 应用来举例。一个典型的 Web 应用可以由业务容器和数据库容器组成,业务容器提供对外的业务服务访问,内部则和数据库容器进行通讯,而数据库容器则不需要对外暴露访问地址和端口。架构如下:

Web应用典型架构
第一步,创建数据库容器

简化起见,采用 Docker Hub 的一个 PostgreSQL 数据库的镜像:training/postgres

#获取PostgreSQL镜像
andy-zhang@localhost:~$ sudo docker pull training/postgres

#创建并启动PostgreSQL容器
andy-zhang@localhost:~$ sudo docker run -d --name postgre-db training/postgres

#进入PostgreSQL容器,启动bash
andy-zhang@localhost:~$ sudo docker exec -i -t 838b8725282e bash

#查看PostgreSQL服务是否正常运行
root@838b8725282e:/# ps -ax | grep postgre
     1 ?        Ss     0:00 su postgres -c /usr/lib/postgresql/$PG_VERSION/bin/postgres -D 
     ……
     ……

#查询PostgreSQL容器IP地址,172.17.0.9
root@838b8725282e:/# ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:ac:11:00:09  
          inet addr:172.17.0.9  Bcast:172.17.255.255  Mask:255.255.0.0
          ……
          ……
第二步,创建业务容器,并链接到该数据库容器中

仍然采用上文的 “training/webapp” 作为业务容器镜像模板。使用 “--link” 选项链接到第一步创建的 “postgre-db” 容器

sudo docker run -d --name web1 --link postgre-db:db -p 192.168.198.129:5001:5000 training/webapp python app.py
sudo docker run -d --name web2 --link postgre-db:db -p 192.168.198.129:5002:5000 training/webapp python app.py
sudo docker run -d --name web3 --link postgre-db:db -p 192.168.198.129:5003:5000 training/webapp python app.py

为了效果对比,创建一个不使用 “--link” 选项的普通业务容器

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

使用 docker exec -i -t 指令登录到 web-1(web-2/web-3 和 web-1 一样,不重复操作)和 web-temp 业务容器中,做如下四件事:

  • 查询容器 IP 地址
  • 执行 env | grep DB 命令
  • ping 数据库容器 IP 地址,即 172.17.0.9
  • ping 数据库容器名,即 postgre-db

最后的结果是:

  • web-1、web-2、web-3、web-temp 和 postgre-db 均由容器平台自动分配了内部 IP,地址段为 172.17.0.*
  • 执行 env | grep DB 命令后,web-1、web-2、web-3 均能查询到 postgre-db 容器的信息,而 web-temp 则查询不到,这正是 “--link” 选项的结果
DB_NAME=/web1/db
DB_PORT_5432_TCP_ADDR=172.17.0.9
DB_PORT=tcp://172.17.0.9:5432
DB_PORT_5432_TCP=tcp://172.17.0.9:5432
DB_PORT_5432_TCP_PORT=5432
DB_PORT_5432_TCP_PROTO=tcp
DB_ENV_PG_VERSION=9.3
  • web-1、web-2、web-3、web-temp 都能 ping 通 postgre-db 容器 IP
  • web-1、web-2、web-3 能够 ping 通 postgre-db 容器名,web-temp 则不行

对于未创建关联,却能够通过内部 IP 成功互联的问题,在实际应用场景下,问题不大。内部 IP 属于基础设施层面的管理,而容器则处于租户层面,基于用户角色管控,租户只能获取自己容器的相关信息。当然,如果对于管理员“作恶”,那是另外一个范畴的问题了。后续专门会针对容器安全进行学习和整理,此处不再展开了。


Look,Docker!
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容

  • 一、Docker容器概述 1、docker中的容器技术演进 lxc --> libcontainer --> ru...
    任总阅读 3,912评论 0 26
  • docker提供了映射容器端口到宿主主机和容器互联机制来为容器提供网络服务。本节讲解docker的网络功能,包括使...
    八目朱勇铭阅读 649评论 0 1
  • 大量的互联网应用服务包括多个服务组件,这往往需要多个容器之间通过网络通信进行相互配合。Docker目前提供了映射容...
    王滕辉阅读 374评论 0 0
  • 五、Docker 端口映射 无论如何,这些 ip 是基于本地系统的并且容器的端口非本地主机是访问不到的。此外,除了...
    R_X阅读 1,734评论 0 7
  • 没有反思的人生不值得过 -苏格拉底 时间管理践行的第486天,第17个月度检视。 一、健康:时间管理的基础是精力管...
    马净1887阅读 181评论 0 0