运行Apache的Docker容器始终暴露端口80

时间:2019-04-30 08:48:04

标签: apache docker port

我有一个运行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,并且至关重要的是,如何阻止其暴露?

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

入口点脚本

#!/bin/bash
set -e

if [ "$1" = '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/

2 个答案:

答案 0 :(得分:3)

端口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仅是文档/元数据。它不会改变   容器彼此通信。 docker ps只是让你   知道图像创建者记录的端口可以发布,但尚未发布   来过(因为地图上没有主机)。没什么可   除非您有代码或坚持这一点的用户,否则请在此处更改   文档符合您的环境。为此,您必须   重建上游图像。

答案 1 :(得分:0)

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