Создание сети, которая позволяет обмениваться данными между контейнерами, но без доступа в Интернет

#docker #testcontainers

#docker #тестовые контейнеры

Вопрос:

Как я могу создать сеть docker, используя testcontainers которую:

  • позволяет всем контейнерам в сети взаимодействовать друг с другом
  • позволяет контейнерам сопоставлять порты с хостом
  • но не позволяет контейнерам иметь доступ к Интернету

Я пытался сделать это с помощью internal сети:

 private Network generateInternalNetwork() {
     // Consumer which operates on the final CreateNetworkCmd which will be run to
     // make sure the 'internal' flag is set.
     Consumer<CreateNetworkCmd> cmdModifier = (createNetworkCmd) -> {
         createNetworkCmd.withInternal(true);
     };

     return Network.builder()
             .createNetworkCmdModifier(cmdModifier)
             .build();
}
  

Однако, когда я запускаю это, я не могу сопоставить свой порт. Генерируется исключение:

Caused by: java.lang.IllegalArgumentException: Requested port (8024) is not mapped

Если я запускаю его без withInternal(true) него, он работает нормально, но, конечно, у контейнеров есть доступ в Интернет.

Ответ №1:

Я думаю, вы можете получить то, что хотите, (а) создав обычные сети, а затем (б) добавив DROP правило в свою DOCKER-USER цепочку брандмауэров:

 iptables -I DOCKER-USER -j DROP
  

В моем быстром эксперименте только что это позволило мне сопоставить порты из контейнеров, но не позволило контейнерам получить доступ к Интернету (поскольку эта цепочка вызывается из FORWARD цепочки, она не позволяет контейнерам перенаправлять трафик через хост во внешний Интернет).

Комментарии:

1. мне любопытно, есть ли способ сделать это на уровне docker и не задействовать ОС.

2. как говорит @Joe — вы знаете, как я могу сделать это на уровне docker (используя testcontainers, если это возможно).

Ответ №2:

Потратив несколько дней на попытки разных вещей, я придумал способ взлома решения, которое работает:

     /**
     * Set an invalid DNS for the given container.
     * This is done as a workaround so that the container cannot access
     * the internet.
     */
    void setInvalidDns() {
        GenericContainer<?> container = getContainer();
        Consumer<CreateContainerCmd> modifier = (cmd) -> {
                // Amend the config with the garbage DNS.
                String invalidDns = "255.255.255.255";
                HostConfig hostConfig = cmd.getHostConfig();
                hostConfig.withDns(invalidDns);
                cmd.withHostConfig(hostConfig);
        };

        container.withCreateContainerCmdModifier(modifier);
    }
  

Это устанавливает DNS контейнера на недопустимый IP-адрес, а затем, когда вы пытаетесь выполнить HTTP-запрос в контейнере, он выдает java.net.ConnectException .