Соедините два контейнера через сеть докеров

Моя цель - подключить два разных контейнера для получения данных, другими словами:

  • У меня есть экземпляр OpenCTI, работающий в моем докере, и я могу получить к нему доступ через браузер (http://localhost:8080).
  • Следовательно, я разрабатываю еще один для получения данных из OpenCTI.

Чтобы соединить оба, я уже создал сеть докеров под названием «minharede».

Однако не работает.

Конфигурация моих контейнеров:

Docker-compose файл OpenCTI:

version: '3'
services:
  redis:
    image: redis:6.2.6
    restart: always
    volumes:
      - redisdata:/data
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.17.1
    volumes:
      - esdata:/usr/share/elasticsearch/data
    environment:
      - discovery.type=single-node
      - xpack.ml.enabled=false
    restart: always
    ulimits:
      memlock:
        soft: -1
        hard: -1
      nofile:
        soft: 65536
        hard: 65536
  minio:
    image: minio/minio:RELEASE.2022-02-26T02-54-46Z
    volumes:
      - s3data:/data
    ports:
      - "9800:9800"
    environment:
      MINIO_ROOT_USER: ${MINIO_ROOT_USER}
      MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}    
    command: server /data
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
      interval: 30s
      timeout: 20s
      retries: 3
    restart: always
  rabbitmq:
    image: rabbitmq:3.9-management
    environment:
      - RABBITMQ_DEFAULT_USER=${RABBITMQ_DEFAULT_USER}
      - RABBITMQ_DEFAULT_PASS=${RABBITMQ_DEFAULT_PASS}
    volumes:
      - amqpdata:/var/lib/rabbitmq
    restart: always
  opencti:
    image: opencti/platform:5.2.1          
    environment:
      - NODE_OPTIONS=--max-old-space-size=8096
      - APP__PORT=8080
      - APP__ADMIN__EMAIL=${OPENCTI_ADMIN_EMAIL}
      - APP__ADMIN__PASSWORD=${OPENCTI_ADMIN_PASSWORD}
      - APP__ADMIN__TOKEN=${OPENCTI_ADMIN_TOKEN}
      - APP__APP_LOGS__LOGS_LEVEL=error
      - REDIS__HOSTNAME=redis
      - REDIS__PORT=6379
      - ELASTICSEARCH__URL=http://elasticsearch:9200
      - MINIO__ENDPOINT=minio
      - MINIO__PORT=9000
      - MINIO__USE_SSL=false
      - MINIO__ACCESS_KEY=${MINIO_ROOT_USER}
      - MINIO__SECRET_KEY=${MINIO_ROOT_PASSWORD}
      - RABBITMQ__HOSTNAME=rabbitmq
      - RABBITMQ__PORT=5672
      - RABBITMQ__PORT_MANAGEMENT=15672
      - RABBITMQ__MANAGEMENT_SSL=false
      - RABBITMQ__USERNAME=${RABBITMQ_DEFAULT_USER}
      - RABBITMQ__PASSWORD=${RABBITMQ_DEFAULT_PASS}
      - SMTP__HOSTNAME=${SMTP_HOSTNAME}
      - SMTP__PORT=25
      - PROVIDERS__LOCAL__STRATEGY=LocalStrategy
    ports:
      - "8080:8080"
    depends_on:
      - redis
      - elasticsearch
      - minio
      - rabbitmq
    restart: always
  worker:
    image: opencti/worker:5.2.1
    environment:
      - OPENCTI_URL=http://opencti:8080
      - OPENCTI_TOKEN=${OPENCTI_ADMIN_TOKEN}
      - WORKER_LOG_LEVEL=info
    depends_on:
      - opencti
    deploy:
      mode: replicated
      replicas: 3
    restart: always
  connector-history:
    image: opencti/connector-history:5.2.1
    environment:
      - OPENCTI_URL=http://opencti:8080
      - OPENCTI_TOKEN=${OPENCTI_ADMIN_TOKEN}
      - CONNECTOR_ID=${CONNECTOR_HISTORY_ID} # Valid UUIDv4
      - CONNECTOR_TYPE=STREAM
      - CONNECTOR_NAME=History
      - CONNECTOR_SCOPE=history
      - CONNECTOR_CONFIDENCE_LEVEL=15 # From 0 (Unknown) to 100 (Fully trusted)
      - CONNECTOR_LOG_LEVEL=info
    restart: always
    depends_on:
      - opencti
  connector-export-file-stix:
    image: opencti/connector-export-file-stix:5.2.1
    environment:
      - OPENCTI_URL=http://opencti:8080
      - OPENCTI_TOKEN=${OPENCTI_ADMIN_TOKEN}
      - CONNECTOR_ID=${CONNECTOR_EXPORT_FILE_STIX_ID} # Valid UUIDv4
      - CONNECTOR_TYPE=INTERNAL_EXPORT_FILE
      - CONNECTOR_NAME=ExportFileStix2
      - CONNECTOR_SCOPE=application/json
      - CONNECTOR_CONFIDENCE_LEVEL=15 # From 0 (Unknown) to 100 (Fully trusted)
      - CONNECTOR_LOG_LEVEL=info
    restart: always
    depends_on:
      - opencti
  connector-export-file-csv:
    image: opencti/connector-export-file-csv:5.2.1
    environment:
      - OPENCTI_URL=http://opencti:8080
      - OPENCTI_TOKEN=${OPENCTI_ADMIN_TOKEN}
      - CONNECTOR_ID=${CONNECTOR_EXPORT_FILE_CSV_ID} # Valid UUIDv4
      - CONNECTOR_TYPE=INTERNAL_EXPORT_FILE
      - CONNECTOR_NAME=ExportFileCsv
      - CONNECTOR_SCOPE=text/csv
      - CONNECTOR_CONFIDENCE_LEVEL=15 # From 0 (Unknown) to 100 (Fully trusted)
      - CONNECTOR_LOG_LEVEL=info
    restart: always
    depends_on:
      - opencti
  connector-export-file-txt:
    image: opencti/connector-export-file-txt:5.2.1
    environment:
      - OPENCTI_URL=http://opencti:8080
      - OPENCTI_TOKEN=${OPENCTI_ADMIN_TOKEN}
      - CONNECTOR_ID=${CONNECTOR_EXPORT_FILE_TXT_ID} # Valid UUIDv4
      - CONNECTOR_TYPE=INTERNAL_EXPORT_FILE
      - CONNECTOR_NAME=ExportFileTxt
      - CONNECTOR_SCOPE=text/plain
      - CONNECTOR_CONFIDENCE_LEVEL=15 # From 0 (Unknown) to 100 (Fully trusted)
      - CONNECTOR_LOG_LEVEL=info
    restart: always
    depends_on:
      - opencti
  connector-import-file-stix:
    image: opencti/connector-import-file-stix:5.2.1
    environment:
      - OPENCTI_URL=http://opencti:8080
      - OPENCTI_TOKEN=${OPENCTI_ADMIN_TOKEN}
      - CONNECTOR_ID=${CONNECTOR_IMPORT_FILE_STIX_ID} # Valid UUIDv4
      - CONNECTOR_TYPE=INTERNAL_IMPORT_FILE
      - CONNECTOR_NAME=ImportFileStix
      - CONNECTOR_VALIDATE_BEFORE_IMPORT=true # Validate any bundle before import
      - CONNECTOR_SCOPE=application/json,text/xml
      - CONNECTOR_AUTO=true # Enable/disable auto-import of file
      - CONNECTOR_CONFIDENCE_LEVEL=15 # From 0 (Unknown) to 100 (Fully trusted)
      - CONNECTOR_LOG_LEVEL=info
    restart: always
    depends_on:
      - opencti
  connector-import-document:
    image: opencti/connector-import-document:5.2.1
    environment:
      - OPENCTI_URL=http://opencti:8080
      - OPENCTI_TOKEN=${OPENCTI_ADMIN_TOKEN}
      - CONNECTOR_ID=${CONNECTOR_IMPORT_DOCUMENT_ID} # Valid UUIDv4
      - CONNECTOR_TYPE=INTERNAL_IMPORT_FILE
      - CONNECTOR_NAME=ImportDocument
      - CONNECTOR_VALIDATE_BEFORE_IMPORT=true # Validate any bundle before import
      - CONNECTOR_SCOPE=application/pdf,text/plain,text/html
      - CONNECTOR_AUTO=true # Enable/disable auto-import of file
      - CONNECTOR_ONLY_CONTEXTUAL=false # Only extract data related to an entity (a report, a threat actor, etc.)
      - CONNECTOR_CONFIDENCE_LEVEL=15 # From 0 (Unknown) to 100 (Fully trusted)
      - CONNECTOR_LOG_LEVEL=info
      - IMPORT_DOCUMENT_CREATE_INDICATOR=true
    restart: always
    depends_on:
      - opencti

networks: 
  default: 
    external: 
      name: minharede #network created for the purpose

volumes:
  esdata:
  s3data:
  redisdata:
  amqpdata:
    

Файловый контейнер Docker-Compose B:

    version: '3.4'
    
    services:
      teste:
        image: teste
        build:
          context: .
          dockerfile: ./Dockerfile
    networks: 
      default: 
        external: 
          name: minharede  #docker network created for the purpose

config.yml контейнера B:

opencti:
  url: "http://localhost:8080"
  token: "xxxxxxxxxxxxxxxxxxxxxxxxxxx" #is hidden to post here

connector:
  id: "245b2de5-b85e-4236-bedd-97540b133ea2"
  type: "INTERNAL_ENRICHMENT"
  name: "osthreatenrichment"
  scope: "IPv4-Addr, IPv6-Addr, Domain-Name"
  auto: true
  confidence_level: 70 #From 0 (unknown) to 100 (Fully trusted)
  log_level: "info"

Когда я пытаюсь запустить свой контейнер B в Visual Code, чтобы проверить его (он подключен к докеру), я получаю эту ошибку:

Exception has occurred: ValueError OpenCTI API is not reachable. Waiting for OpenCTI API to start or check your configuration...

Кто-нибудь может мне помочь?? Спасибо вам, ребята!

(изображение прилагается) Соедините два контейнера через сеть докеров

Пожалуйста, покажите содержимое вашего config.yml. В docker-compose вы получаете доступ к другим контейнерам в сети по имени их службы (не localhost)

atultw 21.03.2022 18:07

Какое имя хоста вы пытаетесь использовать для подключения к другому контейнеру? Будет проще, если вы сможете запускать оба контейнера в одном и том же файле Compose. Есть ли смысл их разделять?

David Maze 21.03.2022 19:22

@atultw я добавил конфигурацию confi.yml в описание проблемы. Видишь? Итак, я должен заменить URL?

MdaCosta 21.03.2022 19:45

@DavidMaze Я не запускаю контейнер в том же файле Compose, потому что контейнер OpenCTI уже реализован в докере, и я разрабатываю контейнер B в Visual Code, который подключен к Docker, чтобы протестировать мой код. Идея состоит в том, чтобы интегрировать окончательное решение в композицию, но не сейчас.

MdaCosta 21.03.2022 19:48
Развертывание модели машинного обучения с помощью Flask - Angular в Kubernetes
Развертывание модели машинного обучения с помощью Flask - Angular в Kubernetes
Kubernetes - это портативная, расширяемая платформа с открытым исходным кодом для управления контейнерными рабочими нагрузками и сервисами, которая...
Как создать PHP Image с нуля
Как создать PHP Image с нуля
Сегодня мы создадим PHP Image from Scratch для того, чтобы легко развернуть базовые PHP-приложения. Пожалуйста, имейте в виду, что это разработка для...
1
4
135
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

составить ссылку имеет этот пример:

services:
  some-service:
    networks:
     - some-network
     - other-network

И в нем говорится:

Networks to join, referencing entries under the top-level networks key.

Вам нужно указать определение сети на верхнем уровне вашего файла компоновки, а в определении службы вам нужно указать именованную сеть.

Однако это не вся история. Как предполагает @davidmaze, это будет проще сделать в одном файле компоновки, а не в нескольких. Docker compose рассматривает каждую композицию как отдельное «приложение», и все внутри композиции «присваивается пространство имен» этому приложению.


Чтобы получить то, что вы хотите, вам нужно разместить вашу именованную сеть за пределами файла компоновки. Команда docker network - это направление, в котором вам нужно двигаться, но я думаю, что целый учебник о том, как этого добиться, выходит за рамки ответа SO.

Чтобы поддерживать решение этой проблемы, каждая рабочая станция разработчика должна содержать и поддерживать идентично сконфигурированную именованную сеть, к которой могут присоединиться оба составных приложения. Это контрпродуктивно — смысл разработки в составе docker состоит в том, чтобы удерживать всю среду разработки в самом репозитории.

В любом случае, ключевым компонентом является создание именованной сети на вашей рабочей станции с помощью docker network create <name>, а затем подключение к ней в вашем файле компоновки с помощью атрибута external.

https://docs.docker.com/compose/networking/#use-a-pre-existing-network (прокрутите немного вверх, сайт документации для докера смещается примерно на 150 пикселей при загрузке #anchor):

If you want your containers to join a pre-existing network, use the external option:

services:
  # ...
networks:
  default:
    external:
      name: my-pre-existing-network

Это не совсем так. Каждая служба в файле компоновки будет присоединена к сети по умолчанию. Поэтому вам не нужно указывать его явно под сетевым ключом данной службы.

The Fool 21.03.2022 20:06

@TheFool По умолчанию да, каждая служба будет присоединена к сети по умолчанию. Вопрос в том, как заставить их присоединиться к альтернативной сети. Ответ таков: сеть должна быть указана как на верхнем уровне, так и на уровне обслуживания.

voxobscuro 21.03.2022 20:10

Вы используете http://localhost:8080 в качестве цели, что не может работать, так как каждый контейнер свой localhost.

opencti:
  url: "http://localhost:8080" # this should be the other services name

Измените его на сетевой псевдоним целевого контейнера (создайте имя службы). В этом случае opencti.


Когда я копирую вашу настройку, я получаю предупреждение об устаревании

WARN[0000] network default: network.external.name is deprecated in favor of network.name 

Я исправил это предупреждение и смог успешно создать файл setup.

Сначала я создаю сеть:

docker network create minharede

Затем я создаю фиктивный сервис в .yaml и запускаю docker compose -p a -f a.yaml up -d:

# a.yaml
services:
  my-svc:
    image: traefik/whoami
networks:
  default:
    name: minharede
    external: true

Наконец, я создаю еще одну службу в другом файле для скручивания сетевого псевдонима whoami службы.

# b.yaml
services:
  curl:
    image: curlimages/curl
    command: -s my-svc
networks:
  default:
    name: minharede
    external: true

Когда я запускаю docker compose -p b -f b.yaml up, я вижу следующий вывод.

Attaching to curl_1
curl_1  | Hostname: d63e37dd5363
curl_1  | IP: 127.0.0.1
curl_1  | IP: 172.22.0.2
curl_1  | RemoteAddr: 172.22.0.3:38960
curl_1  | GET / HTTP/1.1
curl_1  | Host: my-svc
curl_1  | User-Agent: curl/7.82.0-DEV
curl_1  | Accept: */*
curl_1  | 
curl_1 exited with code 0

Так что то, что вы пытаетесь сделать, безусловно, возможно. Вы просто используете неправильное имя хоста. В моем примере вы можете увидеть имя службы в файле компоновки службы, которую я пытаюсь свернуть, — my-svc. Это также то, что я использую для имени хоста в команде curl.


На самом деле вы можете упростить это, не используя внешнюю сеть для a, но по-прежнему ссылаясь на a's сеть по умолчанию как на внешнюю в b.

# a.yaml
networks:
  default:
    name: minharede
# b.yaml
networks:
  default:
    name: minharede
    external: true

Тогда вам нужно только убедиться, что вы начинаете a до b.

Я пытаюсь добраться до образа «платформа» контейнера openCTI. Вы можете увидеть изображение по ссылке: ![image.png](postimg.cc/CzVB5vVK) . Я изменил ссылку в соответствии с именем хоста на http://plataforma:8080 и все еще не работает, API недоступен.

MdaCosta 21.03.2022 21:55

@MdaCosta, вы можете показать сервис в файле компоновки? У вас есть ... там. Хоть покажи название сервиса. В противном случае трудно проверить, что вы делаете. То, как вы это формулируете, звучит так, будто вы пытаетесь использовать имя изображения, а не имя службы. В моем примере это одно и то же, это может сбивать с толку. Теперь я изменил это и назвал сервис my-svc.

The Fool 21.03.2022 22:15

Я имею в виду, пожалуйста, обновите свой вопрос и покажите имя службы для openCTI.

The Fool 21.03.2022 22:21

Я уже обновил вопрос с файлом компоновки Docker контейнера OpenCTI. Можете ли вы проверить это, пожалуйста?

MdaCosta 22.03.2022 09:18

@MdaCosta, используйте opencti в качестве имени хоста.

The Fool 22.03.2022 09:29

Та же ошибка, API недоступен :(

MdaCosta 22.03.2022 09:40

@MdaCosta, ты тоже используешь правильный порт?

The Fool 22.03.2022 09:45

Я изменил адрес отhttp://localhost:8080кhttp://opencti:8080 . Это правильно ?

MdaCosta 22.03.2022 12:13

@MdaCosta, да, это правильно. Вы также можете увидеть это, например, на рабочем сервисе. Он использует тот же URL. Если, возможно, openctpi не прослушивает более одного порта. Может апи не рабочий порт. Вы можете запустить свой контейнер и попробовать curl или nslookup или что-то подобное, чтобы увидеть, можете ли вы хотя бы разрешить dns.

The Fool 22.03.2022 12:17

Этот парень решил, как описано здесь github.com/OpenCTI-платформа/opencti/issues/1061, однако, предположительно, я делаю то же самое.

MdaCosta 22.03.2022 12:26

@MdaCosta, вы уже пытались использовать новый синтаксис для внешней сети, как показано в моем ответе? В своем посте вы все еще используете устаревшую форму.

The Fool 22.03.2022 12:30

Вы имеете в виду примерно так: ![изображение.png](postimg.cc/BLnC2zgh)

MdaCosta 22.03.2022 13:18

@MdaCosta, да вот так.

The Fool 22.03.2022 13:21

Да, я пробовал. Посмотрите на это: ![image.png](postimg.cc/0zcFMjLm) . Контейнер, который я тестирую, из Visual Code предположительно работает, как вы можете видеть на изображении. Однако, когда я выполняю docker inspect minharede, у меня есть только изображения контейнера OpenCTI, как вы можете видеть здесь: ![image.png](postimg.cc/Vd6m7ymj) . Как это возможно? Изучив сети, я обнаружил, что контейнер B подключен к сетевому «мосту», как вы можете видеть на этом изображении ![изображение.png](postimg.cc/SJJXjSDP) . Не знаю как, я настроил на сеть "минхареде"

MdaCosta 22.03.2022 14:57
Ответ принят как подходящий

Прежде всего, во время отладки в VSCode, который подключен к Docker, контейнер в разработке (Cntainer B) подключается к сети по умолчанию, в моем случае это была сеть под названием «мост». Следовательно, у меня не было подключения к той же сети, что и контейнер OpenCTI, и чтобы решить эту проблему, я выполнил обратное: я подключил контейнер OpenCTI к сетевому «мосту», к которому подключен мой контейнер в разработке. После этого я пошел проверить IP-адрес службы в моем контейнере OpenCTI, который я хотел получить соединение из контейнера B, и я изменил URL-адрес с http://opencti:8080 на http://172.xx.x.x:8080 (вам нужно только заменить xx на правильные цифры IP адрес) и отлично работал для меня!!

Другие вопросы по теме