dockerでSFTPサーバーを作成し、Pythonで作成した一時ファイルをアップロードしてみた

2022.12.06

データアナリティクス事業本部のueharaです。

今回はdockerイメージからSFTPサーバーを作成し、Pythonで一時ファイルの作成・ファイルのアップロードを行うという検証をしてみたいと思います。

SFTPじゃなくてFTPが知りたい!って方は以下の記事をご参考下さい。

dockerによるSFTPサーバーの構築

SFTPのdockerイメージは atmoz/sftp を利用したいと思います。

dockerイメージのダウンロード

以下のコマンドを実行し、イメージのダウンロードを行います。

docker pull atmoz/sftp

コンテナの起動

イメージの用意ができたら、 docker-compose.yml ファイルを作成します。

docker-compose.yml

version: '3'

services:
  sftp:
    image: atmoz/sftp
    container_name: sftp-test
    # docker-compose.ymlがあるディレクトリに、コンテナとの共有ディレクトリを作る
    volumes:
        - ./data:/home/testuser/data
    ports:
        - "2222:22"
    command: testuser:test123:::data

今回はあくまでローカル環境での検証を目的としているため、ユーザー名は testuser、パスワードは test123 としています。

コンテナ側の22番ポートには、ホスト側の 2222 番を割り当てます。

コンテナとの共有ディレクトリについても、 docker-compose.yml を置くディレクトリと同じ階層としています。

docker-compose.yml の準備が完了したら、 docker-compose.yml があるディレクトリでdocker-compose upを実行し、コンテナを起動します。

docker-compose up

コンテナを起動すると、ホスト側に共有ディレクトリが作成され、以下のようになっているかと思います。

.
├ data
└ docker-compose.yml

以上でSFTPサーバーの構築は完了です。

PythonによるSFTPサーバーへのアクセス

接続先情報の準備

今回、接続先情報は別ファイルで管理し、Pythonの標準モジュールであるconfigparserで読み込む形としたいと思います。

先程 docker-compose.yml で設定した接続情報を、 config.ini に書き起こしてみます。

config.ini

[sftp]
host = localhost
port = 2222
username = testuser
password = test123

PythonでのSFTPサーバーへのアクセス

Pythonを利用して、一時ファイルを作成し、それをSFTPでアップロードしてみたいと思います。

全体のコードとしては以下の通りです。

sftp_test.py

import configparser
import tempfile

import paramiko


# config.iniの読み取り
config = configparser.ConfigParser()
config.read("config.ini", encoding="utf-8")

# 接続するためのSSHクライアントの準備
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy)

# 接続先情報を設定して接続
client.connect(
    cofig["sftp"]["host"],
    port=int(cofig["sftp"]["port"]),
    username=cofig["sftp"]["username"],
    password=cofig["sftp"]["password"]
)

# セッション開始
sftp = client.open_sftp()

# 一時ファイルを作成してアップロード
with tempfile.NamedTemporaryFile(mode="w", encoding="utf8") as tmpf:
    tmpf.write("This is test file.\n")
    tmpf.flush()
    sftp.put(tmpf.name, "/data/test.txt")

sftp.close()
client.close()

SFTPのクライアントとしては、 Paramiko を利用しています。

ParamikoのSSH Clientに関してはこちらのドキュメントに記載がありますが、 open_sftp() でSFTP client objectを取得することができます。

一時ファイルの作成には、Pythonの標準モジュールである tmpfile を利用しています。こちらは、一時ファイルやディレクトリを作成する際に非常に便利なモジュールです。

特に tempfile.NamedTemporaryFile() は一時ファイルのpathが取得できるのが特徴です。

1つ注意点として、WindowsだとNamedTemporaryFileで一時ファイルを開いている状態で、その名前を使用して再度ファイルを開くことができません(UNIX系のシステムであれば問題なし)。

その場合でも、以下のように記載をすることができます。

with tempfile.NamedTemporaryFile(mode="w", encoding="utf8", delete=False) as tmpf:
    tmpf.write("This is test file.\n")
    tmpf_name = tmpf.name
sftp.put(tmpf_name, "/data/test.txt")

上記プログラム sftp_test.py を実行後、ホスト側の共有ディレクトリである data に、 test.txt がアップロードされていれば成功です。

.
├ data
 └ test.txt
└ docker-compose.yml

test.txt

This is test file.

最後に

今回はdockerイメージからSFTPサーバーを作成し、Pythonで一時ファイルの作成・アップロードを行うといった検証をしてみました。

参考になりましたら幸いです。

参考文献