参考:
端口映射
docker 中运行的应用可以通过外部网络来进行访问,比如我们的 web 应用使用 docker 容器运行,我们肯定需要通过外部网络来访问 web 应用提供的服务。这时候需要使用 -p
或 -P
进行容器的端口映射。
- -P:
docker
会随机映射一个49000~49900
的端口对容器中开放的端口进行映射。 - -p:我们可以指定宿主机与容器之间的端口映射。
使用 -P
来运行一个容器(其中的 demo-server 镜像可参考Dockerfile制作镜像示例):
[root@localhost dockerDir]# docker run -d -P --name demo3 demo-server
531ec87461829a23161e906ef67cc63265b4c4b70c4a2eab65eeff4fddde97d3
[root@localhost dockerDir]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
531ec8746182 demo-server "/bin/sh -c 'exec ja…" About a minute ago Up About a minute 0.0.0.0:32769->8080/tcp demo3
可以看到容器中开放的 8080
端口映射到了宿主机的 32769
端口。
如果容器内部开放了多个端口,-P
会全部分配一个随机的端口。
-p
则可以指定要映射的端口,并且,在一个指定端口上只可以绑定一个容器。支持的格式有 ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort
。
其中最常用的格式为 hostPort:containerPort
:
docker run -d -p 80:8080 --name demo demo-server
-p
可以同时绑定多个端口,如果容器内部开放多个端口的话,可以使用以下方式绑定:
docker run -d -p 80:8080 -p 8090:8090 --name demo demo-server
容器通信及network配置
运行两个容器:
docker run -d -p 81:8080 --name demo1 demo-server
docker run -d -p 82:8080 --name demo2 demo-server
容器在启动时,都会被分配一个 IP
地址,可以通过 docker inspect "容器ID或名称"
查看。当然,这个地址仅存在 docker
应用内部。
容器之间互相通信,可以使用这个 IP
地址。
# 进入demo2容器
[root@localhost dockerDir]# docker exec -it demo2 /bin/bash
# 使用demo1的IP地址对其进行通信
root@dac8487aba99:/# ping 172.17.0.3
PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data.
64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.231 ms
64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.138 ms
64 bytes from 172.17.0.3: icmp_seq=3 ttl=64 time=0.083 ms
但是容器每一次启动或者重启,这个 IP
地址都会改变,因此我们不建议使用 IP
地址通信。--link
和 network
可帮助我们解决这个问题。
--link
这里只是介绍 --link
的使用方式,而不推荐使用。随着 Docker 网络的完善,强烈建议大家将容器加入自定义的 Docker 网络来连接多个容器,而不是使用 --link
参数。
我们改变 demo2
对 demo1
的通信方式,使用容器名称对 demo1
进行通信:
[root@localhost dockerDir]# docker exec -it demo2 /bin/bash
root@dac8487aba99:/# ping demo1
ping: demo1: Name or service not known
可以看到是无法通信的,我们改变一下 demo2
的运行命令,在其后面添加一个 --link
:
# 当然,如果你是按照本篇文章来进行练习,需要先删除已存在demo2容器:docker rm -f demo2
docker run -d -p 82:8080 --name demo2 --link demo1 demo-server
容器启动好之后我们再次进行通信:
[root@localhost dockerDir]# docker exec -it demo2 /bin/bash
root@23076465d04e:/# ping demo1
PING demo1 (172.17.0.2) 56(84) bytes of data.
64 bytes from demo1 (172.17.0.2): icmp_seq=1 ttl=64 time=0.141 ms
64 bytes from demo1 (172.17.0.2): icmp_seq=2 ttl=64 time=0.108 ms
64 bytes from demo1 (172.17.0.2): icmp_seq=3 ttl=64 time=0.102 ms
现在已经可以正常通信了。
值得注意的是:
- 以上操作只能使
demo2
对demo1
进行通信,想要demo1
对demo2
进行通信,那么demo1
也需要使用--link
来链接demo2
。 - 使用
--link
其实就是修改了demo2
自己的host
文件和设置了环境变量而已。 - 使用
--link
链接容器时,被链接的容器必须存在。
--link
在 yml
文件中的使用方法:
links:
- db
- db:database //连接到 db 服务,并命名为 database
- redis
使用的别名将会自动在服务容器中的 /etc/hosts
里创建。例如:
172.12.2.186 db
172.12.2.186 database
172.12.2.187 redis
network
network
是目前常用的容器间通信方式。
新建网络
# 新建一个名为 my-net 的网络
docker network create -d bridge my-net
-d
参数指定 Docker 网络类型,有 bridge
overlay
。其中 overlay
网络类型用于 Swarm mode,在本小节中你可以忽略它。
显示所有网络
docker network ls
执行上面命令会发现,除了我们创建的 my-net
之外,还存在三个 bridge
host
nono
,且这三个是默认的无法删除的。
运行容器时加入网络
在运行容器时使用 --network
参数指定容器要加入的网络:
docker run -d -p 81:8080 --name demo1 --network my-net demo-server
docker run -d -p 82:8080 --name demo2 --network my-net demo-server
加入同一网络的容器可以使用容器名相互通信:
[root@localhost dockerDir]# docker exec -it demo1 /bin/bash
root@51ee50af6e16:/# ping demo2
PING demo2 (172.18.0.3) 56(84) bytes of data.
64 bytes from demo2.my-net (172.18.0.3): icmp_seq=1 ttl=64 time=0.189 ms
64 bytes from demo2.my-net (172.18.0.3): icmp_seq=2 ttl=64 time=0.099 ms
64 bytes from demo2.my-net (172.18.0.3): icmp_seq=3 ttl=64 time=0.097 ms
其他命令
# 可以查看该网络的详细信息,以及在该网络里的容器
docker inspect my-net
# 手动将某个容器加入网桥
docker network connect my-net demo3
-- end --