Leandro Lima
Leandro Lima

Reputation: 11

Connection error in apps when enabling https on example.com:8080 (Docker) with Apache

I will try to explain my situation but I apologize right now because I started studying the subject a little while ago and maybe I don't know how to give all the details correctly.

I recently got a script (backend and two Android apps) that works perfectly on http, but the apps have a payment gateway that works only with https. The author of the code created a doc that teaches you how to install the backend on the server in an automated way, just install Docker and run the backend with the link wget http://authorsite/docker-compose.yaml && docker-compose up -d.

The installation created the containers for the database and the backend files, and created a docker-compose.yaml file:

 version: '3'

 services:
   mysql:
     image: mysql
     command: --default-authentication-plugin=mysql_native_password
     volumes:
       - mysqlvol:/var/lib/mysql
     environment:
       MYSQL_ROOT_PASSWORD: defaultpassword

   redis:
     image: redis
     volumes:
       - redisvol:/data

   taxi:
     image: author/taxi
     restart: always
     depends_on:
       - "redis"
       - "mysql"
     volumes:
       - ./img:/app/public/img
       - ./config:/app/config
       - taxiassets:/app/public/assets
     links:
       - mysql
       - redis
     ports:
       - "8080:8080"

 volumes:
    redisvol:
    mysqlvol:
    taxiassets:

The backend page started working at http://example.com:8080 and I just needed to add the same url in the apps, in the config.kt file:

class Config {
    companion object {
        const val Backend = "http://example.com:8080/"
    }
}

Everything works fine, but as I mentioned, I need https for the payment gateway to work in apps, and also to get rid of http. The author does not give this information, so I researched and found some tutorials on reverse proxy, I already had Apache installed on my server (outside of Docker) and followed the tutorials related to Apache.

My .conf file (with Let's Encrypt) looked like this:

<IfModule mod_ssl.c>
<VirtualHost *:443>
    ServerAdmin webmaster@localhost
    ServerName example.com
    ServerAlias www.example.com
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
    
    ProxyPass / http://127.0.0.1:8080/
    ProxyPassReverse / http://127.0.0.1:8080/
    ProxyPreserveHost On
    ProxyPassReverseCookiePath / /

    <Proxy *>
        Order deny,allow
        Allow from all
        Allow from localhost
    </Proxy>

Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
</VirtualHost>
</IfModule>
<IfModule mod_ssl.c>
<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    ServerName example.com
    ServerAlias www.example.com
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
    
    ProxyPass / ws://127.0.0.1:8080/

</VirtualHost>
</IfModule>

I'm still learning and I sure must be doing something wrong, the backend still works at http://example.com:8080 but it doesn't work at https://example.com:8080, but even so the backend has now started work correctly at https://example.com. I can access the panel with https, but when trying to open apps with https://example.com, as in the example:

class Config {
    companion object {
        const val Backend = "https://example.com/"
    }
}

Or

class Config {
    companion object {
        const val Backend = "https://example.com:8080/"
    }
}

the apps started to show connection error and are not working properly.

I don't know if this is the correct approach, the backend works with the changes mentioned, before it was http://example.com:8080 and now I can access it at https://example.com, but this new url makes apps don't work the same way and have connection errors. If I keep the original url:

class Config {
    companion object {
        const val Backend = "http://example.com:8080/"
    }
}

Apps are back to working normally.

What am I doing wrong?

Upvotes: 1

Views: 581

Answers (1)

ErikMD
ErikMD

Reputation: 14753

Replying to your question would be two-fold:

1. TLS termination proxy

You might want to dockerize your TLS reverse proxy, which would increase maintainability easiness (no need for some manual installation/configuration outside of Docker), and isolation w.r.t. your host machine; see e.g. that other SO question for pointers.

2. Docker Networking

In your docker-compose.yml, when adding an extra service (dockerized TLS termination proxy), named e.g. proxy, in charge of handling the inbound requests on your host, you should address the following things:

  • Expose the 80 and 443 ports for this service:

    services:
      proxy:
        image: …
        ports:
          - '80:80'
          - '443:443'
        …
    

    Note: it is typical to also include the standard HTTP port 80, in order to implement a permanent redirection (HTTP 301) to HTTPS.

  • Remove the ports: ["8080:8080"] specification from your taxi service (otherwise http://example.com:8080 will still be accessible).

  • Don't use the links: property as it is a deprecated feature.

  • Instead, put the various containers that have to communicate each other in the same custom network:

    • Adding
        networks:
          - network-name
      
      in docker-compose services (taxi, mysql, redis), instead of
        links:
          - mysql
          - redis
      
    • Adding
      networks:
        network-name:
          driver: bridge
      
      at the end of your docker-compose.yml.
  • Specify URLs such as http://mysql:3306 or http://redis:6379 within the taxi service.
    Ideally, these URL should be set as docker-compose environment variables of your taxi service.

  • Similarly, specify the URL http://taxi:8080 in your proxy service (similarly to the last code snippet you mentioned in your question, which would then be const val Backend = "http://taxi:8080/") to access the taxi service from proxy.
    To this aim, you may also want to create yet another custom docker-compose network, common to (proxy, taxi) services.

  • Note that the URLs above start with http:, not https:, given they correspond to internal HTTP requests between containers, and the domain name in these URL is the docker-compose service name.

For more details on these docker-compose networking notions, see the official doc.

Finally, here is a sample component diagram that summarizes the various containers involved in the application you consider:

component-diagram

Upvotes: 1

Related Questions