Home  >  Q&A  >  body text

Solution to PHP FTP connection problem in containerized environment

<p>I'm trying to containerize my PHP script. </p><p>But for some reason it cannot connect to my FTP server when running in a container. </p><p>Run the script on my local machine without any problems. </p><p><strong>Dockerfile:</strong></p><pre class="brush:php;toolbar:false;">FROM php:8.1-cli EXPOSE 8080 COPY ./var/www/html/ WORKDIR /var/www/html ENTRYPOINT php -f serve.php</pre><p><strong>PHP script:</strong></p><pre class="brush:php;toolbar:false;">$ connection = ftp_connect(FTP_HOST, 21, 90); ftp_pasv($connection, true); if(ftp_login($connection, FTP_USERNAME, FTP_PASSWORD)) { $stream = fopen('data://text/plain,','r'); ftp_fput($connection, $filename, $stream); } ftp_close($connection);</pre><p>After 90 seconds, it will give the following warning: </p><p><em>ftp_fput(): Connection timed out in /var/ www/html/ftp.php on line 16</em></p><p>I tried going into the container and installing the FTP client. </p><p>It gives me a similar timeout error - I can connect to the host, but running any command causes a pause. </p><p>I also tried running the container on a VPS to eliminate any local firewall/network issues. </p><p>But the problem still exists. </p><p>If you need further information to resolve the issue, please let me know. </p>
P粉302484366P粉302484366440 days ago554

reply all(1)I'll reply

  • P粉775723722

    P粉7757237222023-08-29 20:07:59

    Pay attention to the documentation of PHP's ftp_pasv function (emphasis mine):

    Also note that you are not checking the status return value of the ftp_pasv call, so you won't notice whether the call actually succeeded (which it most likely won't). Therefore, your script will attempt to establish an active FTP connection. This does not work in containers (unless started with --network=host), since containers run in a private network via NAT on the host machine.

    Solution: Log in first, then enable passive mode (also always check for error return values; many old functions from the PHP standard library do not throw exceptions but rely on error return values):

    if (ftp_login($connection, FTP_USERNAME, FTP_PASSWORD))
    {
        if (ftp_pasv($connection, true) === false) {
            throw new \Exception("无法启用被动模式")
        }
    
        $stream = fopen('data://text/plain,','r');
        ftp_fput($connection, $filename, $stream);
    }

    reply
    0
  • Cancelreply