bridge 模式

docker pull busybox

docker run -d --name test1 busybox /bin/sh -c "while true; do sleep 3600; done;"

查看目前docker存在的网络

docker network ls

查看docker网络详情 语法:docker network inspect [ network id]

docker network inspect b082622a801e

示例

[vagrant@docker-node1 ~]$
[vagrant@docker-node1 ~]$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
b082622a801e        bridge              bridge              local
7493b2597cb5        host                host                local
70f231a3a944        none                null                local
[vagrant@docker-node1 ~]$ docker network inspect b082622a801e
[
    {
        "Name": "bridge",
        "Id": "b082622a801eaa1d003bad837de3a2185634c48986c77892d2c59cf3e230b8f8",
        "Created": "2018-12-28T01:59:14.320061696Z",
.....

使用命令 ip a

图片

安装查看linux网络桥接工具bridge-utils

查看桥接网络

图

再次创建一个容器:

docker run -d --name test2 busybox /bin/sh -c "while true; do sleep 3600; done;"

图

docker bridge network表示图

图

访问外网则通过nat技术、访问

docker container中的link功能

假设有一种场景、搭建了一个web服务器、但是nginx和php和mysql是分开的容器,如果我的PHP要访问mysql那么必须知道地址才可以访问。那么我在PHP容器里面、我是如何知道mysql的地址。

当然是可以进入mysql容器中查看它IP 然后在去PHP容器中更改ip地址。那么相当的不便。 docker link功能就能解决这个问题。但是link用的很少,它只能单向获取。

docker stop 7e83 #删除test2

[vagrant@docker-node1 ~]$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
1b825fbfa3be        busybox             "/bin/sh -c 'while t…"   23 hours ago        Up 2 minutes                            test1

重新启动test2 添加 –link test1 「test1是上面的容器名字」

docker run -d --name test2 --link test1 busybox /bin/sh -c "while true; do sleep 3600; done;"

进入test2里面可以ping通test1

图

ping名字 只能单向、用的不多

删除test2

docker stop test2
docker rm test2

创建docker network bridge

sudo docker network create -d bridge my-bridge

图

可以新建容器指定 网络my-bridge

docker run -d --name test3 --network my-bridge busybox /bin/sh -c "while true; do sleep 3600; done;"

图

docker run -d --name test2 busybox /bin/sh -c "while true;do sleep 3600;done;"

添加容器到指定的bridge

docker network connect my-bridge test2

docker network inspect 971630bb43d5  #my-bridge的network ID

图

现在进入test2里面、ping test3是可以ping通的。如果把test1加入my-bridge中那么也可以test1。

容器的端口间的映射

新建一个nginx服务器容器

sudo docker run --name web -d nginx

正常情况下、外网是访问不到的、只能本地主机进行访问。

docker stop web && docker rm web

重新建立对端口进行映射 -p参数

docker run --name web -d -p 80:80 nginx

图

这样本地就能访问里面的nignx服务器

图

docker none网络模式

none模式几乎不用、none指定后、不和主机和其他网络相连只能在主机

参数指定 –network none

docker run -d --name test1 --network none busybox /bin/sh -c "while true;do sleep 3600; done;"

docker exec -it test1   /bin/sh
或者
docker exec -it test1   /bin/sh  -c "ip a"

图

只能通过exec 访问

docker host网络模式

如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口

docker run -d --name test1 --network host busybox /bin/sh -c "while true;do sleep 3600; done;"

docker exec -it test1 /bin/sh -c "ip a"

图

使用host模式启动容器后可以发现,使用ip addr查看网络环境时,看到的都是宿主机上的信息。这种方式创建出来的容器,可以看到host上的所有网络设备。
容器中,对这些设备有全部的访问权限。因此docker提示我们,这种方式是不安全的。如果在隔离良好的环境中(比如租户的虚拟机中)使用这种方式,问题不大。

简单的多容器部署

新建app.py

from flask import Flask
from redis import Redis
import os
import socket

app = Flask(__name__)
redis = Redis(host=os.environ.get('REDIS_HOST', '127.0.0.1'), port=6379)


@app.route('/')
def hello():
    redis.incr('hits')
    return 'Hello Container World! I have been seen %s times and my hostname is %s.\n' % (redis.get('hits'),socket.gethostname())


if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000, debug=True)

Dockerfile

FROM python:2.7
LABEL maintaner="xxx@gmail.com"
COPY . /app
WORKDIR /app
RUN pip install flask redis
EXPOSE 5000
CMD [ "python", "app.py" ]

build一个image

docker build -t flask-redis .

运行一个redis容器

docker run -d --name redis redis
docker run -d --link redis --name flask-redis -e REDIS_HOST=redis flask-redis

上面命令的 -e 是设置环境变量的 -e REDIS_HOST=redis 的意思就是设置一个环境变量 REDIS_HOST 值为redis

图

因为上一篇讲过 –link具有单向链接功能、flask-redis链接了redis容器。

进入flask-redis

docker exec -it flask-redis /bin/bash

图片

图

不同的linux机器的docker通信

图

两台主机通信用了VXLAN技术。具体的我自己不懂、原理上是数据包里面又包了一层数据包。

图

VXLAN(Virtual eXtensible Local Area Network)或许是目前最热门的网络虚拟化技术。网络虚拟化是指在一套物理网络设备上虚拟出多个二层网络。VXLAN由RFC7348定义,这是2014年定稿的一个协议,VXLAN协议将Ethernet帧封装在UDP内,再加上8个字节的VXLAN header,用来标识不同的二层网络。

VXLAN vs VLAN 文章链接地址:传送门

多机器通信overlay

在docker-node1上

ubuntu@docker-node1:~$ wget https://github.com/coreos/etcd/releases/download/v3.0.12/etcd-v3.0.12-linux-amd64.tar.gz
ubuntu@docker-node1:~$ tar zxvf etcd-v3.0.12-linux-amd64.tar.gz
ubuntu@docker-node1:~$ cd etcd-v3.0.12-linux-amd64
ubuntu@docker-node1:~$ nohup ./etcd --name docker-node1 --initial-advertise-peer-urls http://192.168.205.10:2380 \
--listen-peer-urls http://192.168.205.10:2380 \
--listen-client-urls http://192.168.205.10:2379,http://127.0.0.1:2379 \
--advertise-client-urls http://192.168.205.10:2379 \
--initial-cluster-token etcd-cluster \
--initial-cluster docker-node1=http://192.168.205.10:2380,docker-node2=http://192.168.205.11:2380 \
--initial-cluster-state new&

在docker-node2上

ubuntu@docker-node2:~$ wget https://github.com/coreos/etcd/releases/download/v3.0.12/etcd-v3.0.12-linux-amd64.tar.gz
ubuntu@docker-node2:~$ tar zxvf etcd-v3.0.12-linux-amd64.tar.gz
ubuntu@docker-node2:~$ cd etcd-v3.0.12-linux-amd64/
ubuntu@docker-node2:~$ nohup ./etcd --name docker-node2 --initial-advertise-peer-urls http://192.168.205.11:2380 \
--listen-peer-urls http://192.168.205.11:2380 \
--listen-client-urls http://192.168.205.11:2379,http://127.0.0.1:2379 \
--advertise-client-urls http://192.168.205.11:2379 \
--initial-cluster-token etcd-cluster \
--initial-cluster docker-node1=http://192.168.205.10:2380,docker-node2=http://192.168.205.11:2380 \
--initial-cluster-state new&

检查cluster状态

ubuntu@docker-node2:~/etcd-v3.0.12-linux-amd64$ ./etcdctl cluster-health
member 21eca106efe4caee is healthy: got healthy result from http://192.168.205.10:2379
member 8614974c83d1cc6d is healthy: got healthy result from http://192.168.205.11:2379
cluster is healthy

重启docker服务

在docker-node1上

$ sudo service docker stop
$ sudo /usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock --cluster-store=etcd://192.168.205.10:2379 --cluster-advertise=192.168.205.10:2375&

在docker-node2上

$ sudo service docker stop
$ sudo /usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock --cluster-store=etcd://192.168.205.11:2379 --cluster-advertise=192.168.205.11:2375&

创建overlay network

sudo docker network create -d overlay demo

图

进入docker-node2查看

图

通过查看etcd的key-value, 我们获取到,这个demo的network是通过etcd从node1同步到node2的

图

在node2里面现启动个redis

docker run -d –net dome –name redis redis

在去node1里面

docker run -d --name flask --link reids --network demo -e REDIS_HOST=redis flask-redis

图

查看node1启动的容器

图

补充:Vagrantfile

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.require_version ">= 1.6.0"

boxes = [
    {
        :name => "docker-node1",
        :eth1 => "192.168.205.10",
        :mem => "1024",
        :cpu => "1"
    },
    {
        :name => "docker-node2",
        :eth1 => "192.168.205.11",
        :mem => "1024",
        :cpu => "1"
    }
]

Vagrant.configure(2) do |config|

  config.vm.box = "centos/7"

  boxes.each do |opts|
      config.vm.define opts[:name] do |config|
        config.vm.hostname = opts[:name]
        config.vm.provider "vmware_fusion" do |v|
          v.vmx["memsize"] = opts[:mem]
          v.vmx["numvcpus"] = opts[:cpu]
        end

        config.vm.provider "virtualbox" do |v|
          v.customize ["modifyvm", :id, "--memory", opts[:mem]]
          v.customize ["modifyvm", :id, "--cpus", opts[:cpu]]
        end

        config.vm.network :private_network, ip: opts[:eth1]
      end
  end

  config.vm.synced_folder "./labs", "/home/vagrant/labs", 
  config.vm.provision "shell", privileged: true, path: "./setup.sh"

end
最后修改:2020 年 01 月 31 日
如果觉得我的文章对你有用,请随意赞赏