两个容器之间如何互通呢

docker官方已经不推荐使用--link进行网络连接了,建议使用自定义网络来实现容器互联.但是我们可以了解下

自定义网络

创建网络的命令是 docker network create

$  docker network create -d bridge individual

通过 -d 选项我们可以为新的网络指定驱动的类型,其值可以是刚才我们所提及的 bridgehostoverlaymaclannone,也可以是其他网络驱动插件所定义的类型。这里我们使用的是 Bridge Driver( 当我们不指定网络驱动时,Docker 也会默认采用 Bridge Driver 作为网络驱动 )。

通过 docker network ls或是 docker network list 可以查看 Docker 中已经存在的网络。

$  docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
bc14eb1da66b        bridge              bridge              local
35c3ef1cc27d        individual          bridge              local

之后在我们创建容器时,可以通过--network来指定容器所加入的网络,一旦这个参数被指定,容器便不会默认加入到 bridge 这个网络中了 ( 但是仍然可以通过 --network bridge 让其加入 )。

$ docker run -d --name mysql -e MYSQL_RANDOM_ROOT_PASSWORD=yes --network individual mysql:5.7

我们通过 docker inspect 观察一下此时的容器网络。

$  docker inspect mysql
[
    {
## ......
        "NetworkSettings": {
## ......
            "Networks": {
                "individual": {
                    "IPAMConfig": null,
                    "Links": null,
                     ## ......    
                }
            }
## ......
        }
## ......
    }
]

可以看到,容器所加入网络已经变成了 individual 这个网络了。

这时候我们通过 --link 让处于另外一个网络的容器连接到这个容器上,看看会发生什么样的效果。

$ docker run -d --name webapp --link mysql --network bridge webapp:latest
docker: Error response from daemon: Cannot link to /mysql, as it does not belong to the default network.
ERRO[0000] error waiting for container: context canceled

可以看到容器并不能正常的启动,而 Docker 提醒我们两个容器处于不同的网络,之间是不能相互连接引用的。

我们来改变一下,让运行 Web 应用的容器加入到 individual 这个网络,就可以成功建立容器间的网络连接了。

$ docker run -d --name webapp --link mysql --network individual webapp:latest

使用link连接

要让一个容器连接到另外一个容器,我们可以在容器通过 docker createdocker run创建时通过 --link 选项进行配置。

例如,这里我们创建一个 MySQL 容器,将运行我们 Web 应用的容器连接到这个 MySQL 容器上,打通两个容器间的网络,实现它们之间的网络互通。

 $ docker run -d --name mysql -e MYSQL_RANDOM_ROOT_PASSWORD=yes mysql

$ docker run -d --name webapp --link mysql webapp:latest

容器间的网络已经打通,那么我们要如何在 Web 应用中连接到 MySQL 数据库呢?Docker 为容器间连接提供了一种非常友好的方式,我们只需要将容器的网络命名填入到连接地址中,就可以访问需要连接的容器了。

假设我们在 Web 应用中使用的是 JDBC 进行数据库连接的,我们可以这么填写连接。

String url = "jdbc:mysql://mysql:3306/webapp";

在这里,连接地址中的 mysql 就好似我们常见的域名解析,Docker 会将其指向 MySQL 容器的 IP 地址。

在docker里面我们不再需要关心mysql容器中的地址,映射的事情交给docker处理就好.

expose port

我们需要对应的地址和端口去访问对应的服务,Docker 为容器网络增加了一套安全机制,只有容器自身允许的端口,才能被其他容器所访问。

我们首先查看下容器暴露了哪些端口

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                 NAMES
95507bc88082        mysql:5.7           "docker-entrypoint.s…"   17 seconds ago      Up 16 seconds       3306/tcp, 33060/tcp   mysql

可以看到mysql:5.7这个景象暴露了330633060端口,使用TCP协议访问.

想要暴露其他的端口,使用--expose参数即可,比如我们想暴露 33061和33062端口:

$  docker run -d --name mysql -e MYSQL_RANDOM_ROOT_PASSWORD=yes --expose 33061 --expose 33062 mysql:5.7

我们在通过docker ps看一下

$  docker ps 
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                       NAMES
3c4e645f21d7        mysql:5.7           "docker-entrypoint.s…"   4 seconds ago       Up 3 seconds        3306/tcp, 13306/tcp, 23306/tcp, 33060/tcp   mysql

可以看到docker容器已经将对应的端口暴露出来了,我们可以访问这个端口了.

容器暴露了端口只是类似我们打开了容器的防火墙,具体能不能通过这个端口访问容器中的服务,还需要容器中的应用监听并处理来自这个端口的请求。

alias

链接的时候就把容器的名字写死了,就丧失了灵活性和可配置性,如果代码里面写死了另一个名称,这样更改起来就会比较麻烦,docker支持使用alias来让我们摆脱容器名称的限制:

docker run -d --name webapp --link mysql:database webapp:latest

我们使用 --link <name>:<alias>的形式把mysql容器的别名设置为database,
上面的语句就可以写成

String url = "jdbc:mysql://database:3306/webapp";

端口映射

容器和外部怎么进行连接呢,自然是端口映射

通过 Docker 端口映射功能,我们可以把容器的端口映射到宿主操作系统的端口上,当我们从外部访问宿主操作系统的端口时,数据请求就会自动发送给与之关联的容器端口。

要映射端口,我们可以在创建容器时使用 -p 或者是 --publish 选项。

$ sudo docker run -d --name nginx -p 80:80 -p 443:443 nginx:1.12

使用端口映射选项的格式是-p <ip>:<host-port>:<container-port>,其中 ip 是宿主操作系统的监听 ip,可以用来控制监听的网卡,默认为 0.0.0.0,也就是监听所有网卡。host-port 和 container-port 分别表示映射到宿主操作系统的端口和容器的端口,这两者是可以不一样的,我们可以将容器的 80 端口映射到宿主操作系统的 8080 端口,传入 -p 8080:80 即可。

容器的参数一般都是 宿主机(不好理解的话,就是操作系统)参数:容器参数.

我们可以在容器列表里看到端口映射的配置。

$ sudo docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                      NAMES
bc79fc5d42a6        nginx:1.12          "nginx -g 'daemon of…"   4 seconds ago       Up 2 seconds        0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp   nginx

打印的结果里用 -> 标记了端口的映射关系。