我有一个运行Apache的Docker镜像,我已经配置了Apache(通过httpd.conf)来侦听端口8080
。
Listen 8080
当我构建我的图像并运行它时,我能够通过端口8080
成功连接到我的网站,所以在这一点上似乎都很好。
docker build -t my/apache:8080 .
docker run --name "MyWebsite" -p 8080:8080 -v ~/dir:/mnt/dir -d -t my/apache:8080
但是,当我使用docker ps
列出我正在运行的容器时,我发现端口80
也因某些原因而被暴露。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
23c4e1f0ea66 my/apache:8080 "/docker-entrypoint.…" 12 minutes ago Up 12 minutes 80/tcp, 0.0.0.0:8080->8080/tcp MyWebsite
当我打开正在运行的容器并搜索“Listen 80”的实例时,除了我添加到httpd.conf的“Listen 8080”实例之外,什么也没有显示。
docker exec -it 23c4e1f0ea66 /bin/bash
grep -ri "Listen 80"
我的Dockerfile只包含一个EXPOSE
声明 - EXPOSE 8080
。但是,我不认为这实际上暴露了端口,并且更多的是作为记录在运行利用映像的容器时应该暴露哪个端口的方式。
我怎样才能知道何时暴露端口80
,至关重要的是,如何阻止它暴露?
FROM httpd:2.4
COPY httpd.conf /usr/local/apache2/conf/
COPY docker-entrypoint.sh /
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["apache"]
### Apache (proxies to MapProxy).
EXPOSE 8080
#!/bin/bash
set -e
if [ "$1" = 'apache' ]; then
echo "Starting Apache"
httpd-foreground
fi
exec "$@"
ServerRoot "/usr/local/apache2"
Listen 8080
LoadModule mpm_event_module modules/mod_mpm_event.so
LoadModule authn_file_module modules/mod_authn_file.so
LoadModule authn_core_module modules/mod_authn_core.so
LoadModule authz_host_module modules/mod_authz_host.so
LoadModule authz_groupfile_module modules/mod_authz_groupfile.so
LoadModule authz_user_module modules/mod_authz_user.so
LoadModule authz_core_module modules/mod_authz_core.so
LoadModule access_compat_module modules/mod_access_compat.so
LoadModule auth_basic_module modules/mod_auth_basic.so
LoadModule reqtimeout_module modules/mod_reqtimeout.so
LoadModule filter_module modules/mod_filter.so
LoadModule mime_module modules/mod_mime.so
LoadModule log_config_module modules/mod_log_config.so
LoadModule env_module modules/mod_env.so
LoadModule headers_module modules/mod_headers.so
LoadModule setenvif_module modules/mod_setenvif.so
LoadModule version_module modules/mod_version.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule unixd_module modules/mod_unixd.so
LoadModule status_module modules/mod_status.so
LoadModule autoindex_module modules/mod_autoindex.so
<IfModule !mpm_prefork_module>
</IfModule>
<IfModule mpm_prefork_module>
</IfModule>
LoadModule dir_module modules/mod_dir.so
LoadModule alias_module modules/mod_alias.so
<IfModule unixd_module>
User daemon
Group daemon
</IfModule>
ServerAdmin [email protected]
ServerName mapproxy.gcs.lmkcloud.net:8080
DocumentRoot "/usr/local/apache2/htdocs"
ErrorLog /proc/self/fd/2
LogLevel warn
<IfModule log_config_module>
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b" common
<IfModule logio_module>
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
</IfModule>
CustomLog /proc/self/fd/1 common
</IfModule>
<IfModule mime_module>
TypesConfig conf/mime.types
AddType application/x-compress .Z
AddType application/x-gzip .gz .tgz
</IfModule>
<IfModule ssl_module>
SSLRandomSeed startup builtin
SSLRandomSeed connect builtin
</IfModule>
ProxyPreserveHost On
ProxyPass / http://example.com:8001/ retry=1 acquire=3000 timeout=20 Keepalive=On
ProxyPassReverse / http://example.com:8001/
端口80由父Dockerfile公开,用于httpd:2.4
映像 -
https://github.com/docker-library/httpd/blob/75e85910d1d9954ea0709960c61517376fc9b254/2.4/Dockerfile
Dockerfile中的EXPOSE
语句最终将在docker ps
中为您提供输出。但是,这仅暴露给容器网络,并且不允许通过定义的端口与同一网络外的容器或主机进行通信。要允许这种情况发生,您需要发布端口。
示例 -
docker run -dit --expose 8008 httpd:2.4
输出 -
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d628b537aded httpd:2.4 "httpd-foreground" 3 seconds ago Up 2 seconds 80/tcp, 8008/tcp objective_dewdney
这暴露了容器端口。参数--expose
等于使用EXPOSE
in Dockerfile的语句。
我们现在尝试发布端口 -
docker run -dit -p 8009 httpd:2.4
输出 -
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2c8c93a78e97 httpd:2.4 "httpd-foreground" 2 seconds ago Up 2 seconds 80/tcp, 0.0.0.0:32768->8009/tcp keen_swirles
请参阅0.0.0.0:32768
,它现在通过随机短暂端口发布到主机,即32768.您也可以在特定的主机端口上发布它。
示例 -
docker run -dit -p 8009:8009 httpd:2.4
输出 -
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1023df9822e5 httpd:2.4 "httpd-foreground" 2 seconds ago Up 2 seconds 80/tcp, 0.0.0.0:8009->8009/tcp fervent_almeida
简而言之,现在没有办法从父Dockerfile中取消端口80。你当然可以暴露更多的端口。
这是一个悬而未决的问题 - https://github.com/moby/moby/issues/2210 https://github.com/moby/moby/issues/3465
将@BMitch评论添加到我认为是现实的答案中,因为容器可以在同一网络中相互通信,而不管端口是否暴露 -
按照@BMitch -
EXPOSE只是文档/元数据。它不会改变容器彼此之间的通信方式。 docker ps只是让你知道图像创建者记录的一个端口可以发布但是还没有(因为没有地图的主机端)。除非您的代码或用户坚持认为此文档与您的环境相匹配,否则此处无需更改。为此,您必须重建上游图像。