Docker 容器 运行 apache 总是暴露端口 80
Docker container running apache always exposing port 80
我有一个 Docker 图像 运行s Apache,我已经配置 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
列出我的 运行ning 容器时,我发现端口 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
当我 shell 进入 运行ning 容器并搜索 "Listen 80" 的实例时,除了我添加到的 "Listen 8080" 的实例之外没有任何显示httpd.conf.
docker exec -it 23c4e1f0ea66 /bin/bash
grep -ri "Listen 80"
我的 Docker 文件只包含一个 EXPOSE
声明 - EXPOSE 8080
。但是,我不认为这实际上会暴露端口,更多的目的是作为一种记录在 运行 使用图像的容器时应该暴露哪个端口的方式。
我如何知道什么时候暴露端口 80
,最重要的是,我怎样才能阻止它被暴露?
Docker文件
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 [ "" = 'apache' ]; then
echo "Starting Apache"
httpd-foreground
fi
exec "$@"
HTTP 配置
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 applicationdelivery@landmark.co.uk
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 由 httpd:2.4
图像的父 Dockerfile 公开 -
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
等于在 Dockerfile 中使用 EXPOSE
的语句。
让我们现在尝试发布端口 -
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 is only documentation/metadata. It doesn't change how
containers communicate with each other. docker ps is just letting you
know a port the image creator documented could be published but hasn't
been (since there's no host side of the map). There's nothing to
change here unless you have code or users that insist this
documentation matches your environment. For that, you'd have to
rebuild the upstream image.
在 DockerHub page 中有关于如何执行此操作的提示。必须通过 Dockerfile 获取替代配置文件并将其添加到容器中。
首先获取配置文件的副本:
docker run --rm httpd:2.4 cat /usr/local/apache2/conf/httpd.conf > my-httpd.conf
然后编辑my-httpd.conf
文件,修改端口:
Listen 8080
最后将复制指令添加到 Dockerfile 中:
COPY ./my-httpd.conf /usr/local/apache2/conf/httpd.conf
我有一个 Docker 图像 运行s Apache,我已经配置 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
列出我的 运行ning 容器时,我发现端口 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
当我 shell 进入 运行ning 容器并搜索 "Listen 80" 的实例时,除了我添加到的 "Listen 8080" 的实例之外没有任何显示httpd.conf.
docker exec -it 23c4e1f0ea66 /bin/bash
grep -ri "Listen 80"
我的 Docker 文件只包含一个 EXPOSE
声明 - EXPOSE 8080
。但是,我不认为这实际上会暴露端口,更多的目的是作为一种记录在 运行 使用图像的容器时应该暴露哪个端口的方式。
我如何知道什么时候暴露端口 80
,最重要的是,我怎样才能阻止它被暴露?
Docker文件
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 [ "" = 'apache' ]; then
echo "Starting Apache"
httpd-foreground
fi
exec "$@"
HTTP 配置
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 applicationdelivery@landmark.co.uk
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 由 httpd:2.4
图像的父 Dockerfile 公开 -
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
等于在 Dockerfile 中使用 EXPOSE
的语句。
让我们现在尝试发布端口 -
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 is only documentation/metadata. It doesn't change how containers communicate with each other. docker ps is just letting you know a port the image creator documented could be published but hasn't been (since there's no host side of the map). There's nothing to change here unless you have code or users that insist this documentation matches your environment. For that, you'd have to rebuild the upstream image.
在 DockerHub page 中有关于如何执行此操作的提示。必须通过 Dockerfile 获取替代配置文件并将其添加到容器中。
首先获取配置文件的副本:
docker run --rm httpd:2.4 cat /usr/local/apache2/conf/httpd.conf > my-httpd.conf
然后编辑my-httpd.conf
文件,修改端口:
Listen 8080
最后将复制指令添加到 Dockerfile 中:
COPY ./my-httpd.conf /usr/local/apache2/conf/httpd.conf