通过 docker 网络连接两个容器

Connect two containers through docker network

我的objective是连接两个不同的容器获取数据,也就是说:

为了连接两者,我已经创建了一个名为“minharede”的 docker 网络。

但是不工作

我的容器配置是:

Docker-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-编写文件容器B:

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

容器B的config.yml为:

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"

当我尝试在 Visual Code 上 运行 我的容器 B 进行测试时(它连接到 docker),我得到这个错误:

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

谁能帮帮我??谢谢大家!

(附图)

compose reference有这个例子:

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

它指出:

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

您需要在撰写文件的顶层指定网络定义,并且您需要在服务定义中指定命名网络。

但这还不是全部。正如@davidmaze 所建议的那样,在一个撰写文件而不是多个撰写文件中完成此操作会更容易。 Docker compose 将每个 compose 视为一个单独的“应用程序”,并且 compose 中的所有内容都“命名空间”到该应用程序。


为了获得您想要的内容,您需要在撰写文件之外托管您的命名网络。 docker network 命令是你必须进入的方向,但我认为关于如何实现这一点的整个教程超出了 SO 答案的范围。

为了维护对此的解决方案,每个开发人员工作站都必须持有和维护一个相同配置的命名网络,compose-apps 都可以加入。这是适得其反的——在 docker compose 中进行开发的目的是将整个开发环境保存在存储库本身中。

无论如何,关键组件是使用 docker network create <name> 在您的工作站上构建一个命名网络,然后通过 external 属性将其附加到您的撰写文件中。

https://docs.docker.com/compose/networking/#use-a-pre-existing-network(稍微向上滚动,docker 的文档站点在加载 #anchor 时错位了大约 150 像素):

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

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

您正在使用 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 

我已修复此警告,并且可以成功创建设置。

首先,我创建网络:

docker network create minharede

然后,我在 a.yaml 和 运行 docker compose -p a -f a.yaml up -d:

中创建了一个虚拟服务
# a.yaml
services:
  my-svc:
    image: traefik/whoami
networks:
  default:
    name: minharede
    external: true

最后,我在另一个文件中创建了另一个服务,以 curl 服务的网络别名 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

所以你想做的事情当然是可能的。您只是使用了错误的主机名。在我的示例中,您可以看到我尝试 curl 的服务的组合文件中的服务名称是 my-svc。这也是我在 curl 命令中用于主机名的内容。


您实际上可以通过不为 a 使用外部网络来简化此操作,但仍将 a's 默认网络引用为 b.

中的外部网络
# a.yaml
networks:
  default:
    name: minharede
# b.yaml
networks:
  default:
    name: minharede
    external: true

那么你只需要确保在b之前开始a

首先,在连接到 Docker 的 VSCode 调试期间,开发中的容器 (Cntainer B) 连接默认网络,在我的例子中是一个名为“bridge”的网络“。因此,我没有连接到与容器 OpenCTI 相同的网络,为了解决这个问题,我执行了相反的操作,我将容器 OpenCTI 连接到我的开发容器所连接的网络“桥”。 在那之后,我去检查我的容器 OpenCTI 中我想要从容器 B 获得连接的服务的 IP 地址,我将 url 从 http://opencti:8080 更改为 http://172.xx.x.x:8080(你只需将 xx 替换为正确的 IP 地址数),对我来说很好!!