我发现docker启动容器时(以redis为例),在已经启动了一个-p 6379:6379的redis1容器后,当我们开启第二个redis2容器时,
右边的端口映射既可以写别的我们想要映射的端口(-p 6380:6380 redis2),也可以继续写6379(-p 6380:6379 redis2)!!!
因为众所周知,一个服务只能占用一个端口,但是这里却能映射相同的docker容器的端口号!(所以我很好奇)
(注:先测试映射6380的redis2,再换成映射6379的redis2,并且redis1一直是开启的状态)
1* 启动两个redis容器的(redis1配置文件端口为6379,redis2是6380)
首先是映射不同的端口创建两个容器,分别映射6379 和 6380 端口。
[root@zch config]# docker run -d --name redis1 -v /usr/local/docker/redis/config/redis1/redis.conf:/etc/redis.conf -v /usr/local/docker/redis/data:/data -p 6379:6379 redis:6.0.12 redis-server /etc/redis.conf
ffeac01946f1d34115734fb1405a68f5a020e6bb1b0f6100c6dbd257630ffe7a
[root@zch config]# docker run -d --name redis2 -v /usr/local/docker/redis/config/redis2/redis.conf:/etc/redis.conf -v /usr/local/docker/redis/data:/data -p 6380:6380 redis:6.0.12 redis-server /etc/redis.conf
ca58fb27e6f92d12afacebafaa854692f99fab9db4ce8fe66af8304cf8e9fffc
[root@zch config]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ca58fb27e6f9 redis:6.0.12 “docker-entrypoint.s…” 13 seconds ago Up 12 seconds 6379/tcp, 0.0.0.0:6380->6380/tcp redis2
ffeac01946f1 redis:6.0.12 “docker-entrypoint.s…” 52 seconds ago Up 51 seconds 0.0.0.0:6379->6379/tcp redis1
然后进入redis1和redis2的客户端,可以看到都是能成功连接上的
(注:在进入redis2的时候一定要以==-p 6380==进入)
[root@zch config]# docker exec -it redis1 redis-cli
127.0.0.1:6379> exit
[root@zch config]# docker exec -it redis2 redis-cli -p 6380
127.0.0.1:6380>
2* 接着我将原来的redis2容器删除后,再重新创建redis2,并把右边的映射端口,也改成和redis1一样的6379
docker run -d --name redis2 -v /usr/local/docker/redis/config/redis2/redis.conf:/etc/redis.conf -v /usr/local/docker/redis/data:/data -p 6380:6379 redis:6.0.12 redis-server /etc/redis.conf
然后再次进入redis2容器,会发现虽然是映射的还是6379,但依然是能够进入到客户端的
[root@zch ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
203a0d3dad1a redis:6.0.12 “docker-entrypoint.s…” 5 hours ago Up 5 minutes 0.0.0.0:6380->6379/tcp redis2
ffeac01946f1 redis:6.0.12 “docker-entrypoint.s…” 15 hours ago Up 3 seconds 0.0.0.0:6379->6379/tcp redis1
[root@zch ~]# docker exec -it redis2 redis-cli -p 6380
127.0.0.1:6380>
但是,注意到docker ps 的时候redis2的PORTS属性只剩下0.0.0.0:6380->6379/tcp了
再回看之前映射6380的redis2的PORTS属性:6379/tcp, 0.0.0.0:6380->6380/tcp
可以看到映射内部6380端口的redis2容器PORTS有两个值,并且没有与内部端口6379映射的本机ip
我们可以看下pull下来的redis镜像的具体信息
[root@zch config]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
redis 6.0.12 090314e0c44c 4 weeks ago 104MB
[root@zch config]# docker inspect 090314e0c44c
[
{
"Id": "sha256:090314e0c44c58e5faaa379904242657dcb4203e1a6a61413e534e0f40e8bdd5",
"RepoTags": [
"redis:6.0.12"
],
"RepoDigests": [
"redis@sha256:cc4231ed1a6ae4d0a3e0c85c205ba68d0cbcd60c837caca1334b01661eb8b3bb"
],
"Parent": "",
"Comment": "",
"Created": "2021-03-13T04:04:30.678552814Z",
"Container": "c62962de94021537ddd3d2a2cf36c1ee26eec6f374b65c9624fc54675b65beb3",
"ContainerConfig": {
"Hostname": "c62962de9402",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"ExposedPorts": {
"6379/tcp": {}
},
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"GOSU_VERSION=1.12",
"REDIS_VERSION=6.0.12",
"REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-6.0.12.tar.gz",
"REDIS_DOWNLOAD_SHA=f16ad973d19f80f121e53794d5eb48a997e2c6a85b5be41bb3b66750cc17bf6b"
],
"Cmd": [
"/bin/sh",
"-c",
"#(nop) ",
"CMD [\"redis-server\"]"
],
"Image": "sha256:09a494871c16ded394e132a87f16e105522b63e88c92018a1dddcf21d8b401f3",
"Volumes": {
"/data": {}
},
"WorkingDir": "/data",
"Entrypoint": [
"docker-entrypoint.sh"
],
"OnBuild": null,
"Labels": {}
},
"DockerVersion": "19.03.12",
"Author": "",
"Config": {
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"ExposedPorts": {
"6379/tcp": {}
},
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"GOSU_VERSION=1.12",
"REDIS_VERSION=6.0.12",
"REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-6.0.12.tar.gz",
"REDIS_DOWNLOAD_SHA=f16ad973d19f80f121e53794d5eb48a997e2c6a85b5be41bb3b66750cc17bf6b"
],
"Cmd": [
"redis-server"
],
"Image": "sha256:09a494871c16ded394e132a87f16e105522b63e88c92018a1dddcf21d8b401f3",
"Volumes": {
"/data": {}
},
"WorkingDir": "/data",
"Entrypoint": [
"docker-entrypoint.sh"
],
"OnBuild": null,
"Labels": null
},
"Architecture": "amd64",
"Os": "linux",
"Size": 104291820,
"VirtualSize": 104291820,
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/6f0cd9ab5a300e71ce8475861a4bc2b76a2826ec0020e787a43d38a5ff2db2ef/diff:/var/lib/docker/overlay2/d70138999bd376d810f4b4f6d1ada4560923317c74609ac467381fd0fc67d50a/diff:/var/lib/docker/overlay2/12991f82bf1068b3191de47ebf9d581f34bcc3a8a8cbdef0f90f052bf65b53e8/diff:/var/lib/docker/overlay2/85b82010fca6b6fa29cc66a3e3df59c1c934a5340e0dcfd023650c23439b2439/diff:/var/lib/docker/overlay2/0ae0ed3fdcd6cbe7a7c6aa491d837653a84e1a55f774a6604df1035c29012c65/diff",
"MergedDir": "/var/lib/docker/overlay2/83b39cef71e2dc3cd1ff367a3496afcbf68c248afe6cb427a348907fb94cefce/merged",
"UpperDir": "/var/lib/docker/overlay2/83b39cef71e2dc3cd1ff367a3496afcbf68c248afe6cb427a348907fb94cefce/diff",
"WorkDir": "/var/lib/docker/overlay2/83b39cef71e2dc3cd1ff367a3496afcbf68c248afe6cb427a348907fb94cefce/work"
},
"Name": "overlay2"
},
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:14a1ca976738392ffa2ae4e54934ba28ab9cb756e924ad9297a4795a4adbfdf6",
"sha256:a6b7270e6c20bae1d8c5d009171ce7db2e268c3d32e447a2ec4f33b02b256955",
"sha256:cf2aefb51919d2cf15e3311fec4e187f968e06f168ee610d500e81757b53a3f7",
"sha256:6e0e8a8a5ad7776289d5929ba624ce58e64600af5995f0208502fc265773a192",
"sha256:e3059a3a1a65e206c34ae3e24ae6098ede134e7ad4cbd8a5eae4b5feeeb38589",
"sha256:65508d7d88a08e37d76fad31e959cd15facecee0f1b3513ef4592d1186be077e"
]
},
"Metadata": {
"LastTagTime": "0001-01-01T00:00:00Z"
}
}
]
[root@zch config]#
注意到这个地方
“ExposedPorts”: {
“6379/tcp”: {}
},
也就是说,当我们pull下来镜像的时候,就已经在docker内部有一个默认的端口号了(一般就是平常各种服务默认的端口号),所以当我们通过镜像创建容器的时候,对于同一个镜像,它所创建的不同容器在docker内部的端口都有一个默认的和镜像一致的端口!
===查看与6380内部端口映射(-p 6380:6380)的redis2的元数据时(docker inspect redis2)发现
“Ports”: {
“6379/tcp”: null, //这里的就是docker容器内部默认的端口,只不过我们没有本机地址与它映射,所以为null,也是为何docker ps时有两个值的原因
“6380/tcp”: [
{
“HostIp”: “0.0.0.0”,
“HostPort”: “6380”
}
]
}
===再看与6379内部端口映射(-p 6380:6379)的redis2的元数据时(docker inspect redis2)发现
“Ports”: {
“6379/tcp”: [
{
“HostIp”: “0.0.0.0”,
“HostPort”: “6380”
}
]
}
这里就只有容器默认的内部端口6379和本机的映射了
所以,为何同一个docker内部端口6379能够与不同的本机端口相映射呢
我猜测是跟docker网络有关。。
所以我们查看一下开启前后的ip
(注:此时两个容器都是与内部端口6379映射的)
[root@zch ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
203a0d3dad1a redis:6.0.12 "docker-entrypoint.s…" 6 hours ago Up 49 minutes 0.0.0.0:6380->6379/tcp redis2
ffeac01946f1 redis:6.0.12 "docker-entrypoint.s…" 16 hours ago Up 43 minutes 0.0.0.0:6379->6379/tcp redis1
[root@zch ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:16:3e:30:ac:de brd ff:ff:ff:ff:ff:ff
inet 172.24.11.75/18 brd 172.24.63.255 scope global dynamic eth0
valid_lft 307823829sec preferred_lft 307823829sec
3: br-2ebc59f84c42: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:51:6f:6a:ad brd ff:ff:ff:ff:ff:ff
inet 172.18.0.1/16 brd 172.18.255.255 scope global br-2ebc59f84c42
valid_lft forever preferred_lft forever
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:42:98:e1:75 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
[root@zch ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:16:3e:30:ac:de brd ff:ff:ff:ff:ff:ff
inet 172.24.11.75/18 brd 172.24.63.255 scope global dynamic eth0
valid_lft 307824120sec preferred_lft 307824120sec
3: br-2ebc59f84c42: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:51:6f:6a:ad brd ff:ff:ff:ff:ff:ff
inet 172.18.0.1/16 brd 172.18.255.255 scope global br-2ebc59f84c42
valid_lft forever preferred_lft forever
4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:42:98:e1:75 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
12178: vethb34c46b@if12177: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 5a:35:bb:a2:4e:c1 brd ff:ff:ff:ff:ff:ff link-netnsid 0
12180: vetha7fde8c@if12179: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 72:24:61:31:6a:41 brd ff:ff:ff:ff:ff:ff link-netnsid 1
很明显,最后多了两个ip,也就是说docker为不同的容器分配了不同的ip,所以即便内部端口都是6379,但是由于前面的ip不同,所以自然也就可以共存(我猜的**)