Назад | Перейти на главную страницу

Обратный прокси-сервер Nginx с именами переменных для контейнера докеров возвращает неправильные файлы

Я много читал и много пробовал, но в итоге ничего не вышло. Я надеюсь, что вы можете помочь мне.

Итак, вот моя установка:

У меня есть файл Docker-compose, содержащий контейнер phpmyadmin. Моя проблема не ограничивается phpmyadmin, это просто хороший пример. Ниже docker-файл (важные части). Как видите, я хочу, чтобы phpmyadmin был доступен по адресу https://www.example.com/phpmyadmin/. Думаю, моя установка была бы намного проще, если бы я использовал https://phpmyadmin.example.com/ (субдомен вместо суб-пути, но это не то, что я хочу.) Сам контейнер phpmyadmin работает отлично.

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

Затем у меня есть ВТОРОЙ файл для создания докеров, который запускает Nginx. Здесь ничего особенного:

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

В-третьих, у меня есть файл конфигурации Nginx для моего vHost. Я пытаюсь проксировать все запросы к / phpmyadmin / к контейнеру phpmyadmin и все остальное "/" к другому контейнеру, на котором запущен apache + php. Как вы можете видеть ниже, я выполняю прокси-переход в контейнер phpmyadmin. Когда я использую имя контейнера докеров, все работает proxy_pass http://k3633970_phpmyadmin/;(см. комментированную часть).

Но когда я использую такие переменные, как proxy_pass $target; больше не работает. (Я описываю связанную проблему как ссылку на будущее для меня и для других, поэтому пост немного длиннее). Что происходит, так это то, что загружается стартовая страница phpmyadmin, которая включает некоторые файлы JS / CSS, такие как «js / phpmyadmin.js» или «css / phpmyadmin.css». Веб-браузер загружает файлы, но обратный прокси-сервер Nginx доставляет не файлы CSS / JS, а снова стартовую страницу. Браузер отображает предупреждения о том, что он не может включать файлы CSS / JS из-за неправильного типа mime, потому что стартовая страница доставляется как «text / html». Это сначала привело меня к неправильной трассировке, что типы mime являются ложными, хотя на самом деле типы mime верны, но доставляются неправильные файлы.

Вы понимаете, что я имею в виду? Я пытаюсь объяснить это еще раз:

Я загружаю www.example.com/phpmyadmin -> возвращается стартовая страница html phpmyadmin с mime-типом text / html (что правильно). Эта стартовая страница включает www.example.com/phpmyadmin/js/phpmyadmin.js и www.example.com/phpmyadmin/css/phpmyadmin.css, но это то, что возвращается: www.example.com/phpmyadmin/js/phpmyadmin .js -> HTML-код phpmyadmin Начальная страница с типом mime возвращается текст / html. www.example.com/phpmyadmin/css/phpmyadmin.css -> html phpmyadmin Начальная страница с типом mime возвращается текст / html.

Это мой конфигурационный файл nginx.

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;
    }
}

Итак, причина в документации Nginx:

Если директива proxy_pass указана с URI, тогда, когда запрос передается на сервер, часть нормализованного URI запроса, соответствующая местоположению, заменяется URI, указанным в директиве.

Хорошо, понял. Но как я могу это решить сейчас?

Я пробовал все возможные комбинации с set $target http://k3633970_phpmyadmin$uri; set $target http://k3633970_phpmyadmin$request_uri; set $target http://k3633970_phpmyadmin/$uri; и т.д. Рабочей комбинации не нашел.

Пожалуйста, помогите, я застрял - спасибо!

Последнее замечание: Зачем мне нужны переменные в проходе прокси? Вся причина в том, что у меня есть около 10 файлов docker-compose с 10 стеками wordpress по 3 контейнера в каждом (apache + php / mariabdb / phpmyadmin) и один обратный прокси-сервер nginx. Если я использую имена хостов docker, все 10 стеков docker-compose должен быть запущен прежде чем я запустил nginx. Это невозможно, иногда один-два стека отключаются для тестирования / обслуживания. Подход с переменными позволяет запускать nginx даже в том случае, если запущено и работает только 8 из 10 стеков докеров.

Спасибо!

Ваша служба nginx должна разрешить IP-адрес контейнера phpmyadmin, используя «имя службы», а не «имя контейнера».

Кроме того, вы должны сохранить путь / phpmyadmin в URL-адресе, когда вы проксируете запрос в контейнер phpmyadmin, и если вы поместите конечную косую черту, она удалит эту часть, поэтому вы НЕ должны ставить конечную косую черту. Или вы также можете восстановить полный URL-адрес с помощью синтаксического анализа регулярного выражения.

Так должно работать примерно так:

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 теперь это рабочий конфиг:

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;
}

Спасибо!