Тайм-аут чтения при попытке перечислить каталог FTP-сервера в контейнере Docker в Linux

#java #docker #ftp #apache-commons-net

#java #докер #ftp #apache-commons-net

Вопрос:

У меня есть служба, которая опрашивает FTP-сервер с помощью команды LIST. Я использую локальный пассивный режим, использую FTPSClient со следующей настройкой:

 ftpClient.setTrustManager(TrustManagerUtils.getAcceptAllTrustManager());
ftpClient.setDataTimeout(1800000); //30 minutes
ftpClient.setBufferSize(1281000000);
ftpClient.setControlKeepAliveTimeout(120);
 

Каталог FTP-сервера содержит около 700 000 файлов, поэтому серверу требуется время для ответа. На моем локальном компьютере при запуске необработанного Java-приложения для получения списка файлов требуется около 5 минут, в контейнере Docker в Windows он также работает без проблем в то же время, FileZilla — без проблем, но дольше. Однако, когда я запускаю контейнер на компьютере с Linux (Ubuntu 18.04.4 LTS), он не может получить данные, несмотря на то, что он может подключаться к серверу. По истечении указанного времени в настройках таймаута я получаю:

Вызвано: java.net.SocketTimeoutException: время ожидания чтения истекло в java.net.SocketInputStream.socketRead0 (собственный метод) ~ [?:?] в java.net.SocketInputStream.socketRead(SocketInputStream.java:115) ~ [?:?] в java.net.SocketInputStream.read(SocketInputStream.java: 168) ~[?:?] в java.net.SocketInputStream.read(SocketInputStream.java:140) ~[?:?] в sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java: 284) ~[?:?] в sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java: 326) ~[?:?] в sun.nio.cs.StreamDecoder.read(StreamDecoder.java: 178) ~ [?:?] в java.io.InputStreamReader.read(InputStreamReader.java:185) ~ [?:?]:?] в java.io.BufferedReader.fill(BufferedReader.java: 161) ~ [?:?] в java.io.BufferedReader.readLine(BufferedReader.java: 326) ~ [?:?] в java.io.BufferedReader.readLine(BufferedReader.java: 392)~[?:?] в org.apache.commons.net.ftp.FTPFileEntryParserImpl.readNextEntry(FTPFileEntryParserImpl.java:53) ~ [app.jar :?] в org.apache.commons.net.ftp.FTPListParseEngine.ReadStream(FTPListParseEngine.java:142) ~[app.jar :?]в org.apache.commons.net.ftp.FTPListParseEngine.readServerList(FTPListParseEngine.java: 118) ~ [app.jar :?] в орг.apache.commons.net.ftp.FTPClient.initiateListParsing(FTPClient.java:3450) ~[app.jar :?] в org.apache.commons.net.ftp.FTPClient.initiateListParsing(FTPClient.java:3371) ~[app.jar :?] в org.apache.commons.net .ftp.FTPClient.initiateListParsing (FTPClient.java:3308) ~[app.jar :?] в каталоге org.my.org.ftp.FtpOperator.list(FtpOperator.java:30) ~[app.jar :?]

Я предполагаю, что это не проблема с брандмауэром, потому что у меня есть похожий сервис, который опрашивает внешний сервер, и он работает должным образом. Обе службы используют локальный пассивный режим клиентской библиотеки Apache FTP.

Docker-создать файл:

 version: '2'
services:
  ingest:
    image: pl/ingest
    ports:
      - "8038:8038"

    volumes:
      - ./logs:/logs
      - ./processedFiles:/processedFiles

networks:                                
  default:                               
    driver: bridge                       
    driver_opts:                         
      com.docker.network.driver.mtu: 1500
 

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

1. @MartinPrikryl Я мог получить список с помощью FTP-клиента командной строки (не FTPS). Я запускаю это приложение без Docker, запустив JAR-файл, который использует FTPS (фактически команду gradle run), и он также может указывать каталог. Все это было на компьютере с Linux.

2. Обычная работа FTP в Java, клиент командной строки FTPS также работает. Обычный FTP также не работает в Docker.

3. Я имею в виду, что FTP-клиент командной строки работает в той же среде, в которой нет контейнера Docker, как обычного, так и FTPS. Java JAR (gradle run) работает в той же среде, что и контейнер Docker not, как обычный, так и FTPS. Ни обычный FTP, ни FTPS (в Java JAR) не работают в контейнере Docker.

Ответ №1:

Изменение сетевого режима с моста на хост в docker-compose сделало контейнер способным перечислять файлы по FTPS / FTP:

 version: '2'
services:
  ingest:
    image: pl/ingest
    ports:
      - "8038:8038"
    volumes:
      - ./logs:/logs
      - ./processedFiles:/processedFiles
    network_mode: "host"
 

Ответ №2:

С той же проблемой y обратился к этому ответу суперпользователя:

… ftp в активном режиме не подходит для контейнерных ftp-клиентов, поскольку сервер активно пытается инициировать подключение для передачи данных к ftp-клиенту, что невозможно для контейнера.

Существуют обходные пути для контейнеров, но программный способ решения этой проблемы может быть проще: просто переключитесь в пассивный режим после подключения.

 ftpClient.enterLocalPassiveMode()
 

И теперь это работает для меня.

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

1. У меня был включен локальный пассивный режим, и я все равно столкнулся с этой проблемой в контейнере Docker. Это зависит от FTP-сервера. Я подключался к FTP-серверам в локальном пассивном режиме, когда мне не нужно было устанавливать сетевой режим в конфигурации контейнера. В этом конкретном случае мне это было нужно.

2. Вы установили пассивный режим ПОСЛЕ подключения?

3. ДА. Как я уже упоминал, это работало для других FTP-серверов.