Docker составьте отображение порта, порт хоста! = Порт контейнера - PullRequest
2 голосов
/ 04 ноября 2019

Как мне заставить curl http://barfoo:8002 работать из контейнера foobar, не внося изменений в файл Docker?

У меня есть следующий составной файл:

version: '3'
services:
  foobar:
    build:
      context: ./foobar
    ports:
      - 8001:80
    depends_on:
      - barfoo
  barfoo:
    build:
      context: ./barfoo
    ports:
      - 8002:80

И я добавилследующее к моему файлу hosts на моем компьютере

127.0.0.1     foobar
127.0.0.1     barfoo

Теперь я запускаю этот проект с docker-compose up.

Когда я выполняю следующее на моем терминале, это логически работает без каких-либо проблем:curl http://barfoo:8002

Когда я делаю то же самое из Bash в контейнере foobar (docker-compose exec foobar /bin/bash), я получаю Failed to connect to barfoo port 8002: Connection refused, если я использую curl http://barfoo:80, это работает.

Причина, почемув том, что я хочу смоделировать производственную ситуацию, когда в производстве нет необходимости в порте, поскольку они используют другое имя хоста и оба могут напрямую использовать порт 80

Ответы [ 3 ]

1 голос
/ 04 ноября 2019

Когда вы выполняете curl http://barfoo:8002 со своего терминала, вы подключаетесь к локальному порту 8002 вашего компьютера, который пересылает порт 80 вашего контейнера.

Контейнер foobar, однако, попадает в порт контейнеранепосредственно, который прослушивает только порт 80.

Вы можете добиться того, что вы пытаетесь сделать, добавив другой контейнер в docker-compose.yaml, который будет действовать как обратный прокси-сервер перед контейнером barfoo.

Новый docker-compose будет выглядеть примерно так -

version: '3'
services:
  foobar:
    build:
      context: ./foobar
    ports:
      - 8001:80
    depends_on:
      - barfoo
  barfoo-host:
    build:
      context: ./barfoo
    ports:
      - 8002:80
  barfoo:
    image: custom-nginx:latest

И образ custom-nginx должен быть построен примерно так -

FROM nginx:1.17-alpine
COPY nginx.conf /etc/nginx/
EXPOSE 8002
CMD ["nginx", "-g", "daemon off;"]

Используя этокак файл nginx.conf -

user                            root;
worker_processes                auto;

error_log                       /var/log/nginx/error.log warn;

events {
    worker_connections          1024;
}

http {
    include                     /etc/nginx/mime.types;
    default_type                application/octet-stream;
    sendfile                    off;
    access_log                  off;
    keepalive_timeout           3000;
    server {
        listen                  8002;
        root                    /usr/share/nginx/html;
        server_name             barfoo;
        location / {
            proxy_pass http://barfoo-host;
        }
    }
}
1 голос
/ 04 ноября 2019

Пока что возможный обходной путь - переписать command в docker-compose.yml так, чтобы процесс в нем слушал порт 8002 вместо 80.

version: '3'
services:
  foobar:
    build:
      context: ./foobar
    ports:
      - 8001:80
    depends_on:
      - barfoo
  barfoo:
    build:
      context: ./barfoo
    ports:
      - 8002:8002
    command: 'some-service --port 8002'

Но я быбудьте более чем счастливы принять лучшее решение / ответ для этого.

0 голосов
/ 04 ноября 2019

Как заставить curl http://barfoo:8002 работать из контейнера foobar, не внося изменений в файл Docker?

Простое решение - сопоставить порт хоста 8002 сbarfoo порт 8002. Но это, вероятно, не то, что вам нужно.

barfoo - это имя службы, зарегистрированное во внутренней док-станции dns, доступное только службам (foobar) в той же сети док-станции, созданной при запускеdocker-compose up

8002 - это порт, сопоставленный с хостом докера.

Поэтому, когда вы запускаете curl http://barfoo:8002 из foobar контейнера, вы пытаетесь подключиться к службе barfoo к порту 8002. Однакоbarfoo прослушивает порт 80 внутри контейнера, а не 8002.

Другое решение:

Вы можете добавить network_mode: host к barfoo и foobar.

  foobar:
    build:
      context: ./foobar
    network_mode: host
    ports:
      - 8001:80
    depends_on:
      - barfoo
  barfoo:
    build:
      context: ./barfoo
    network_mode: host
    ports:
      - 8002:80

Но тогда foobar необходимо будет подключиться с помощью localhost:8002

Причина в том, что я хочу смоделировать ситуацию, подобную производственной, когда в производстве не нужен порт, так как онииспользуйте другое имя хоста, и оба могут использовать порт 80 напрямую

Если это действительно то, что вам нужно, лучшей альтернативой будет использование стека докеров.

А вашими сервисами будут docker swarm services:

Вы можете развернуть их, используя:

docker deploy --compose-file path_to_compose_file

Затем foobar подключится к barfoo, используя имя службы и порт barfoo:80

...