前提・実現したいこと
ubuntu 20.04
docker
sqlalchemy
ubuntu上でdockerコンテナを構築し、コンテナ外部のネットワークパソコン上にあるsqlite3ファイルの情報をsqlalchemyを用いて取得したいです。
ネットワーク上のパソコン(windows10)には共有フォルダを作りubuntuからはsambaで接続できています。
コンテナ内にあるpythonファイルから
sqlalchemyを用い上記に置いてあるsqlite3に接続する際に以下のエラーメッセージが発生しました。
発生している問題・エラーメッセージ
エラーメッセージ sqlalchemy.exc.operationalerror (sqlite3.operationalerror) unable to open database file
該当のソースコード
python
1from sqlalchemy import create_engine 2from sqlalchemy.orm import sessionmaker 3from sqlalchemy.ext.declarative import declarative_base 4 5 6 def dbconnect_main(self, val): 7 result = False 8 url = 'sqlite:////172.20.*.***/websys/db.sqlite3' 9 engine = create_engine(url, echo=False) 10 Base = declarative_base(engine) 11 class User(Base): 12 __tablename__ = "top_user" 13 __table_args__ = {"autoload": True} 14 Session = sessionmaker(bind=engine) 15 session = Session() 16 obj = session.query(User).filter(User.idm == val).first() 17 print(obj) 18 if obj is not None: 19 print(obj.user_name) 20 obj.category = '1' 21 obj.tel = '' 22 result = obj 23 else: 24 result = None 25 return result
試したこと
パスにsmb://を追加してみました
sqlite:////smb://172.20
結果は同様のエラーが発生しました。
コンテナ内から外部のネットワークのファイルへのアクセスはできないのしょうか。ご教授お願い致します。
ホストA: windows <- 共有名D で共有フォルダを公開
ホストB: ubuntu <- dockerが入っていて、ホストAの共有名Dを参照可能になっている
そして、ホストBのdockerコンテナでpythonを動かし、そのプログラム上でホストA共有名Dで公開されているフォルダ上にあるファイルに、sqlalchemy(sqlite3)でアクセスしたいということだと仮定します。
まず、sqlalchemyでsqliteを使ってDBファイルにアクセスする場合、ホストAなどを指定する手段はありません。
https://docs.sqlalchemy.org/en/14/dialects/sqlite.html
sqlalchemyが使えるドライバは3種類ありますが、いずれにしてもパスしかサポートしていません。
なので、事前にホストBのubuntuでcifs/smbでホストAの共有名Dをマウントし、パスでアクセスできるようにする必要があります。そうした上で、dockerのmount機能を使って、ローカルパスをmountし、コンテナ側のパスに紐付ければ、sqlalchemyで適切にURLを指定することでアクセスできると思います。
ただ、質問内容を見た感じ、まだ理解が足りていないような気もするので、
(1)ubuntuにファイルをコピーし、dockerを使わずにローカルのpythonで同じことが出来る
(2)ubuntuにファイルをコピーせず、sambaを使ってdockerを使わずにローカルのpythonで同じことが出来る
(3)ubuntuにファイルをコピーせず、sambaもdockerも使って今回質問されたことを実現する
のように段階を踏んでみた方がいいような気がします。
ご回答いただきありがとうございます。
windows10で動作テストをした際はネットワークで繋がった別のwindows10に置いたsqliteへのアクセスは sqlite:////172.20 で問題なくできていました。ですのでその組み合わせで運用できればいいのですが、諸事情により使用できるパソコンがubuntuのみで、さらにインターネットへのアクセスができないオフライン環境となっています。そのため環境構築のしやすさを考慮してdockerを使用している形になります。以上のことから、ご提示頂いた3を行う必要があるのです。
質問の際にその旨を記載しておくべきでした。申し訳ありません。
お教え頂いた内容の中で、おそらくubuntu からwindowsの共有フォルダへのマウントが正しく行えていない・理解できていないのではないかと感じました。
https://www.khstasaba.com/?p=862
共有するのにファイルアプリから接続していたのですが、ターミナルのコマンドでubuntu 側に任意のフォルダを作成しマウントして、それをdockerのvolumeでマウントしてみようと思います。
理由があって3にしてるのは分かりましたし、1についてはWindowsで実績があるのも分かりました。
まずはWindowsでどうして上手く動いたかを説明します。
Windowsではpath部分にUNC表記が使えるので
\\ホスト名\共有名\相対パス
のような書き方が有効です。ここで、\は/でも扱える場合があり、Windows版のpythonでは使えるため、sqlite:///に合わせて
sqlite://///ホスト名/共有名/相対パス
でアクセスできます。例えば
sqlite://///127.0.0.1/testshare/database.db
とすると、127.0.0.1(自ホスト)の共有名testshareにあるdatabase.dbにアクセスできます。
つまりあくまでパスが使えたというだけですね。
しかしLinuxではUNC表記が使えないため、先のコメントのとおりになるというわけです。
次にファイルアプリでURLにアクセスした場合マウントしているのかどうかですが、ファイルアプリ(nautilus)でURLを指定してアクセスしてる場合は、fuseを使ってマウントしています。なので、
mount | grep fuse
などでどこにマウントしているか調べることができ、このパスをdockerからマウントしてあげれば紐付けが可能です。もちろんファイルアプリを使用せず、明示的にmountコマンドから指定して、dockerのコンテナ起動などに合わせた方がいいと思います。
頑張ってください。
UNC表記のこと、Linuxのこと大変勉強になりました。ありがとうございます。もっと精進していきます。
最後に本件を解決済みにし、ベストアンサーをつけさせていただきたいのですが、この質問への追記・修正の依頼ではその機能が無いようです。
大変お手数ですが、回答欄に何か入力していただけると幸いです。
解決したようで良かったです。
自己解決回答をご自分用にまとめておくか、そうでなければ放置でもいいと個人的に思っています。
我儘言ってすみません。
回答1件
あなたの回答
tips
プレビュー