首页  >  问答  >  正文

PHP FTP连接问题在容器化环境下的解决方法

<p>我正在尝试将我的PHP脚本容器化。</p><p>但是由于某种原因,当它在容器中运行时,无法连接到我的FTP服务器。</p><p>在我的本地机器上运行该脚本没有任何问题。</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脚本:</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>90秒后,它会给出以下警告:</p><p><em>ftp_fput(): Connection timed out in /var/www/html/ftp.php on line 16</em></p><p>我尝试进入容器并安装FTP客户端。</p><p>它给我一个类似的超时错误 - 我可以连接到主机,但运行任何命令都会导致停顿。</p><p>我还尝试在VPS上运行容器,以消除任何本地防火墙/网络问题。</p><p>但问题仍然存在。</p><p>如果需要进一步的信息来解决问题,请告诉我。</p>
P粉302484366P粉302484366440 天前556

全部回复(1)我来回复

  • P粉775723722

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

    注意 PHP 的 ftp_pasv 函数的文档(重点在我这里):

    还要注意您没有检查 ftp_pasv 调用的状态返回值,所以您不会注意到该调用是否实际成功(这很可能不会成功)。因此,您的脚本将尝试建立主动的 FTP 连接。这在容器中不起作用(除非使用 --network=host 启动),因为容器在主机机器上通过 NAT 运行在私有网络中。

    解决方案:首先登录,然后启用被动模式(还要始终检查错误返回值;许多来自 PHP 标准库的旧函数不会引发异常,而是依赖于错误返回值):

    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);
    }

    回复
    0
  • 取消回复