2

I read a lot and tried a lot, but in the end, nothing worked. I hope, you can help me.

So here is my setup:

I have a Docker-compose file which contains a phpmyadmin container. My problem is not limited to phpmyadmin, this is just a good example. Below the docker-file (important parts). As you can see, I want phpmyadmin to be available at https://www.example.com/phpmyadmin/. I think my setup would be much easier, if I used https://phpmyadmin.example.com/ (a subdomain instead of a sub path, but this is not what I want.) The phpmyadmin container itself works perfectly well.

phpmyadmin:
  image: phpmyadmin/phpmyadmin:latest
  container_name: k3633970_phpmyadmin
  restart: always
  environment:
    MYSQL_ROOT_PASSWORD: xxx
    PMA_HOST: xxx
    PMA_ABSOLUTE_URI: https://www.example.com/phpmyadmin/
  networks:
   - frontproxy_default
   - backend

Then, I have a SECOND docker-compose file which starts an Nginx. Nothing fancy here:

nginx:
  image: nginx:alpine
  restart: unless-stopped
  volumes:
    - ./data/nginx:/etc/nginx/conf.d
  ports:
    - "80:80"
    - "443:443"
  networks:
    - frontproxy_default

Third, I have a Nginx config file for my vHost. I try to proxy all requests to /phpmyadmin/ to the phpmyadmin container and everything else "/" to another container running apache+php. As you can see below, I do a proxy pass to the phpmyadmin container. When I use a docker container name, everything works proxy_pass http://k3633970_phpmyadmin/;(see the commented part).

But when I use variables like proxy_pass $target; it does not work any more. (I am describing the related problem as future reference for me and for others, so the post is a little bit longer). What happens is, the start page of phpmyadmin is loaded which includes some JS/CSS files like "js/phpmyadmin.js" or "css/phpmyadmin.css". The web browser loades the files, but the Nginx-reverse proxy does not deliver the CSS/JS files but the start page again. The browser displays warnings that it cannot include the CSS/JS files because of the wrong mime type, because the start page is delivered as "text/html". This lead me to the wrong trace first, that the mime types are false, when in fact the mime types are correct, but the wrong files are delivered.

Do you understand what I mean? I try to explain it again:

I am loading www.example.com/phpmyadmin --> the phpmyadmin html start page with mime type text/html is returned (which is correct). This start page includes includes www.example.com/phpmyadmin/js/phpmyadmin.js and www.example.com/phpmyadmin/css/phpmyadmin.css but this is what is returned: www.example.com/phpmyadmin/js/phpmyadmin.js --> the phpmyadmin html start page with mime type text/html is returned. www.example.com/phpmyadmin/css/phpmyadmin.css --> the phpmyadmin html start page with mime type text/html is returned.

This is my nginx config file.

server {
    listen 443 ssl;
    server_name www.example.com;
    server_tokens off;
    ssl_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;


   location /phpmyadmin/ {
        resolver 127.0.0.11 valid=30s;
        set $target http://k3633970_phpmyadmin/; #Notice the trailing slash!
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_pass $target;
    }

# This works, without variables, but this is not what I want
#   location /phpmyadmin/ {
#        resolver 127.0.0.11 valid=30s;
#        set $upstreamx k3633970_phpmyadmin;
#        proxy_set_header Host $host;
#        proxy_set_header X-Real-IP $remote_addr;
#        proxy_pass http://k3633970_phpmyadmin/;
#         gzip  on;
#    }

    location / {
        resolver 127.0.0.11 valid=30s;
        set $upstream k3633970_vhost_1000303;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_pass http://$upstream:80;
    }
}

So the reason is, from the Nginx docs:

If the proxy_pass directive is specified with a URI, then when a request is passed to the server, the part of a normalized request URI matching the location is replaced by a URI specified in the directive.

Okay, understood. But how can I solve that now?

I tried every combination I can think of with set $target http://k3633970_phpmyadmin$uri; set $target http://k3633970_phpmyadmin$request_uri; set $target http://k3633970_phpmyadmin/$uri; etc. I did not find a working combination.

Please help, I am stuck - thank you!

Last note: Why do I need variables in the proxy pass? The whole reason is: I have like 10 docker-compose files with 10 wordpress stacks with 3 containers each (apache+php / mariabdb / phpmyadmin) and one nginx reverse proxy. If I use the docker hostnames, all 10 docker-compose stacks must be up and running before I start nginx. This is not possible, sometimes one-two stacks are down for testing/maintenance. The approach with variables allows to start nginx also if only 8 of 10 docker stacks are up and running.

Thank you!

schube
  • 163
  • 2
  • 9

2 Answers2

1

Your nginx service must resolve the phpmyadmin container ip by using the "service name", not the "container name".

Also, you must keep the /phpmyadmin path in the URL when you proxy the request to the phpmyadmin container, and if you put a trailing slash, it removes that part, so you must NOT put a trailing slash. Or you can also rebuild the full URL with regex parsing.

So something like this should work:

location ~* ^/phpmyadmin/(.*)$ {
  set $query $1;
  set $phpmyadmin phpmyadmin; # Service name in docker-compose file
  proxy_pass http://$phpmyadmin/phpmyadmin/$query$is_args$args; # Rebuild the URL
}
Jonathan Rioux
  • 1,878
  • 6
  • 33
  • 57
  • Thank you for your reply, it works now, that is the solution: location ~* ^/phpmyadmin/(.*)$ { resolver 127.0.0.11 valid=30s; set $query $1; set $target http://k3633970_phpmyadmin/$query$is_args$args; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_pass $target; } – schube Dec 27 '19 at 19:50
  • You wrote: "Also, you must keep the /phpmyadmin path in the URL when you proxy the request to the phpmyadmin container". I don't think so, the container has phpmyadmin installed at "/" and not at "/phpmyadmin". – schube Dec 27 '19 at 19:55
  • You also wrote "Your nginx service must resolve the phpmyadmin container ip by using the "service name", not the "container name"." This is the service name. At least, that is the name, that `docker ps` shows in the `NAMES`-column. – schube Dec 27 '19 at 19:56
  • You've set this envvar for the phpmyadmin service: PMA_ABSOLUTE_URI: https://www.example.com/phpmyadmin/ – Jonathan Rioux Dec 30 '19 at 15:10
  • Just for clarification: The envvar is used for proper absolute URLs in phpmyadmin I guess and from the outside world example.com/phpmyadmin is correct, but the phpmyadmin container self serves phpmyadmin from "/" (and not from /phpmyadmin). Thanks – schube Jan 01 '20 at 08:44
0

With the help of @jonathan-rioux this is the working config now:

location ~* ^/phpmyadmin/(.*)$ {
    resolver 127.0.0.11 valid=30s;
    set $query $1;
    set $target http://k3633970_phpmyadmin/$query$is_args$args;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_pass $target;
}

Thank you!

schube
  • 163
  • 2
  • 9