简体   繁体   English

运行 apache 的 Docker 容器总是暴露端口 80

[英]Docker container running apache always exposing port 80

I have a Docker image that runs Apache, and I have configured Apache (through httpd.conf ) to listen on port 8080 .我有一个运行 Apache 的 Docker 映像,并且我已将 Apache(通过httpd.conf )配置为侦听端口8080

Listen 8080

When I build my image and run it, I'm able to successfully connect to my website via port 8080 , so all seems well at this point.当我构建我的映像并运行它时,我能够通过端口8080成功连接到我的网站,所以此时一切似乎都很好。

docker build -t my/apache:8080 .
docker run --name "MyWebsite" -p 8080:8080 -v ~/dir:/mnt/dir -d -t my/apache:8080

However, when I list my running containers using docker ps , I see that port 80 has also been exposed for some reason.但是,当我使用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

When I shell on to the running container and search for instances of "Listen 80", nothing shows up other than the instance of "Listen 8080" that I added to httpd.conf .当我打开正在运行的容器并搜索“Listen 80”的实例时,除了我添加到httpd.conf的“Listen 8080”实例之外,没有任何显示。

docker exec -it 23c4e1f0ea66 /bin/bash
grep -ri "Listen 80"

My Dockerfile contains only one EXPOSE declaration - EXPOSE 8080 .我的 Dockerfile 只包含一个EXPOSE声明 - EXPOSE 8080 However, I don't believe this actually exposes the port anyway, and is intended more as a way of documenting which port should be exposed when running a container that utilizes the image.但是,我不相信这实际上会公开端口,而是更多地作为一种记录在运行使用图像的容器时应该公开哪个端口的方式。

How can I find out when is exposing port 80 , and crucially, how can I stop it from being exposed?我怎样才能知道什么时候暴露端口80 ,最重要的是,我怎样才能阻止它被暴露?

Dockerfile文件

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

Entrypoint script入口点脚本

#!/bin/bash
set -e

if [ "$1" = 'apache' ]; then
        echo "Starting Apache"
        httpd-foreground
fi

exec "$@"

HTTP config 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/

Port 80 is exposed by the parent Dockerfile for httpd:2.4 image -端口 80 由父 Dockerfile 为httpd:2.4图像公开 -
https://github.com/docker-library/httpd/blob/75e85910d1d9954ea0709960c61517376fc9b254/2.4/Dockerfile https://github.com/docker-library/httpd/blob/75e85910d1d9954ea0709960c61517376fc9b254/2.4/Dockerfile

A EXPOSE statement inside Dockerfile is going to give you an output eventually in docker ps . EXPOSE语句最终会在docker ps为您提供输出。 However, that's exposed only to the container network & will not allow communication via the defined ports to containers outside of the same network or to the host machine.但是,它仅暴露给容器网络,并且不允许通过定义的端口与同一网络外部的容器或主机进行通信。 To allow this to happen you need to publish the ports.要允许这种情况发生,您需要发布端口。


Example -例子 -

docker run -dit --expose 8008 httpd:2.4

Output -输出 -

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

This exposes the container port.这会暴露容器端口。 Argument --expose is equal to a statement using EXPOSE in Dockerfile.参数--expose等于在 Dockerfile 中使用EXPOSE的语句。


Let's try to publish the port now -现在让我们尝试发布端口 -

docker run -dit -p 8009 httpd:2.4

Output -输出 -

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

See the 0.0.0.0:32768 , it's now published to the host machine with a random ephemeral port ie 32768. You can publish it on a specific host port as well.请参阅0.0.0.0:32768 ,它现在已发布到具有随机临时端口(即 32768)的主机。您也可以将其发布到特定主机端口。


Example -例子 -

docker run -dit -p 8009:8009 httpd:2.4

Output -输出 -

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

In a nutshell, there is no way right now to unexpose the port 80 from parent Dockerfile.简而言之,现在无法从父 Dockerfile 中取消暴露端口 80。 You can certainly expose more ports.您当然可以公开更多端口。

It's an open issue -这是一个悬而未决的问题——
https://github.com/moby/moby/issues/2210 https://github.com/moby/moby/issues/2210
https://github.com/moby/moby/issues/3465 https://github.com/moby/moby/issues/3465

Adding @BMitch comment to the answer which I believe is spot on since containers can communicate with each other in the same network irrespective of port exposed -将@BMitch 评论添加到我认为正确的答案中,因为容器可以在同一网络中相互通信,而不管暴露的端口 -

As per @BMitch -根据@BMitch -

EXPOSE is only documentation/metadata. EXPOSE 只是文档/元数据。 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). docker ps 只是让您知道图像创建者记录的端口可以发布但尚未发布(因为地图没有主机端)。 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.为此,您必须重建上游映像。

There is a hint on how to do this at the DockerHub page .DockerHub 页面上有关于如何执行此操作的提示 An alternative config file must be obtained and added to the container via the Dockerfile.必须通过 Dockerfile 获取备用配置文件并将其添加到容器中。

First get a copy of the config file:首先获取配置文件的副本:

docker run --rm httpd:2.4 cat /usr/local/apache2/conf/httpd.conf > my-httpd.conf

Then edit the my-httpd.conf file and modify the port:然后编辑my-httpd.conf文件,修改端口:

Listen 8080

Finally add to the Dockerfile the instruction to copy it:最后在 Dockerfile 中添加复制指令:

COPY ./my-httpd.conf /usr/local/apache2/conf/httpd.conf

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM