PHP+ApacheからFTPサーバーへデータをアップロードするアプリケーションを開発するために、まずはDockerで開発環境を作ることになりました。
その際に、コンテナ(Apache + php)とコンテナ(Pure-FTPd)の間の通信でハマったので、記事にまとめます。
バージョン情報
- PHP 7.4
- Apache 2.4
- Pure-FTPd v1.0.47
結論
最終的なdocker-compose.yml
とPHPのプログラムの記述はこんな感じ。
docker-compose.yml
docker-compose.yml
version: '3.7'
services:
app:
build: .
ports:
- 443:443
volumes:
- .:/var/www/html
ftp-server:
image: stilliard/pure-ftpd:latest
ports:
- "21:21"
- "30000-30009:30000-30009"
volumes:
- ./ftp/data:/home/ftpusers
environment:
- PUBLICHOST=ftp-server
- FTP_USER_NAME=ftp_user
- FTP_USER_PASS=ftp_password
- FTP_USER_HOME=/home/ftpusers
FTPでアップロードするプログラム
ftp_upload.php
$ftp_server = 'ftp-server';
$ftp_port = 21;
$ftp_user_name = 'ftp_user';
$ftp_user_pass = 'ftp_password';
$ftp_send_file = '/hoge/data.txt';
$ftp_remote_file = '/hoge/data.txt';
// FTPサーバへ接続する
$conn_id = ftp_connect($ftp_server, $ftp_port);
if($conn_id == false){
echo "FTPサーバへの接続失敗"."\n";
exit();
}
// ユーザー名とパスワードでログインする
$login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass);
if($login_result == false){
echo "FTPサーバへのログイン失敗"."\n";
// 接続を閉じる
ftp_close($conn_id);
exit();
}
//パッシブモードに設定
ftp_pasv($conn_id, true);
// ファイルをアップロードする
if (ftp_put($conn_id, $ftp_remote_file, $ftp_send_file, FTP_BINARY)) {
echo "UPLOAD 成功"."\n";
} else {
echo "UPLOAD 失敗"."\n";
}
// 接続を閉じる
ftp_close($conn_id);
Dockerfileはあまり重要ではないので割愛します。
重要なところ
docker-compose.yml
version: '3.7'
services:
# 省略
ftp-server:
# 省略
environment:
- PUBLICHOST=ftp-server
ftp_upload.php
$ftp_server = 'ftp-server';
解説
参考記事
Dockerはコンテナ名を使用してコンテナ間の通信をするそう。
なので、
docker-compose.yml
version: '3.7'
services:
# 省略
ftp-server:
ここで設定したサービス名(container_name
で明示的にしていないとサービス名がコンテナ名となる)と、
docker-compose.yml
# 省略
environment:
- PUBLICHOST=ftp-server
このPUBLICHOST
を合わせておかないと、Docker間でのFTP通信ができない。(ホスト名が違うとエラーが出る)
docker-compose.yml
内の項目を合わせたら、これでFTPサーバー側の設定はできたので、
ftp_upload.php
$ftp_server = 'ftp-server';
上記のようにアプリ側でコンテナ名(ホスト名)を指定して、プログラムを実行すれば無事アップロードが成功する。(はず)