Command | Function |
---|---|
EXPOSE |
Document where a service is available, but not create any mapping to the host. The EXPOSE instruction does not actually publish the port. It functions as a type of documentation between the person who builds the image and the person who runs the container, about which ports are intended to be published. |
--expose |
Expose a port at runtime, but not create any mapping to the host. |
-p |
Create a port mapping rule like -p ip:hostPort:containerPort . containerPort is required. If no hostPort is specified, Docker will automatically allocate one. |
-P |
Map a dynamically allocated host port to all container ports that have been exposed by the Dockerfile or –expose. |
--link |
Create a link between a consumer and service container, like –-link name:alias . This will create a set of environment variables and add entries into the consumer container’s /etc/hosts file. You must also expose or publish ports. |
EXPOSE就是EXPOSE,-p和-P实际才是PUBLISH。
在Dockerfile中使用 EXPOSE指令,或在docker run命令中使用 --expose=1234是等效的( --expose接受一定范围的端口作为参数,例如 --expose=2000-3000)。但是,本质上EXPOSE或–expose仅仅是元数据。Dockerfile的作者仅仅是通过EXPOSE提示镜像打算在哪些端口上提供服务,但Docker容器在启动时如果不指定端口映射(通过-p或-P参数)那么在容器外部是不能访问EXPOSE或–expose暴露的端口的(出于安全考虑);也就是说,由容器的操作人员来指定端口的映射规则。
我们可以造一个镜像来验证:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
[root@iZj6c9wo7lpk4csgnvjsbzZ docker-test]# cat Dockerfile FROM ubuntu:trusty EXPOSE 8888 CMD while true; do echo 'hello world' | nc -l -p 8888; done [root@iZj6c9wo7lpk4csgnvjsbzZ docker-test]# docker build -t expose-test:0.0.1 . Sending build context to Docker daemon 2.048 kB Step 1/3 : FROM ubuntu:trusty ---> df043b4f0cf1 Step 2/3 : EXPOSE 8888 ---> Using cache ---> 47e5b2ec4b6c Step 3/3 : CMD while true; do echo 'hello world' | nc -l -p 8888; done ---> Using cache ---> 8626ea5cb0ad Successfully built 8626ea5cb0ad [root@iZj6c9wo7lpk4csgnvjsbzZ docker-test]# docker run -d --name fuck expose-test:0.0.1 23e48eabe4a43074af5549412e424c7bd64ba0ae87de8b5e03676ffac52fd523 [root@iZj6c9wo7lpk4csgnvjsbzZ docker-test]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 23e48eabe4a4 expose-test:0.0.1 "/bin/sh -c 'while..." 10 seconds ago Up 10 seconds 8888/tcp fuck [root@iZj6c9wo7lpk4csgnvjsbzZ docker-test]# docker port 23e48eabe4a4 [root@iZj6c9wo7lpk4csgnvjsbzZ docker-test]# docker inspect fuck [ { "Id": "23e48eabe4a43074af5549412e424c7bd64ba0ae87de8b5e03676ffac52fd523", "Created": "2021-03-10T07:12:10.163580173Z", "Path": "/bin/sh", "Args": [ "-c", "while true; do echo 'hello world' | nc -l -p 8888; done" ], "State": { "Status": "running", "Running": true, "Paused": false, "Restarting": false, "OOMKilled": false, "Dead": false, "Pid": 30376, "ExitCode": 0, "Error": "", "StartedAt": "2021-03-10T07:12:10.362697048Z", "FinishedAt": "0001-01-01T00:00:00Z" }, "Image": "sha256:8626ea5cb0ad5d5509dcdabe9f4fa301b3f41ee77db862575daac95bed162750", "ResolvConfPath": "/var/lib/docker/containers/23e48eabe4a43074af5549412e424c7bd64ba0ae87de8b5e03676ffac52fd523/resolv.conf", "HostnamePath": "/var/lib/docker/containers/23e48eabe4a43074af5549412e424c7bd64ba0ae87de8b5e03676ffac52fd523/hostname", "HostsPath": "/var/lib/docker/containers/23e48eabe4a43074af5549412e424c7bd64ba0ae87de8b5e03676ffac52fd523/hosts", "LogPath": "", "Name": "/fuck", "RestartCount": 0, "Driver": "overlay2", "MountLabel": "", "ProcessLabel": "", "AppArmorProfile": "", "ExecIDs": null, "HostConfig": { "Binds": null, "ContainerIDFile": "", "LogConfig": { "Type": "journald", "Config": {} }, "NetworkMode": "default", "PortBindings": {}, "RestartPolicy": { "Name": "no", "MaximumRetryCount": 0 }, "AutoRemove": false, "VolumeDriver": "", "VolumesFrom": null, "CapAdd": null, "CapDrop": null, "Dns": [], "DnsOptions": [], "DnsSearch": [], "ExtraHosts": null, "GroupAdd": null, "IpcMode": "", "Cgroup": "", "Links": null, "OomScoreAdj": 0, "PidMode": "", "Privileged": false, "PublishAllPorts": false, "ReadonlyRootfs": false, "SecurityOpt": null, "UTSMode": "", "UsernsMode": "", "ShmSize": 67108864, "Runtime": "docker-runc", "ConsoleSize": [ 0, 0 ], "Isolation": "", "CpuShares": 0, "Memory": 0, "NanoCpus": 0, "CgroupParent": "", "BlkioWeight": 0, "BlkioWeightDevice": null, "BlkioDeviceReadBps": null, "BlkioDeviceWriteBps": null, "BlkioDeviceReadIOps": null, "BlkioDeviceWriteIOps": null, "CpuPeriod": 0, "CpuQuota": 0, "CpuRealtimePeriod": 0, "CpuRealtimeRuntime": 0, "CpusetCpus": "", "CpusetMems": "", "Devices": [], "DiskQuota": 0, "KernelMemory": 0, "MemoryReservation": 0, "MemorySwap": 0, "MemorySwappiness": -1, "OomKillDisable": false, "PidsLimit": 0, "Ulimits": null, "CpuCount": 0, "CpuPercent": 0, "IOMaximumIOps": 0, "IOMaximumBandwidth": 0 }, "GraphDriver": { "Name": "overlay2", "Data": { "LowerDir": "/var/lib/docker/overlay2/fd5bce812abd06d5c8beb8657987e218f415d9b16cc2f19ecde72cc2a6bd8ddf-init/diff:/var/lib/docker/overlay2/f9484534c675da6346dbe1a7d46808e6d0318ca93b07cb045c08dddb4e92b275/diff:/var/lib/docker/overlay2/c30c5303cc22968fae504c9dcdcbe7c8dcc66ca369f66a2cbc2be22bcb664520/diff:/var/lib/docker/overlay2/fa6b215be4912137838f0bac40effd8b1eeeabd3b7da20ed477891a3360ec65a/diff", "MergedDir": "/var/lib/docker/overlay2/fd5bce812abd06d5c8beb8657987e218f415d9b16cc2f19ecde72cc2a6bd8ddf/merged", "UpperDir": "/var/lib/docker/overlay2/fd5bce812abd06d5c8beb8657987e218f415d9b16cc2f19ecde72cc2a6bd8ddf/diff", "WorkDir": "/var/lib/docker/overlay2/fd5bce812abd06d5c8beb8657987e218f415d9b16cc2f19ecde72cc2a6bd8ddf/work" } }, "Mounts": [], "Config": { "Hostname": "23e48eabe4a4", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "ExposedPorts": { "8888/tcp": {} }, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ], "Cmd": [ "/bin/sh", "-c", "while true; do echo 'hello world' | nc -l -p 8888; done" ], "ArgsEscaped": true, "Image": "expose-test:0.0.1", "Volumes": null, "WorkingDir": "", "Entrypoint": null, "OnBuild": null, "Labels": {} }, "NetworkSettings": { "Bridge": "", "SandboxID": "6e7f08a2d2406be76ed31aa9ba5ef8df421c493548bd915dfb70d98a47f07bdc", "HairpinMode": false, "LinkLocalIPv6Address": "", "LinkLocalIPv6PrefixLen": 0, "Ports": { "8888/tcp": null }, "SandboxKey": "/var/run/docker/netns/6e7f08a2d240", "SecondaryIPAddresses": null, "SecondaryIPv6Addresses": null, "EndpointID": "be60b1aa78fc3a39be15d78600f8e00b0b4bd8d69a221ef895cbe148c403ca5e", "Gateway": "172.17.0.1", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "IPAddress": "172.17.0.2", "IPPrefixLen": 16, "IPv6Gateway": "", "MacAddress": "02:42:ac:11:00:02", "Networks": { "bridge": { "IPAMConfig": null, "Links": null, "Aliases": null, "NetworkID": "e4ca526b2564cc1bb356a11feae0bd042f20307795b9d4b7f53c49cb360b7582", "EndpointID": "be60b1aa78fc3a39be15d78600f8e00b0b4bd8d69a221ef895cbe148c403ca5e", "Gateway": "172.17.0.1", "IPAddress": "172.17.0.2", "IPPrefixLen": 16, "IPv6Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "MacAddress": "02:42:ac:11:00:02" } } } } ] [root@iZj6c9wo7lpk4csgnvjsbzZ docker-test]# |
可以看到只在Config中有ExposedPorts,而HostConfig和NetworkSettings中是没有的。
端口映射主要通过-P和-p参数来实现,一个宿主机端口只能绑定一个容器,其中:
1)-P,将Dockerfile内通过EXPOSE暴露的端口及–expose暴露的端口映射到宿主机的随机端口上;
2)-p,将容器内部开放的网络端口映射到宿主机的一个指定端口上;
我们可以通过如下的方法验证-P参数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
[root@iZj6c9wo7lpk4csgnvjsbzZ docker-test]# docker run -d --name fuck --expose=12345 -P expose-test:0.0.1 4a8bf055b4b27034ab385dc55a958632aafd45d1f6a5176e4d1dd18eb2cdac35 [root@iZj6c9wo7lpk4csgnvjsbzZ docker-test]# docker port fuck 12345/tcp -> 0.0.0.0:32768 8888/tcp -> 0.0.0.0:32769 [root@iZj6c9wo7lpk4csgnvjsbzZ docker-test]# docker inspect fuck [ { "Id": "4a8bf055b4b27034ab385dc55a958632aafd45d1f6a5176e4d1dd18eb2cdac35", "Created": "2021-03-10T07:27:30.272471603Z", "Path": "/bin/sh", "Args": [ "-c", "while true; do echo 'hello world' | nc -l -p 8888; done" ], "State": { "Status": "running", "Running": true, "Paused": false, "Restarting": false, "OOMKilled": false, "Dead": false, "Pid": 31433, "ExitCode": 0, "Error": "", "StartedAt": "2021-03-10T07:27:30.479718981Z", "FinishedAt": "0001-01-01T00:00:00Z" }, "Image": "sha256:8626ea5cb0ad5d5509dcdabe9f4fa301b3f41ee77db862575daac95bed162750", "ResolvConfPath": "/var/lib/docker/containers/4a8bf055b4b27034ab385dc55a958632aafd45d1f6a5176e4d1dd18eb2cdac35/resolv.conf", "HostnamePath": "/var/lib/docker/containers/4a8bf055b4b27034ab385dc55a958632aafd45d1f6a5176e4d1dd18eb2cdac35/hostname", "HostsPath": "/var/lib/docker/containers/4a8bf055b4b27034ab385dc55a958632aafd45d1f6a5176e4d1dd18eb2cdac35/hosts", "LogPath": "", "Name": "/fuck", "RestartCount": 0, "Driver": "overlay2", "MountLabel": "", "ProcessLabel": "", "AppArmorProfile": "", "ExecIDs": null, "HostConfig": { "Binds": null, "ContainerIDFile": "", "LogConfig": { "Type": "journald", "Config": {} }, "NetworkMode": "default", "PortBindings": {}, "RestartPolicy": { "Name": "no", "MaximumRetryCount": 0 }, "AutoRemove": false, "VolumeDriver": "", "VolumesFrom": null, "CapAdd": null, "CapDrop": null, "Dns": [], "DnsOptions": [], "DnsSearch": [], "ExtraHosts": null, "GroupAdd": null, "IpcMode": "", "Cgroup": "", "Links": null, "OomScoreAdj": 0, "PidMode": "", "Privileged": false, "PublishAllPorts": true, "ReadonlyRootfs": false, "SecurityOpt": null, "UTSMode": "", "UsernsMode": "", "ShmSize": 67108864, "Runtime": "docker-runc", "ConsoleSize": [ 0, 0 ], "Isolation": "", "CpuShares": 0, "Memory": 0, "NanoCpus": 0, "CgroupParent": "", "BlkioWeight": 0, "BlkioWeightDevice": null, "BlkioDeviceReadBps": null, "BlkioDeviceWriteBps": null, "BlkioDeviceReadIOps": null, "BlkioDeviceWriteIOps": null, "CpuPeriod": 0, "CpuQuota": 0, "CpuRealtimePeriod": 0, "CpuRealtimeRuntime": 0, "CpusetCpus": "", "CpusetMems": "", "Devices": [], "DiskQuota": 0, "KernelMemory": 0, "MemoryReservation": 0, "MemorySwap": 0, "MemorySwappiness": -1, "OomKillDisable": false, "PidsLimit": 0, "Ulimits": null, "CpuCount": 0, "CpuPercent": 0, "IOMaximumIOps": 0, "IOMaximumBandwidth": 0 }, "GraphDriver": { "Name": "overlay2", "Data": { "LowerDir": "/var/lib/docker/overlay2/ff981f7b8f81eb3c488d698eb6dcb870ac9854301d9e057280eba707aa81396e-init/diff:/var/lib/docker/overlay2/f9484534c675da6346dbe1a7d46808e6d0318ca93b07cb045c08dddb4e92b275/diff:/var/lib/docker/overlay2/c30c5303cc22968fae504c9dcdcbe7c8dcc66ca369f66a2cbc2be22bcb664520/diff:/var/lib/docker/overlay2/fa6b215be4912137838f0bac40effd8b1eeeabd3b7da20ed477891a3360ec65a/diff", "MergedDir": "/var/lib/docker/overlay2/ff981f7b8f81eb3c488d698eb6dcb870ac9854301d9e057280eba707aa81396e/merged", "UpperDir": "/var/lib/docker/overlay2/ff981f7b8f81eb3c488d698eb6dcb870ac9854301d9e057280eba707aa81396e/diff", "WorkDir": "/var/lib/docker/overlay2/ff981f7b8f81eb3c488d698eb6dcb870ac9854301d9e057280eba707aa81396e/work" } }, "Mounts": [], "Config": { "Hostname": "4a8bf055b4b2", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "ExposedPorts": { "12345/tcp": {}, "8888/tcp": {} }, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ], "Cmd": [ "/bin/sh", "-c", "while true; do echo 'hello world' | nc -l -p 8888; done" ], "ArgsEscaped": true, "Image": "expose-test:0.0.1", "Volumes": null, "WorkingDir": "", "Entrypoint": null, "OnBuild": null, "Labels": {} }, "NetworkSettings": { "Bridge": "", "SandboxID": "cea7056dbce40dd09525881362502430b79819981bdad6c99fa5538bb3a3d941", "HairpinMode": false, "LinkLocalIPv6Address": "", "LinkLocalIPv6PrefixLen": 0, "Ports": { "12345/tcp": [ { "HostIp": "0.0.0.0", "HostPort": "32768" } ], "8888/tcp": [ { "HostIp": "0.0.0.0", "HostPort": "32769" } ] }, "SandboxKey": "/var/run/docker/netns/cea7056dbce4", "SecondaryIPAddresses": null, "SecondaryIPv6Addresses": null, "EndpointID": "f08ecb997e2d9bfc1e4eaa0310974aae7b49e7599ba311d4e739d142d9cdbfdc", "Gateway": "172.17.0.1", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "IPAddress": "172.17.0.2", "IPPrefixLen": 16, "IPv6Gateway": "", "MacAddress": "02:42:ac:11:00:02", "Networks": { "bridge": { "IPAMConfig": null, "Links": null, "Aliases": null, "NetworkID": "e4ca526b2564cc1bb356a11feae0bd042f20307795b9d4b7f53c49cb360b7582", "EndpointID": "f08ecb997e2d9bfc1e4eaa0310974aae7b49e7599ba311d4e739d142d9cdbfdc", "Gateway": "172.17.0.1", "IPAddress": "172.17.0.2", "IPPrefixLen": 16, "IPv6Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "MacAddress": "02:42:ac:11:00:02" } } } } ] |
-p有几种用法:
①IP:HOSTPORT:CONTAINERPORT
指定宿主机IP、指定宿主机端口、指定容器端口,映射容器端口到宿主机指定IP的指定端口。例如,将容器的5000端口映射到127.0.0.1的5000端口上:
1 |
docker run -it -d -p 127.0.0.1:5000:5000 docker.io/centos:latest /bin/bash |
②IP::CONTAINERPORT
指定宿主机IP、不指定宿主机端口、指定容器端口,映射容器端口到宿主机指定IP的随机端口。例如,将容器的4000端口映射到127.0.0.1的随机端口上:
1 |
docker run -it -d -p 127.0.0.1::4000 docker.io/centos:latest /bin/bash |
上述命令会将容器4000端口映射到宿主机127.0.0.1的随机端口上。
③HOSTPORT:CONTAINERPORT
不指定宿主机IP、指定宿主机端口、指定容器端口,将容器指定端口映射到宿主机的指定端口上,并绑定到所有IP地址。例如,将容器的80端口映射到宿主机的8000端口上:
1 |
docker run -itd -p 8000:80 docker.io/centos:latest /bin/bash |
上述命令会绑定到本地所有网络接口的所有IP地址。
总结一下就是:我们可以省略IP或HOSTPORT,但是必须始终指定要暴露的CONTAINERPORT。如果只指定一个CONTAINERPORT,那么Docker将自动绑定所有IP并随机选择hostPort。通常,为了避免冲突我们会让Docker自己分配hostPort,所以经常会通过下面这种写法来随机映射容器的3000端口:
1 |
docker run -p 3000 image |
此外,默认-p和-P默认使用的是TCP。如果要使用UDP,那么可以通过:
1 |
docker run -p 80:80/tcp -p 80:80/udp ... |
指定。同样,EXPOSE默认也是TCP,如果要使用UDP,那么可以:
1 2 |
EXPOSE 80/tcp EXPOSE 80/udp |
我们可以通过如下的命令查看映射端口配置:
1 2 3 |
docker port CONTAINER_ID 或 docker port CONTAINER_NAME |
由于docker port只能在容器运行时显示端口映射,我们还可以通过docker inspect查看配置中的端口映射,这些信息位于Config、HostConfig和NetworkSettings中。
以下示例:
会将容器的80端口映射到宿主机的8000端口上。如果在容器中安装httpd服务,那么在宿主机上访问http://IP:HOSTPORT(即访问http://192.168.101.222:8000)就可以访问到容器了:
参考文档:
1、https://blog.csdn.net/a985588764/article/details/103857268
2、https://www.ctl.io/developers/blog/post/docker-networking-rules/
转载时请保留出处,违法转载追究到底:进城务工人员小梅 » Docker端口映射