こんにちは。
Dockerに立てたMySQLコンテナに対して、ホストからORマッパーを使いデータベースにアクセスしデータの永続化を実現する機能を持ったソフトウェアを作ろうとしています。
使っている言語はRust
です。
console
1$ sw_vers 2ProductName: macOS 3ProductVersion: 12.4 4BuildVersion: 21F79 5$ cargo --version 6cargo 1.61.0 (a028ae42f 2022-04-29)
実現したいこと
問題は、クライアントのホストPCにmysql
のインストールを強いるような実装は控えたい、しかしORマッパー(diesel
)を使ってDockerコンテナのmysql
へ接続がしたいというときのコードの書き方がわからないということです。
ホストPCにMySQLがインストールされていれば、下記の要領で問題なくコンテナ内のMySQLにもアクセスできることはわかっています。
console
1$ docker-compose up -d 2mysql_container is up-to-date 3$ mysqladmin ping -h127.0.0.1 -P3316 -uroot -prootpass 4mysqladmin: [Warning] Using a password on the command line interface can be insecure. 5mysqld is alive
ユーザが使うローカルPCにはWindowsやMacといったOSなど実行環境に依存させない(インストーラを環境別に作ることを防ぎたい)ためにMySQLをインストールしたくありません。
※わかりにくい表現だったので訂正します。
今回はそうではありません。
DockerだけでMySQLを完結させたいです。
なお、実装に際し部分的にこちらのサイトも参考にしています。
docker-compose.yml
yml
1version: "3" 2 3services: 4 mysql: 5 image: mysql/mysql-server:5.7.28 6 container_name: mysql_container 7 command: --default-authentication-plugin=mysql_native_password 8 environment: 9 MYSQL_ROOT_PASSWORD: rootpass 10 MYSQL_DATABASE: sakila 11 TZ: "Asia/Tokyo" 12 volumes: 13 - ./my.cnf:/etc/mysql/conf.d/my.cnf 14 - ./init:/docker-entrypoint-initdb.d 15 ports: 16 - "3316:3306"
実行したコマンド
ローカルにMySQLがインストールされていない状況を再現するためbrew uninstall
でMySQLをアンインストールしました。
console
1$ brew list -l | grep mysql 2drwxr-xr-x 3 a.kano admin 96 May 27 21:48 mysql 3drwxr-xr-x 3 a.kano admin 96 May 27 21:48 mysql-client 4$ mysql.server restart 5Shutting down MySQL 6. SUCCESS! 7Starting MySQL 8. SUCCESS! 9$ brew uninstall mysql 10Uninstalling /opt/homebrew/Cellar/mysql/8.0.29... (311 files, 295MB) 11$ brew uninstall mysql-client 12Uninstalling /opt/homebrew/Cellar/mysql-client/8.0.29... (129 files, 149.0MB)
次に、docker-compose up -d
を実行してMySQLのコンテナを立てます。
console
1docker-compose up -d 2Starting mysql_container ... done
コンテナに入り、MySQLが生きているか確認します。
console
1$ docker ps 2CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 39db1d950c858 mysql/mysql-server:5.7.28 "docker-entrypoint.s…" About a minute ago Up 11 seconds 33060/tcp, 0.0.0.0:3316->3306/tcp, :::3316->3306/tcp mysql_container 4$ docker exec -it 9db1d950c858 bash 5root@9db1d950c858:/# mysqladmin ping -uroot -prootpass 6mysqladmin: [Warning] Using a password on the command line interface can be insecure. 7mysqld is alive
生きていることが確認できました。
しかし、ここへRustのORマッパー(dieselを使用)からアクセスする方法がわかりません。
未完成のソースコード
RustでMySQLへのコネクションを確立するコードは現状以下のように書いています。
rust
1// mysql.rs 2pub use diesel::prelude::*; 3pub use diesel::MysqlConnection; 4use dotenv::dotenv; 5use std::env; 6 7pub fn establish_connection() -> MysqlConnection { 8 dotenv().ok(); 9 10 let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set"); 11 MysqlConnection::establish(&database_url) 12 .expect(&format!("Error connecting to {}", database_url)) 13}
rust
1// main.rs 2mod mysql; 3use crate::mysql::establish_connection; 4 5fn main() { 6 establish_connection(); 7}
toml
1[package] 2name = "mysql-docker" 3version = "0.1.0" 4edition = "2021" 5 6[dependencies] 7dotenv = "0.15.0" 8diesel = { version = "1.4.8", features = ["mysql"] }
上記dotenv
で読み込む環境変数DATABASE_URLは.envに次のように設定しています。
DATABASE_URL=mysql://root:rootpass@127.0.0.1:3316/sakila
そして実行します。
console
1$ cargo run 2 Finished dev [unoptimized + debuginfo] target(s) in 0.03s 3 Running `target/debug/mysql-docker` 4dyld[43490]: Library not loaded: /opt/homebrew/opt/mysql/lib/libmysqlclient.21.dylib 5 Referenced from: /Users/a.kano/development/mysql-docker/target/debug/mysql-docker 6 Reason: tried: '/opt/homebrew/opt/mysql/lib/libmysqlclient.21.dylib' (no such file), '/Users/a.kano/development/mysql-docker/target/debug/deps/libmysqlclient.21.dylib' (no such file), '/Users/a.kano/development/mysql-docker/target/debug/libmysqlclient.21.dylib' (no such file), '/Users/a.kano/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/aarch64-apple-darwin/lib/libmysqlclient.21.dylib' (no such file), '/Users/a.kano/.rustup/toolchains/stable-aarch64-apple-darwin/lib/libmysqlclient.21.dylib' (no such file), '/Users/a.kano/lib/libmysqlclient.21.dylib' (no such file), '/usr/local/lib/libmysqlclient.21.dylib' (no such file), '/usr/lib/libmysqlclient.21.dylib' (no such file) 7zsh: abort cargo run
このエラーもホストPCにmysql
がインストールされていれば正常終了することは試してわかっているのですが、やはりホストPCにmysql
はインストールしないと実行できないというのでは意味がないと思います。
解決策はありますか?
もし解決策がないなら、繰り返しになりますがユーザのPCに余計にMySQLのインストールをしなければならない制約を課すことになるため、Docker本来の仮想環境の利点が活かされず、Dockerをわざわざ使う意味がありません。インストールに要するコマンドが増えるなど仕様もわかりにくくなります。正しい解決方法が存在していて、私が見つけられていないだけでしょうか?
Sequel Ace
などのようなアプリケーションでもコンテナMySQLの接続にホストにmysql
がインストールされている必要があるか試してみたのですが、予想通りMySQLがホストにインストールされていないと接続できないようでした。
至らない内容で恐縮ですが、ご存知の方、いらっしゃいますでしょうか。
ご教示いただけると助かります。
よろしくお願いします。

回答2件
あなたの回答
tips
プレビュー