I have a Docker image that runs Apache, and I have configured Apache (through httpd.conf) to listen on port 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.
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.
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.
docker exec -it 23c4e1f0ea66 /bin/bash
grep -ri "Listen 80"
My Dockerfile contains only one EXPOSE
declaration – 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?
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
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/
2
Answers
Port 80 is exposed by the parent Dockerfile for
httpd:2.4
image –https://github.com/docker-library/httpd/blob/75e85910d1d9954ea0709960c61517376fc9b254/2.4/Dockerfile
A
EXPOSE
statement inside Dockerfile is going to give you an output eventually indocker 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 –
This exposes the container port. Argument
--expose
is equal to a statement usingEXPOSE
in Dockerfile.Let’s try to publish the port now –
docker run -dit -p 8009 httpd:2.4
Output –
See the
0.0.0.0:32768
, it’s now published to the host machine with a random ephemeral port i.e 32768. You can publish it on a specific host port as well.Example –
docker run -dit -p 8009:8009 httpd:2.4
Output –
In a nutshell, there is no way right now to unexpose the port 80 from parent Dockerfile. You can certainly expose more ports.
It’s an open issue –
https://github.com/moby/moby/issues/2210
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 –
As per @BMitch –
There is a hint on how to do this at the DockerHub page. An alternative config file must be obtained and added to the container via the Dockerfile.
First get a copy of the config file:
Then edit the
my-httpd.conf
file and modify the port:Finally add to the Dockerfile the instruction to copy it: