'Trouble creating a FTP connection from within a docker container to an external host

So the setup is as followed: I have a host machine on which i run a docker container. From this i want to open a connection to a ftp server on the web and download a test file. The programm is written in go and works when executed directly on the host machine without the container.

The minimum example script looks as follows and I use the ftp package github.com/jlaffaye/ftp: (This should work out of the box as is - at least it does for me)

package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "strings"
    "time"

    "github.com/jlaffaye/ftp"
)

func main() {
    URL := "ftp://speedtest.tele2.net/1MB.zip"
    User := "anonymous"
    Password := "anonymous"

    urlElements := strings.Split(URL, "/")
    dialTarget := fmt.Sprintf("%s:%s", urlElements[2], "21")
    fmt.Println("Attempting FTP connection to ", dialTarget)           

    c, err := ftp.Dial(dialTarget, ftp.DialWithTimeout(5*time.Second)) 
    if err != nil {
        log.Fatalf("TCP dial failed: %v", err)
    }
    defer c.Quit()

    err = c.Login(User, Password)
    if err != nil {
        log.Fatalf("FTP login failed: %v", err)
    }
    defer c.Logout()

    data, err := c.Retr(strings.Join(urlElements[3:], "/"))
    if err != nil {
        log.Fatalf("Failed to get file: %v", err)
    }

    _, err = ioutil.ReadAll(data)
    if err != nil {
        log.Fatalf("Failed to read file: %v", err)
    }
    fmt.Println("success!")
}

Since this code part will be part of a larger container later on running this on the host network with --network=host in docker options is not possible. (Apart this did not work for some reason -> lead to timeouts or EOF errors on dial)

Solution I considered:

Open an ssh-bridge to the target machine. I tried this using the package github.com/elliotchance/sshtunnel which provides a (imo) comprehensive example of how to use it: See here for reference. The idea was to basically tunnel from the container through the host directly onto the target. However while the tunnel returned a connection success, the ftp client still failed with timeouts or EOF errors.

For this reason: Is there a good way to do this? If so which direction would be the best to go in? I am somewhat lost on this, especially since since connecting an samba client to a remote machine works without any issue from within the container for some reason.

Thx in advance for any leads - please let me know if i missed to provide any information/details.

For reference the docker file looks like this:

FROM golang:alpine AS BUILDER
# install certificates to enable usage for http
RUN apk update \
        && apk upgrade \
        && apk add --no-cache \
        ca-certificates \
        && update-ca-certificates 2>/dev/null || true
# all prerequsites should be done before this point.
WORKDIR /src

COPY . .

RUN go get -d -v
RUN CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=5 go build -o ./out/ftp-test .


FROM scratch

COPY --from=BUILDER /src/out/ftp-test /ftp-test
COPY --from=BUILDER /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
# Run the executable
ENTRYPOINT ["/ftp-test"]


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source