skip to Main Content

I am fairly new to Docker and I have some trouble to understand how to make my “contained” apps accessible from the internet.

[my current configuration] two web sites (in /var/www/html) + standard Apache + some tweeking I would like to be applied to everything new I deploy (headers CSP based rewriting, SSL certificate renewal with Certbot, etc etc). I am fairly happy with my current conf.

[my two apps] Both are standalone applications (only requiring a db).

official wordpress image. (-> new domain name)

-a django based app packed with a gunicorn server based on this tutorial (-> subdomain of an existing domain )

[the issue] If I bind both apps on, say, ports 8080 and 8000, browsers wont be able to reach it, for DNS servers do not handle ports (from what I understood, correct me if I am wrong). If I bind then on standard ports, I’ll have a conflict with my existing Apache.

How would you deal with it? Can I redirect to containers’ internal ip with a mod_proxy of some kind? Is there a cleaner-easier-safer way to do it?

<VirtualHost *:443>
    ServerName sub.mydomain.io
    Redirect "/" "http://172.17.0.2/"

    ErrorLog /var/log/apache2/error.zarebski.io.com.log
    Include /etc/letsencrypt/options-ssl-apache.conf
    SSLCertificateFile /etc/letsencrypt/live/mydomain.io/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/mydomain.io/privkey.pem
</VirtualHost>

2

Answers


  1. Chosen as BEST ANSWER

    Well, it took me a while to figure things out, for there was two main corner cases. I'll stick to one case: the wordpress image

    <VirtualHost *:443>
        ServerName new_domain.eu
        ProxyPass / http://localhost:8081/
    
        <Location />
                AddOutputFilterByType SUBSTITUTE text/html
                SetOutputFilter proxy-html
                ProxyPassReverse /
                Substitute "s|http://localhost:8081/|https://new_domain.eu/|i"
                RequestHeader    unset  Accept-Encoding
        </Location>
    
        SSLCertificateFile /etc/letsencrypt/live/new_domain.eu/fullchain.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/new_domain.eu/privkey.pem
        Include /etc/letsencrypt/options-ssl-apache.conf
    </VirtualHost>
    

    [First of all], I could not access container from their local ip (i.e 172.7.0.3:80, not sure why), so I used the localhost port defined while setting the container up:

    docker run -e WORDPRESS_DB_PASSWORD=thePassWord --name wordpress --link wordpressdb:mysql -p 8081:80 -v "$PWD/html":/var/www/html -d wordpress
    

    [secondly] the tricky part was, then, to handle properly relative urls (e.g. some/path/to/css), for these were not accessible. Apparently, this is a well known issue. This part was the longest: things changed a lot around Apache 2.4 and the syntax is not well documented. Basically,

    Substitute "s|http://localhost:8081/|https://new_domain.eu/|i" 
    

    replace all urls in html so that relative resources (css, js, png, etc etc) could be properly accessed.

    [possible improvements] I am not quite happy with port 8081 being visible from the external world. It means that the app could be accessed from this very port, bypassing the rules I setted up in apache.conf. I fixed the issue by adding an iptables rule

    iptables -A INPUT -p tcp -s localhost --dport 8081 -j ACCEPT
    iptables -A INPUT -p tcp --dport 8081 -j DROP
    

    Not quite elegant so if anyone has a suggestion, let me know.

    //_


  2. In case of multiple applications running on different ports and different local IP addresses the recommended method is using Reverse Proxy

    Basically you configure your apache to forward requests to those services, i.e.:

    <VirtualHost *:443>
        ServerName sub.mydomain.io
        ProxyPass "/wordpress" "http://172.17.0.2:8080/"
        ProxyPass "/django" "http://172.17.0.2:8000/"
    
        ErrorLog /var/log/apache2/error.mydomain.io.com.log
        Include /etc/letsencrypt/options-ssl-apache.conf
        SSLCertificateFile /etc/letsencrypt/live/mydomain.io/fullchain.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/mydomain.io/privkey.pem
    </VirtualHost>
    

    If you have multpile external domain you can use Name Based Virtual hosts

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search