同福

使用docker的自定义网络network实现服务之间通过容器名称访问

介绍

介绍

前面福哥带着大家学习了使用Dockerfile制作PHP、MySQL、Redis和Elasticsearch的镜像,还使用PHP镜像连接了MySQL和Redis。大家可能发现一个问题,就是福哥在使用tfphp去连接tfmysql和tfredis的时候都会先查一下tfmysql和tfredis容器的IP地址,最后通过IP地址连接的tfmysql和tfredis容器上面的服务。为什么一定要用IP地址连接呢?这个IP地址还需要查询一下,而且重启容器后IP地址还会发送变化,太不靠谱了吧?

是的,使用IP地址确实存在各种问题,为了要解决这个问题需要建立一个自定义的docker网络,通过这个自定义的docker网络就可以使tfphp、tfmysql、tfredis、tfelasticsearch几个容器之间通过容器名称连接了!

今天福哥就带着大家建立一个自定义的docker网络tfnet,然后将tfphp、tfmysql、tfredis和tfelasticsearch都加入到tfnet网络里面,容器之间通过tfnet连接!

环境

操作系统
CentOS 7 x86_64 2009
服务器TFCentOS7x64
IP192.168.168.68
Docker18.06.3-ce, build d7080c1
Docker网络tfnet

docker默认网络

docker本身有三类默认网络,我们如果要自定义一个网络的话,也是基于这三类默认网络建立的。

bridge桥接网络

bridge网络是以桥接的方式建立的一个虚拟网络,每一个使用bridge网络创建的容器都会在网络列表里有一个对应的虚拟网络设备,每一个使用bridge网络创建的容器也都会有一个独立的内网IP地址。

使用bridge网络的容器通过虚拟网络的网关连接互联网!有独立IP地址!

创建一个基于bridge网络的容器network-bridge。

docker run -tid \
--name network-bridge \
-h network-bridge \
--net bridge \
registry.tongfu.net:5000/centos:centos7.9.2009

home/topic/2023/0807/21/9de0aacabd6e9ba962fe954299c75403.png

测试容器是否可以联网。

docker exec -ti network-bridge curl -sS https://tongfu.net/api/status

home/topic/2023/0807/22/988b3501887cf56b36339e1ea8a82f6d.png

查看容器的IP地址。

docker inspect network-bridge | grep IPAddress

home/topic/2023/0807/22/8f0693b52cff6d68af8df497b11e358b.png

host主机网络

host网络是共享主机的方式建立的一个虚拟网络,使用host网络创建的容器不会在网络列表里创建虚拟网络设备,因此也不会有独立的内网IP地址。

使用host网络的容器通过共享主机网络连接互联网!没有独立IP地址!

创建一个基于host网络的容器network-host。

docker run -tid \
--name network-host \
-h network-host \
--net host \
registry.tongfu.net:5000/centos:centos7.9.2009

home/topic/2023/0807/22/db2e6f68788799fc81c352a3c75e65f4.png

可以连接互联网!但是没有IP地址!

docker exec -ti network-host curl -sS https://tongfu.net/api/status
docker inspect network-host | grep IPAddress

home/topic/2023/0807/22/6ea48509fc8fdd078dc8c37e0da97550.png

none无网络

none网络就是没有网络,使用none网络创建的容器是不能连接互联网的!

使用none网络的容器不能连接互联网!

创建一个基于none网络的容器network-none。

docker run -tid \
--name network-none \
-h network-none \
--net none \
registry.tongfu.net:5000/centos:centos7.9.2009

home/topic/2023/0807/22/9c4856966d72e59815ce5ac99f79dfcb.png

不能连接互联网!也没有IP地址!

docker exec -ti network-none curl -sS https://tongfu.net/api/status
docker inspect network-none | grep IPAddress

home/topic/2023/0807/22/5960bbdd294d26fa37624724732f865a.png

创建自定义网络

查看网络

使用下面的目录查看现有网络。

docker network ls

home/topic/2023/0807/22/f2f1aff32ae56eb58723c75417488643.png

创建自定义网络

福哥创建了一个的自定义网络tfnet,网络是10.16.18.0,网关是10.16.18.1。

docker network create \
--subnet=10.16.18.0/16 \
--gateway=10.16.18.1 \
--opt com.docker.network.bridge.name=tfnet \
tfnet

home/topic/2023/0807/22/7d22100b840d3ad766cbff291ba5e261.png再次查看一下网络列表,有了我们的自定义网络tfnet了!

home/topic/2023/0807/22/b8873c9d42ff80efc7af1e9537339fb4.png

重建所有容器

要想让之前建立的容器使用tfnet网络只能删除旧的容器再建立新的容器才行,建立新的容器的时候使用--net参数指定容器网络为自定义网络tfnet,这样新的容器就会分配10.16.18.0的网络的IP地址了。

重建tfphp

docker rm -f tfphp
docker run -tid \
--name tfphp \
-h tfphp \
--net tfnet \
-p 80:80 \
-p 443:443 \
-v /tongfu.net/data/docker/data/tfphp/html:/var/www/html \
registry.tongfu.net:5000/tfphp:7.4-nginx-1.0.0

home/topic/2023/0807/22/26999ec2a9e04262b0e400050873d5b4.png

重建tfmysql

docker rm -f tfmysql
docker run -tid \
--name tfmysql \
-h tfmysql \
--net tfnet \
-p 3306:3306 \
-v /tongfu.net/data/docker/data/tfmysql:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=abcdef \
registry.tongfu.net:5000/tfmysql:5.7-1.0.0

home/topic/2023/0807/22/d80876d4b399520c682de7a887c2dc54.png

重建tfredis

docker rm -f tfredis
docker run -tid \
--name tfredis \
-h tfredis \
--net tfnet \
-p 6379:6379 \
-v /tongfu.net/data/docker/data/tfredis:/var/lib/redis \
registry.tongfu.net:5000/tfredis:6.0-1.0.0

home/topic/2023/0807/22/230a338e10870a9cab033c1f41b9d63b.png

重建tfelasticsearch

docker rm -f tfelasticsearch 
docker run -tid \
--name tfelasticsearch \
-h tfelasticsearch \
--net tfnet \
-p 9200:9200 \
-v /tongfu.net/data/docker/data/tfelasticsearch:/usr/share/elasticsearch/data \
registry.tongfu.net:5000/tfelasticsearch:6-1.0.0

home/topic/2023/0807/22/15274e82f1afa4296d046b4d35d138c6.png

测试连通性

tfmysql.php

把IP地址172.17.0.3改成tfmysql容器名称,然后测试用PHP连接MySQL数据库。

<?php

header("Content-Type: text/html; charset=utf-8");

try{
    // 连接数据库
    $pdo = new \PDO("mysql:host=tfmysql;dbname=tfmysql", "root", "abcdef", [\PDO::MYSQL_ATTR_INIT_COMMAND => "set names utf8mb4"]);
    $pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);

    // 获取数据库列表
    $rs = $pdo->prepare("show databases");
    $rs->execute();
    $dbs = $rs->fetchAll(\PDO::FETCH_ASSOC);

    // 获取数据表列表
    $rs = $pdo->prepare("show tables");
    $rs->execute();
    $tables = $rs->fetchAll(\PDO::FETCH_ASSOC);

    // 获取数据表数据
    $rs = $pdo->prepare("select * from user");
    $rs->execute();
    $data = $rs->fetchAll(\PDO::FETCH_ASSOC);

    // 数据库
    echo "<table border=\"1\"><tbody>";
    echo "<tr><th>Database</th></tr>";
    foreach ($dbs as $db){
        echo "<tr><td>". $db['Database']. "</td>";
    }
    echo "</tbody></table>";

    // 数据表
    echo "<table border=\"1\"><tbody>";
    echo "<tr><th>Table</th></tr>";
    foreach ($tables as $table){
        echo "<tr><td>". $table['Tables_in_tfmysql']. "</td>";
    }
    echo "</tbody></table>";

    // 数据
    echo "<table border=\"1\"><tbody>";
    echo "<tr>";
    foreach ($data[0] as $field => $value){
        echo "<th>". $field. "</th>";
    }
    echo "</tr>";
    foreach ($data as $row){
        echo "<tr>";
        foreach ($row as $field => $value){
            echo "<td>". $value. "</td>";
        }
        echo "</tr>";
    }
    echo "</tbody></table>";
}
catch (\PDOException $e){
    echo $e->getMessage();
}

home/topic/2023/0807/22/cca0dd3302f7b660b3c020165fa785fc.png

tfredis.php

把IP地址172.17.0.3改成tfredis容器名称,然后测试用PHP连接Redis数据库。

<?php

$redis = new \Redis();
$redis->connect("tfredis", 6379);
$redis->auth("tongfu.net");

echo "<b>String</b><br>";
print_r($redis->get("userNick"));
echo "<br><br><b>Hash</b><br>";
print_r($redis->hgetall("user"));
echo "<br><br><b>Set inter</b><br>";
print_r($redis->sinter("userTags", "userTags2"));
echo "<br><br><b>Set diff</b><br>";
print_r($redis->sdiff("userTags", "userTags2"));
echo "<br><br><b>Set union</b><br>";
print_r($redis->sunion("userTags", "userTags2"));
echo "<br><br><b>ZSet</b><br>";
print_r($redis->zrevrange("hotSubDomains", 0, -1));

home/topic/2023/0807/22/5330054df3cbee4b9f314064fac12ae6.png

总结

今天福哥带着大家学习了docker的自定义网络network的使用技巧,通过自定义的docker网络就可以让网络内的容器之间通过容器名称进行相互访问,这样实在是太方便了~

虽然有了自定义的docker网络解决了容器之间互联的问题,但是这么多服务管理起来还是有点繁琐的,有没有什么工具可以轻松管理这些容器呢?