FTP client not working inside Docker container

I am trying to get my app functioning properly in Docker, but am having trouble with it.

The app connects to a remote FTP server with PASV mode, and PUTs a file. Pretty simple and works fine without docker. Neither the FTP server nor the client are behind any NAT; but the client becomes NAT'd because I am using Docker bridged networking. (Using default bridge config http://pastie.org/10954592)

If I look at tshark on the FTP server when running the client app, it exchanges a lot of packets, so it is "connecting" to the server, but the app isn't receiving anything back. This makes me assume that when the the FTP server attempts to respond on that empirical port, it isn't being routed back to the Docker container from the host OS.

So, hopefully to summarize, is there any good way to have these pasv ports forwarded properly to the docker bridge? Constraint: I do not have control of the FTP server in production, so I can not simply hardcode a list of pasv ports for iptables.

Thanks for any ideas!


Solution 1:

PASV FTP works fine inside Docker containers.

It gets harder using Docker Swarm, but is possible with a single replica or in deploy mode:global with port mapping using mode:host.

Because PASV mode is stateful, subsequent requests need to be routed to the same node in the cluster.

Example stack using host mode

services:
  ftp:
    image: vendor/vsftpd
    ports:
      - { target: 20,    published: 20, mode: host }
      - { target: 21,    published: 21, mode: host }
      - { target: 21100, published: 21100, mode: host }
      - { target: 21101, published: 21101, mode: host }
      - { target: 21102, published: 21102, mode: host }
    deploy:
      mode: global