Экспедирование контейнерных портов

У меня есть двоичный файл, который прослушивает порт 3000, однако Google Cloud Run хочет, чтобы я прослушивал порт, определенный $PORT, по умолчанию это 8080.

Есть ли способ привязать мой контейнер к 8080, а затем перенаправить входящие запросы на 3000? например, добавив короткий скрипт и одну строку к моему Dockerfile, мой контейнер будет прослушивать 8080 и пересылать на мой двоичный файл.


person Steren    schedule 30.04.2019    source источник
comment
Разве вы не можете изменить свое приложение по умолчанию на 3000, но если определен $ PORT, вместо этого используйте этот порт?   -  person codestation    schedule 30.04.2019
comment
@codestation В вопросе указано, что это двоичный файл, предположительно OP не может изменить порт.   -  person Dustin Ingram    schedule 01.05.2019
comment
@dustin-ingram правильный. Переменная среды PORT указана системой в Cloud Run. Решение действительно должно гарантировать, что контейнер будет принимать трафик при любом значении PORT, указанном службой; просто сейчас это всегда 8080, но это не стойко.   -  person DazWilkin    schedule 01.05.2019


Ответы (2)


Приведенный ниже код не тестировался, но общая идея такова:

  1. Используйте сценарий запуска на основе оболочки
  2. Включить iptables
  3. Маршрутизация трафика от srcPort к dstPort
  4. Выполнить исходный двоичный файл

В Dockerfile замените ENTRYPOINT сценарием запуска:

FROM debian:9 # or another container that has iptables available
RUN apt-get install iptables
EXPOSE 8080
ENTRYPOINT /bin/startup.sh /bin/original

А затем напишите сценарий запуска, который включает iptables и перенаправляет входящий трафик с 8080 на 3000 внутри контейнера:

#!/usr/bin/env bash
set -e

sed -i 's/#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/g' /etc/sysctl.conf
sysctl -p
systemctl start iptables

iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 8080 -j REDIRECT --to-port 3000
iptables -t nat -A PREROUTING -i eth0 -p udp --dport 8080 -j REDIRECT --to-port 3000


unshift 
exec "$@"
person sethvargo    schedule 30.04.2019
comment
К сожалению, сценарий не работает. (1) debian:9 не включает sysctl, но debian:8 включает; (2) Я думаю (!?) Вы не можете изменить net.ipv4.ip_forward в контейнере, если не запускаете контейнер как --privileged и не используете --sysctl=net.ipv4.ip_forward=1 (чего он не может в Cloud Run); (3) вы хотите обновить пакеты перед установкой с помощью sudo apt-get update && sudo apt-get -y install iptables. @steren - надеюсь, у вас есть FR для разрешения перенаправления портов | публикации в Cloud Run ;-) - person DazWilkin; 30.04.2019

Если вы можете установить запуск второго процесса и запускать его вместе с основным процессом, тогда установите и запустите socat, используя следующую команду:

socat tcp-listen:8080,fork,reuseaddr tcp-connect:localhost:3000

Таким образом, socat будет связываться с портом 8080 и отправлять весь трафик на порт 3000, где ваш двоичный файл прослушивает.

Вне Cloud Run: если вы не можете коснуться своего изображения или контейнера, вы все равно можете запустить socat в дополнительном контейнере, например:

version: '3.5'
services:
  proxy:
    image: alpine/socat:1.0.3
    command: tcp-listen:8080,fork,reuseaddr tcp-connect:myservice:3000
    networks:
      - mynet
networks:
  mynet:
    external: true

Где mynet - это сеть, в которой работает ваш двоичный файл, а myservice - имя службы вашего двоичного файла.

person codestation    schedule 30.04.2019
comment
Вы проверили и проверили это в Google Cloud Run? - person John Hanley; 01.05.2019
comment
@JohnHanley, нет, но первый вариант должен работать нормально (дополнительный процесс для перенаправления трафика), иначе что-то в Cloud Run не работает (в прошлом я успешно использовал socat с контейнерами докеров). Конечно, если все остальное терпит неудачу, OP может изменить двоичный файл в шестнадцатеричном формате, чтобы изменить номер порта (при условии, что двоичный файл не подписан / не запутан). - person codestation; 01.05.2019
comment
Я не думаю, что вторая часть вашего ответа возможна с Cloud Run. Хотя Cloud Run запускает контейнер, это не платформа контейнера Docker. Порт прослушивания (один порт) для всего контейнера контролируется Google. Нет доступа к сети Docker по имени и т. Д. Адрес другого контейнера будет неизвестен. Сколько контейнеров работает одновременно, неизвестно (в настоящее время). Cloud Run разработан как система HTTP-запросов / ответов, которая масштабируется в зависимости от количества запросов в секунду. - person John Hanley; 01.05.2019
comment
@ john-hanley правильно, что вы не можете (хотя это хорошее решение) запускать контейнер, похожий на `` sidecar '', в Cloud Run для проксирования трафика (это то, что Google должен учитывать особенно, поскольку это (а) будет достаточно распространенным проблема; (б) базовой моделью является Kubernetes Pod, и это общий шаблон с Kubernetes. - person DazWilkin; 01.05.2019
comment
Хотя запуск socat в одном и том же контейнере может решить проблему, а запуск некоторой формы прокси в контейнере может быть единственным решением, это противоречит хорошей практике запускать несколько процессов в одном контейнере. - person DazWilkin; 01.05.2019