I have problems figuring out how to properly set up a web server with https which contains multiple Docker containers.
I have a main container running apache by using the "httpd" docker-image. For simplicity lets call this website "main.com". SSL works perfectly here. I have set up the httpd.conf configuration file to redirect all calls to port 80 to port 443 and loaded SSL and proxy modules. (Port 80 and 443 are both exposed).
I have another Docker container which runs an API to serve geodata to "main.com". We can call this container for "side-container". In the Dockerfile for "side-container" I expose port 8080 from this. Then I can call "main.com:8080" to make a query to my "side-container" which runs the API.
Problem --> At least I could until I changed "main.com" to only use https.
I am stuck trying to get "side-container" to work again. When trying to connect to "main.com:8080" I get a timeout error.
My "docker ps" looks like this:
IMAGE COMMAND PORTS NAMES
main-container "httpd-foreground" 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp, 0.0.0.0:9010->9010/tcp main
side-container:latest "/docker-entrypoint.…" 0.0.0.0:8080->8080/tcp side-container
I use docker-compose to control the containers, so perhaps I need to set something there? I have made an attempt to get it working by using a reverse proxy setting in apache (see http.conf below), by using port 9010 on the "main" container to point to port 8080 on the "side-container". I can get it to reply with an "internal server error" due to a failed SSL handshake, but no more than that.
My background is in pure physics and not software and webservers so maybe I am missing something obvious. Any hint is greatly appreciated.
From httpd.conf:
<IfModule mod_ssl.c>
Listen 443
Listen 8080
Listen 0.0.0.0:9010 https
LoadModule socache_shmcb_module modules/mod_socache_shmcb.so
SSLProtocol all -SSLv3
SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
SSLHonorCipherOrder on
SSLCompression off
SSLSessionTickets off
SSLRandomSeed startup file:/dev/urandom 512
SSLRandomSeed connect file:/dev/urandom 512
SSLSessionCache shmcb:/dev/ssl_gcache_data(512000)
</IfModule>
<Virtualhost *:443>
ServerName main.com
SSLEngine on
#Primary Certificate file
SSLCertificateFile /usr/local/apache2/conf/certificate.crt
#Private Key
SSLCertificateKeyFile /usr/local/apache2/conf/private.key
#Chain bundle file
SSLCertificateChainFile /usr/local/apache2/conf/ca_bundle.crt
</VirtualHost>
<Virtualhost 0.0.0.0:9010>
ServerName main.com
SSLEngine on
SSLProxyEngine on
SSLProxyVerify none
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off
SSLProxyCheckPeerExpire off
SSLCertificateFile /usr/local/apache2/conf/certificate.crt
SSLCertificateKeyFile /usr/local/apache2/conf/private.key
SSLCertificateChainFile /usr/local/apache2/conf/ca_bundle.crt
ProxyPass /apptest http://0.0.0.0:8080/
ProxyPassReverse /apptest https://0.0.0.0:8080/
</VirtualHost>
docker-compose.yml:
version: '3'
services:
main-container:
build:
context: .
dockerfile: Dockerfile
container_name: "main"
restart: "always"
ports:
- "80:80"
- "443:443"
- "9010:9010"
links:
- side-container
networks:
- fu
side-container:
image: side-container:latest
container_name: "side-container"
ports:
- "8080:8080"
volumes:
- ${HOME}/data:/data
restart: "always"
networks:
- fu
networks:
fu:
driver: bridge
It's ok to have multiple processes, but to get the most benefit out of Docker, avoid one container being responsible for multiple aspects of your overall application. You can connect multiple containers using user-defined networks and shared volumes.
Surprisingly or not, neither Docker nor Podman support exposing multiple containers on the same host's port right out of the box. Example: docker-compose failing scenario with "Service specifies a port on the host. If multiple containers for this service are created on a single host, the port will clash."
Run multiple services in a container. It is generally recommended that you separate areas of concern by using one service per container. That service may fork into multiple processes (for example, Apache web server starts multiple worker processes). It’s ok to have multiple processes, but to get the most benefit out of Docker,...
A container’s main running process is the ENTRYPOINT and/or CMD at the end of the Dockerfile. It is generally recommended that you separate areas of concern by using one service per container. That service may fork into multiple processes (for example, Apache web server starts multiple worker processes).
First, you need to kick things off with a config file (docker-compose.yml) that encompasses images for both Nginx and certbot. Next, you can use this basic configuration to point incoming requests to HTTPS.
Lastly, since the default port for MySQL is 3306, we are mapping it to the container’s port 3306 and exposing that port for access. Once the above file is created, run the below command to get your Docker image created and run it as a container. The MySQL image will be pulled and then Docker will spin up a container to run this image.
When linking docker containers within the same network with docker compose you need to reference them by the docker service name, thus instead of 0.0.0.0
use side-container
:
ProxyPass /apptest http://side-container:8080/
ProxyPassReverse /apptest https://side-container:8080/
NOTE: the server running in the side container must be listening into 0.0.0.0:8080 in its httpd configuration.
Now you can remove from the docker compose file the ports declaration altogether, because both containers are in the same docker network, therefore you don't need to expose any ports. Exposing ports are only necessary if you want to reach the side-container
from localhost in the host machine or from the internet.
So from the side container remove:
ports:
- "8080:8080"
Also in the docker compose file you should replace links
with the new syntax depends_on
:
depends_on:
- side-container
For educational purpose.
Please bear in mind that when specifying the port like 8080:8080
is the same as 0.0.0.0:8080:8080
and 0.0.0.0
listens in all requests from the internet, thus to restrict them to localhost 127.0.0.1
of the machine running docker you would do 127.0.0.1:8080:8080
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With