Reputation: 12077
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?
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/
Upvotes: 10
Views: 30291
Reputation: 6841
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:
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:
Listen 8080
Finally add to the Dockerfile the instruction to copy it:
COPY ./my-httpd.conf /usr/local/apache2/conf/httpd.conf
Upvotes: 4
Reputation: 14903
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 in 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.
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 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 -
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. 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 -
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.
Upvotes: 11