docker网络基础

docker使用到的与linux网络有关的主要技术

  • Network Namespace(网络命名空间)
  • Veth设备对
  • Iptables/NetFilter
  • 网桥
  • 路由

标准的dokcer支持以下4种网络模式

  • host模式: 使用--net=host指定
  • container模式:使用--net=container:NAME_or_ID指定
  • none模式: 使用 --net=none指定
  • bridge模式:使用--net=bridge指定,为默认设置
    • docker第一次启动时会创建一个虚拟网桥,默认为docker0,在私有网络空间中给这个网桥分配一个子网,由docker创建出来的每一个容器,会创建一个虚拟的以太网设备(veth设备对),其中一端关联到网桥,一端使用linux的网络命名空间技术映射为容器内的eth0设备,然后从网桥的地址段内给eth0接口分配一个ip地址  

容器访问外部网络

器要想访问外部网络,需要本地系统的转发支持。在Linux 系统中,检查转发是否打开。

$sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1

如果为 0,说明没有开启转发,则需要手动打开。

从外部访问容器

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

当使用 -P 标记时,Docker 会随机映射一个 49000~49900 的端口到内部容器开放的网络端口。
-p(小写的)则可以指定要映射的端口,并且,在一个指定端口上只可以绑定一个容器。支持的格式有

ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort。

映射所有接口地址

使用 hostPort:containerPort 格式本地的 5000 端口映射到容器的 5000 端口,可以执行

$ sudo docker run -d -p 5000:5000 training/webapp python app.py

此时默认会绑定本地所有接口上的所有地址。

映射到指定地址的指定端口
可以使用 ip:hostPort:containerPort 格式指定映射使用一个特定地址,比如 localhost 地址 127.0.0.1

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

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

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

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

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

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

查看映射端口配置

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

$ docker port nostalgic_morse 5000    #container NAMES
127.0.0.1:49155.

注意:
容器有自己的内部网络和 ip 地址(使用 docker inspect 可以获取所有的变量,Docker 还可以有一个可变的网络配置。)

-p 标记可以多次使用来绑定多个端口,例如:

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

容器互联

官网示例

先创建一个新的 Docker 网络。

$ docker network create -d bridge my-net
-d 参数指定 Docker 网络类型,有 bridge overlay。其中 overlay 网络类型用于 Swarm mode\ 连接容器,运行一个容器并连接到新建的 my-net 网络 $ docker run -it --rm --name busybox1 --network my-net busybox sh 打开新的终端,再运行一个容器并加入到 my-net 网络 $ docker run -it --rm --name busybox2 --network my-net busybox sh 进入容器,通过互相ping 容器名称来判断是否互联

  

自己测试示例

#查看所有网络:
docker network ls #创建自己的网络
docker network create -d bridge my-bridge-network #检查网络(如果你检查网络,会发现里面什么都没有)
docker network inspect my-bridge-network

添加一个容器到自定义的网络

#指定网络 运行(将db添加为自定义的网络)
docker run -d --net=my-bridge-network --name db training/postgres     #--name 为定义的名字

#再次检查网络(会发现多了一个容器)
docker network inspect my-bridge-network #查看网络情况
docker inspect --format='{{json .NetworkSettings.Networks}}' db #查看ip地址
docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' db #启动另一个容器:并不在一个网段,未加入到自定义的网络 名称为web
docker run -d --name web training/webapp python app.py

进入交互模式,并且ping web的地址进行测试

docker exec -it db bash #此时是ping 不通的

#将web加入自定义的网络
$ docker network connect my-bridge-network web docker exec -it db bash   #然后在去交互模式ping web,就可以通信了

容器互联-linking系统

docker有一个linking 系统可以连接多个容器。它会创建一对父子关系,父容器可以看到所选择的 子容器的信息。

注意:
容器的名 称 是 唯 一的。如果 你 命名了一个 叫 web的容器,当 你 要 再次 使用 web这个名 称 的 时候 , 你 需要用 docker rm来 删 除之前创建的容器,也可以 再 执行 docker run的 时候 加--rm标记来 停止旧 的容器, 并删 除, rm 和 -d 参 数是 不兼 容的。

使用--name标记可以为容器命名

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

使用docker ps -l 来验证我们设定的命名

$ sudo docker ps -l

links可以让容器之间安全的交互,使用--link标记。

#先创建一个新的数据库容器,
$ sudo docker run -d --name db training/postgres #创建一个新的web容器,并将它link到db容器
$ docker run -d -P --name web --link db:db training/webapp python app.py # --link标记的格式:--link name:alias,name是我们要链接的容器的名称,alias是这个链接的别名(会在新建的容器中/etc/hosts添加一条记录 ip db 此处的db为指定的alias别名)

使用docker ps来查看容器的链接

可以看到命名的容器,db和web,db容器的names列有db也有web/db。这表示web容 器链接到db容器,他们是一个父子关系。在这个link中,2个容器中有一对父子关系。docker在2个 容器之间创建了一个安全的连接,而且不用映射他们的端口到宿主主机上。在启动db容器的时候也不 用-p和-P标记。使用link之后我们就可以不用暴露数据库端口到网络上。

docker 通过2种方式为父子关系的容器公开连接信息:

• 环境变量
• 更新/etc/hosts文件

#使用env命令来查看容器的环境变量
$ sudo docker run --rm --name web2 --link db:db training/webapp env #除了环境变量,docker还添加host信息到父容器的/etc/hosts的文件。下面是父容器web的hosts文件
$ sudo docker run -t -i --rm --link db:db training/webapp /bin/bash
root@aed84ee21bde:/opt/webapp# cat /etc/hosts

这里有2个hosts,第一个是web容器,web容器用id作为他的主机名,第二个是db容器的ip和主机名

root@aed84ee21bde:/opt/webapp# apt-get install -yqq inetutils-ping
root@aed84ee21bde:/opt/webapp# ping db
PING db (172.17.0.5): data bytes
bytes from 172.17.0.5: icmp_seq= ttl= time=0.267 ms
bytes from 172.17.0.5: icmp_seq= ttl= time=0.250 ms
bytes from 172.17.0.5: icmp_seq= ttl= time=0.256 ms
用ping来ping db容器,它会解析成172.17.0.

注意:官方的ubuntu镜像默认没有安装ping
注意:你可以链接多个子容器到父容器,比如我们可以链接多个web到db容器上。

docker高级网络配置

快速配置指南

下面是一个跟docker网络相关的命令列表,有些命令选项只有 在docker服务启动的时候才可以执行,而且不能马上生效。

• -b BRIDGE or --bridge=BRIDGE —   桥接配置
• --bip=CIDR —              定制docker0的掩码
• -H SOCKET... or --host=SOCKET... — 它告诉docker从哪个通道来接收run container stop container这样的命令,也是docker api的地址 • --icc=true|false           
• --ip-forward=true|false      
• --iptables=true|false        
• --mtu=BYTES —           
• --dns=IP_ADDRESS...         
• --dns-search=DOMAIN...       
• -h HOSTNAME or --hostname=HOSTNAME — 主机名配置
• --link=CONTAINER_NAME:ALIAS     — link 系统
• --net=bridge|none|container:NAME_or_ID|host     —桥接配置
• -p SPEC or --publish=SPEC       — 映射容器端口到宿主主机
• -P or --publish-all=true|false     — 映射容器端口到宿主主机

配置容器dns服务的方法

  • -h HOSTNAME or --hostname=HOSTNAME 设定容器的主机名,它会被写到/etc/hostname,/etc/hosts中的ip地址自动写成分配的ip地址, 在/bin/bash中显示该主机名。但它不会在docker ps中显示,也不会在其他的容器的/etc/hosts中显示。
  • --link=CONTAINER_NAME:ALIAS 这选项会在创建容器的时候添加一个其他容器CONTAINE_NAME的主机名到/etc/hosts文件中, 让新容器的进程可以使用主机名ALIAS就可以连接它。
  • --dns=IP_ADDRESS 添加dns服务器到容器的/etc/resolv.conf中,让容器用这ip地址来解析所有不在/etc/hosts中的主 机名。
  • --dns-search=DOMAIN 设定容器的搜索域,当设定搜索域为.example.com时,会在搜索一个host主机名时,dns不仅搜索 host,还会搜索host.example.com

注意:如果 没 有上 述最 后 2个 选 项, docker会用主机上的 /etc/resolv.conf来配置容器, 它 是 默 认配置。

创建自己的桥接

#停止旧网桥并删除
$ sudo service docker stop
$ sudo ip link set dev docker0 down
$ sudo brctl delbr docker0 # 创建自己的网桥
$ sudo brctl addbr bridge0
$ sudo ip addr add 192.168.5.1/24 dev bridge0
$ sudo ip link set dev bridge0 up
# 确认网桥启动
$ ip addr show bridge0 # 告诉docker桥接设置,并启动docker服务(在ubuntu上)
$ echo 'DOCKER_OPTS="-b=bridge0"' >> /etc/default/docker
$ sudo service docker start

docker服务启动成功并绑定容器到新的网桥,建一个容器,你会看到它的ip是我们的设置的新ip 段,docker会自动检测到它。

用brctl show可以看到容器启动或则停止后网桥的配置变化,在容器中使 用ip a 和ip r 来查看ip地址配置和路由信息

创建一个点到点连接(network namespace)

#创建一个名为nestest的 network namespace
ip netns add netest #列出系统中存在的network namespace
ip netns list #删除一个network namespace
ip netns delete nstest #在network namespace中执行一条命令
ip netns exec <network namespace name > command 如:
ip netns exec <network namespace name > ip addr #在network namespace中启动一个bash
ip netns exec <network namespace name > /bin/bash

默认docker会将所有容器连接到由docker0提供的虚拟子网,你也可以使用自己创建的网桥。但如 果你想要2个特殊的容器之间可以直连通信,而不用去配置复杂的主机网卡桥接。
解决办法很简单:创建一对接口,把2个容器放到这对接口中,配置成点到点链路类型。这2个容 器就可以直接通信了。配置如下:

# 在2个终端中启动2个容器
$ sudo docker run -i -t --rm --net=none base /bin/bash
root@1f1f4c1f931a:/#
$ sudo docker run -i -t --rm --net=none base /bin/bash
root@12e343489d2f:/# #找到他们的process IDs ,然后创建他们的 namespace entries
$ sudo docker inspect -f '{{.State.Pid}}' 1f1f4c1f931a
2989
$ sudo docker inspect -f '{{.State.Pid}}' 12e343489d2f
3004
$ sudo mkdir -p /var/run/netns
$ sudo ln -s /proc/2989/ns/net /var/run/netns/2989
$ sudo ln -s /proc/3004/ns/net /var/run/netns/3004
# 创建”peer“接口,然后配置路由

#在主机上创建虚拟网卡
$ sudo ip link add A type veth peer name B
$ sudo ip link set A netns 2989           #2989为一个network namespace ,此处是将网卡放到network namespace中的命令
$ sudo ip netns exec 2989 ip addr add 10.1.1.1/32 dev A
$ sudo ip netns exec 2989 ip link set A up       #启动网卡
$ sudo ip netns exec 2989 ip route add 10.1.1.2/32 dev A    #分配ip $ sudo ip link set B netns 3004
$ sudo ip netns exec 3004 ip addr add 10.1.1.2/32 dev B
$ sudo ip netns exec 3004 ip link set B up
$ sudo ip netns exec 3004 ip route add 10.1.1.1/32 dev B

现在这2个容器就可以相互ping通,并成功建立连接。点到点链路不需要子网和子网掩码,使用ip route 来连接单个ip地址到指定的网络接口。

如果 没 有 特 殊 需要 你不 需要指定 --net=none来创建点到点 链路 。 还有一个办法就是创建一个只跟主机通信的容器,除非有特殊需求,你可以仅用--icc=false来限制 主机间的通信。

 

docker 基础之网络管理的更多相关文章

  1. docker基础内容讲解

    一.初识docker 1.1 LXC介绍 LXC为LinuX Container的简写.Linux Container容器是一种内核虚拟化技术,可以提供轻量级的虚拟化,以便隔离进程和资源,而且不需要提 ...

  2. Docker基础用法篇

    Docker基础用法篇 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.安装docker 1>.依赖的基础环境 64 bits CPU Linux Kerner 3.10+ ...

  3. Docker基础(下)

    Docker基础(下) 链接:https://pan.baidu.com/s/1u8Tg5qB4ZZHEK6GqCJkjwg 提取码:u8hb 复制这段内容后打开百度网盘手机App,操作更方便哦 5. ...

  4. Docker - Docker基础命令及使用

    Docker Docker - 官网 Docker - Hub GitHub - Docker Docker中文社区 Docker基础命令 Docker 查看帮助信息:docker --help 查看 ...

  5. 【云计算】Docker云平台—Docker基础

    Docker云平台系列共三讲,此为第一讲:Docker基础 参考资料: Docker官方文档:https://docs.docker.com/ Docker从入门到实践:https://yeasy.g ...

  6. Docker基础技术:Linux Namespace(下)

    在 Docker基础技术:Linux Namespace(上篇)中我们了解了,UTD.IPC.PID.Mount 四个namespace,我们模仿Docker做了一个相当相当山寨的镜像.在这一篇中,主 ...

  7. Docker 基础技术:Linux Namespace(下)

    导读 在Docker基础技术:Linux Namespace(上篇)中我们了解了,UTD.IPC.PID.Mount 四个namespace,我们模仿Docker做了一个相当相当山寨的镜像.在这一篇中 ...

  8. Docker基础入门及示例

    Docker近几年的发展可谓一日千里,特别从是2013年随着一个基于LXC的高级容器引擎开源,到现在,其在linux和windows上都有了很好的支持,并且已经有很多公司将docker用于实际的生产环 ...

  9. Docker 基础 : 镜像

    目录 获取镜像 查看镜像信息 搜索镜像 删除镜像 创建镜像 导出和导入镜像 上传镜像 总结 镜像是 Docker 的三大核心概念之一.Docker 运行容器前需要本地存在对应的镜像,如果本地没有对应的 ...

随机推荐

  1. 上传第三方jar包至maven私服,以geotools为例

    上传jar包(模块打包方式为jar) mvn deploy:deploy-file -DgroupId=org.geotools -DartifactId=gt-api -Dversion=10.3 ...

  2. lyk

    /*这道题第一眼看的时候,设f[i]表示1--i的最大空闲时间 但是我们又可以发现,i时刻的最大空闲时间和后面选择任务的持续的时间是有关系的 那么我们就用f[i]来表是i——n的最大空闲时间,即倒着找 ...

  3. pycharm2019+破解补丁

    事先声明,由于本人的pycharm已经装好,故部分图片来自网络,转载请注明地址 这篇博文以前是2018版本 后来换电脑重装时发现失效了 索性装的2019版本 具体步骤可以参考下面的删除线,新的补丁和激 ...

  4. HDU3480-Division-斜率dp

    首先想到的就是sort一下,然后每个集合都在排过序的数组里面取,不重复. 这样就推出公式dp[i][j] = min(dp[k][j-1] + (s[i]-s[k+1])^2) 其中dp[i][j]为 ...

  5. 戴尔服务器H330阵列卡取消磁盘阵列教程

    一:服务器开机看到ctrl+R提示,按ctrl+r进入阵列卡配置界面 二:按ctrl+N 转到PD Mgmt查看硬盘信息,确认硬盘状态:Ready 三:光标移到需配置硬盘上,按F2,选择 conver ...

  6. P1403 [AHOI2005]约数研究

    原题链接 https://www.luogu.org/problemnew/show/P1403 这个好难啊,求约数和一般的套路就是求1--n所有的约数再一一求和,求约数又要用for循环来判断.... ...

  7. ☆ [POJ2411] Mondriaan's Dream 「状压DP」

    传送门 >Here< 题意:用1*2的砖块铺满n*m的地板有几种方案 思路分析 状压经典题! 我们以$f[i][j]$作为状态,表示第i行之前全部填完并且第i行状态为j(状压)时的方案数. ...

  8. 数据分析---用pandas进行数据清洗(Data Analysis Pandas Data Munging/Wrangling)

    这里利用ben的项目(https://github.com/ben519/DataWrangling/blob/master/Python/README.md),在此基础上增添了一些内容,来演示数据清 ...

  9. Leetcode 11.盛最多水的容器 By Python

    给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) .在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0).找出其中的两条线, ...

  10. [HAOI2012]道路(最短路DAG上计数)

    C国有n座城市,城市之间通过m条[b]单向[/b]道路连接.一条路径被称为最短路,当且仅当不存在从它的起点到终点的另外一条路径总长度比它小.两条最短路不同,当且仅当它们包含的道路序列不同.我们需要对每 ...