- 投稿日:2020-10-15T22:31:35+09:00
Docker 初心者が Mattermost を docker-compose で立ち上げる話
はじめに
オンプレ型チャットツール「Mattermost」のプラグインを開発するために、
Mattermost サーバーを立てようとしていたのですが、
- 初心者だけど Docker で楽に構築したい
- Enterprise Edition を試したい
- バージョン(5.27.0)を指定したい
という条件下でかなり苦戦してしまいました。
自分のために、そして同じ状況下で困っている方(がいるかわかりませんが)のために、
他に参考にした記事を引用しつつ、どんな流れで構築したかを記録しておきます。前提
目指す環境
- Mattermost Enterprise Edition(5.27.0)が動作する
- Mattermost の DB には MySQL(8.0)を使用する
- Mattermost まわりのあれこれを Docker で起動する
- (おまけ)Mattermost のプラグインがファイルでアップロードできる
自分の環境
- macOS Catalina 10.15.6
- Docker
- Desktop 2.3.0.4
- Server Engine 19.03.12
- Client Engine 19.03.12
- Git 2.24.3 (Apple Git-128)
わたし
タイトルにもある通り、Docker ド初心者 です。
- かろうじて自分のMacにDockerが入っている
docker run
docker stop
docker rm
はとりあえず使える- めっちゃ頑張ったら起動中のコンテナのシェルに入れる
- Docker イメージはなんとなくわかる
Dockerfile
を雰囲気で読みながら生きてきたdocker-compose
ってなんなん?というレベルです。優しくしてください。
構築
というわけで、やってみましょう。
1. Mattermost-docker を用意する
今回は、Mattermost サーバーの設定を Docker で行うために、
以下のリポジトリをローカルにcloneします。git clone https://github.com/mattermost/mattermost-docker.gitREADME を読んでみると、
「これ使うと、Mattermost サーバーを Docker 使って簡単にデプロイできるよ(意訳)」と。
なるほど...2. docker-compose.yml を読んでみる
こちらの記事(Mattermost+MySQLのセットアップ (Docker) - Qiita)を参考に、
docker-compose.yml
とやらを書き換えてみたいんですが、
その前に「そもそもこれなんやねん」ということで、ちょっと中身を覗いてみます。docker-compose.ymlversion: "3" services: db: build: db read_only: true restart: unless-stopped volumes: - ./volumes/db/var/lib/postgresql/data:/var/lib/postgresql/data - /etc/localtime:/etc/localtime:ro environment: - POSTGRES_USER=mmuser - POSTGRES_PASSWORD=mmuser_password - POSTGRES_DB=mattermost # uncomment the following to enable backup # - AWS_ACCESS_KEY_ID=XXXX # - AWS_SECRET_ACCESS_KEY=XXXX # - WALE_S3_PREFIX=s3://BUCKET_NAME/PATH # - AWS_REGION=us-east-1 app: build: context: app # uncomment following lines for team edition or change UID/GID # args: # - edition=team # - PUID=1000 # - PGID=1000 restart: unless-stopped volumes: - ./volumes/app/mattermost/config:/mattermost/config:rw - ./volumes/app/mattermost/data:/mattermost/data:rw - ./volumes/app/mattermost/logs:/mattermost/logs:rw - ./volumes/app/mattermost/plugins:/mattermost/plugins:rw - ./volumes/app/mattermost/client-plugins:/mattermost/client/plugins:rw - /etc/localtime:/etc/localtime:ro # When you want to use SSO with GitLab, you have to add the cert pki chain of GitLab inside Alpine # to avoid Token request failed: certificate signed by unknown authority (link: https://github.com/mattermost/mattermost-server/issues/13059) # - <path_to_your_gitlab_pki>/pki_chain.pem:/etc/ssl/certs/pki_chain.pem:ro environment: # set same as db credentials and dbname - MM_USERNAME=mmuser - MM_PASSWORD=mmuser_password - MM_DBNAME=mattermost # use the credentials you've set above, in the format: # MM_SQLSETTINGS_DATASOURCE=postgres://${MM_USERNAME}:${MM_PASSWORD}@db:5432/${MM_DBNAME}?sslmode=disable&connect_timeout=10 - MM_SQLSETTINGS_DATASOURCE=postgres://mmuser:mmuser_password@db:5432/mattermost?sslmode=disable&connect_timeout=10 # in case your config is not in default location #- MM_CONFIG=/mattermost/config/config.json web: build: web ports: - "80:80" - "443:443" read_only: true restart: unless-stopped volumes: # This directory must have cert files if you want to enable SSL - ./volumes/web/cert:/cert:ro - /etc/localtime:/etc/localtime:roどうやら
db
app
web
の三層構造になってるようです。
この三層構造は別に Mattermost 特有の何かとかではなく、
一般的な Web三層アーキテクチャです。
その構造に沿ってdocker-compose.yml
が記述されていると。これまで
docker run
するたびに Apache だの SQL だの一個ずつ起動してたけど、
どうやら階層構造をちゃんと決めて、
アプリケーションに関連するものをまとめて起動してくれそうだぞ、という雰囲気がします。3. docker-compose.yml を書き換える
なんとなく構成がわかったところで、目指す環境にあうように中身を書き換えていきます。
手っ取り早く進めたい方は以下のソースコードをコピペして、次のステップへ進んでください。
docker-compose.yml
docker-compose.ymlversion: "3" services: db: image: mysql/mysql-server:8.0 # read_only: true restart: unless-stopped volumes: # - ./volumes/db/var/lib/postgresql/data:/var/lib/postgresql/data - ./volumes/db/var/lib/mysql:/var/lib/mysql - ./volumes/db/etc/my.cnf.d:/etc/my.cnf.d # - /etc/localtime:/etc/localtime:ro environment: - MYSQL_ROOT_PASSWORD=password - MYSQL_USER=mmuser - MYSQL_PASSWORD=password - MYSQL_DATABASE=mattermost - TZ=`ls -la /etc/localtime | cut -d/ -f8-9` ports: - "33306:3306" # uncomment the following to enable backup # - AWS_ACCESS_KEY_ID=XXXX # - AWS_SECRET_ACCESS_KEY=XXXX # - WALE_S3_PREFIX=s3://BUCKET_NAME/PATH # - AWS_REGION=us-east-1 app: build: context: app # uncomment following lines for team edition or change UID/GID args: - edition!=team # - PUID=1000 # - PGID=1000 restart: unless-stopped volumes: - ./volumes/app/mattermost/config:/mattermost/config:rw - ./volumes/app/mattermost/data:/mattermost/data:rw - ./volumes/app/mattermost/logs:/mattermost/logs:rw - ./volumes/app/mattermost/plugins:/mattermost/plugins:rw - ./volumes/app/mattermost/client-plugins:/mattermost/client/plugins:rw # - /etc/localtime:/etc/localtime:ro # When you want to use SSO with GitLab, you have to add the cert pki chain of GitLab inside Alpine # to avoid Token request failed: certificate signed by unknown authority (link: https://github.com/mattermost/mattermost-server/issues/13059) # - <path_to_your_gitlab_pki>/pki_chain.pem:/etc/ssl/certs/pki_chain.pem:ro environment: # set same as db credentials and dbname - MM_USERNAME=mmuser - MM_PASSWORD=mmuser_password - MM_DBNAME=mattermost - DB_PORT_NUMBER=3306 - MM_SQLSETTINGS_DRIVERNAME=mysql - MM_SQLSETTINGS_DATASOURCE=mmuser:password@tcp(db:3306)/mattermost?charset=utf8mb4,utf8&readTimeout=30s&writeTimeout=30s - TZ=`ls -la /etc/localtime | cut -d/ -f8-9` # use the credentials you've set above, in the format: # MM_SQLSETTINGS_DATASOURCE=postgres://${MM_USERNAME}:${MM_PASSWORD}@db:5432/${MM_DBNAME}?sslmode=disable&connect_timeout=10 # - MM_SQLSETTINGS_DATASOURCE=postgres://mmuser:mmuser_password@db:5432/mattermost?sslmode=disable&connect_timeout=10 # in case your config is not in default location #- MM_CONFIG=/mattermost/config/config.json web: build: web ports: - "8080:80" - "8443:443" read_only: true restart: unless-stopped volumes: # This directory must have cert files if you want to enable SSL - ./volumes/web/cert:/cert:ro # - /etc/localtime:/etc/localtime:ro environment: - TZ=`ls -la /etc/localtime | cut -d/ -f8-9`db
まずは MySQL を使うために、
db
の部分を書き換えます。docker-compose.ymldb: - build: db - read_only: true + image: mysql/mysql-server:8.0 + # read_only: true restart: unless-stopped volumes: - - ./volumes/db/var/lib/postgresql/data:/var/lib/postgresql/data + # - ./volumes/db/var/lib/postgresql/data:/var/lib/postgresql/data + - ./volumes/db/var/lib/mysql:/var/lib/mysql + - ./volumes/db/etc/my.cnf.d:/etc/my.cnf.d - - /etc/localtime:/etc/localtime:ro + # - /etc/localtime:/etc/localtime:ro environment: - - POSTGRES_USER=mmuser - - POSTGRES_PASSWORD=mmuser_password - - POSTGRES_DB=mattermost + - MYSQL_ROOT_PASSWORD=password + - MYSQL_USER=mmuser + - MYSQL_PASSWORD=password + - MYSQL_DATABASE=mattermost + - TZ=`ls -la /etc/localtime | cut -d/ -f8-9` + ports: + - "33306:3306"なお、DB 関連のパスワードは
password
に設定しています。
よろしくないパスワードですが、今回はあくまで動作確認用なので目をつむります。
(気になる方はもちろん変更してください)また、以下の部分は Docker のマウント失敗を回避するためのものです。
volumes: ...(中略)... - - /etc/localtime:/etc/localtime:ro + # - /etc/localtime:/etc/localtime:ro environment: ...(中略)... + - TZ=`ls -la /etc/localtime | cut -d/ -f8-9`app と web でも同様の設定が必要です。
(参考:Dockerで- /etc/localtime:/etc/localtime:ro がMount Deniedを出すやつ - Steady WorX はてな)app
Enterprise Edition を使うために、
edition
を設定します。
また、先ほど設定した DB の設定に合うように各種ポート番号などを書き換えます。docker-compose.ymlapp: build: context: app # uncomment following lines for team edition or change UID/GID - # args: - # - edition=team + args: + - edition!=team # - PUID=1000 # - PGID=1000 restart: unless-stopped volumes: - ./volumes/app/mattermost/config:/mattermost/config:rw - ./volumes/app/mattermost/data:/mattermost/data:rw - ./volumes/app/mattermost/logs:/mattermost/logs:rw - ./volumes/app/mattermost/plugins:/mattermost/plugins:rw - ./volumes/app/mattermost/client-plugins:/mattermost/client/plugins:rw + # - /etc/localtime:/etc/localtime:ro environment: - MM_USERNAME=mmuser - MM_PASSWORD=mmuser_password - MM_DBNAME=mattermost + - DB_PORT_NUMBER=3306 + - MM_SQLSETTINGS_DRIVERNAME=mysql + - MM_SQLSETTINGS_DATASOURCE=mmuser:password@tcp(db:3306)/mattermost?charset=utf8mb4,utf8&readTimeout=30s&writeTimeout=30s + - TZ=`ls -la /etc/localtime | cut -d/ -f8-9` # use the credentials you've set above, in the format: # MM_SQLSETTINGS_DATASOURCE=postgres://${MM_USERNAME}:${MM_PASSWORD}@db:5432/${MM_DBNAME}?sslmode=disable&connect_timeout=10 - - MM_SQLSETTINGS_DATASOURCE=postgres://mmuser:mmuser_password@db:5432/mattermost?sslmode=disable&connect_timeout=10 + # - MM_SQLSETTINGS_DATASOURCE=postgres://mmuser:mmuser_password@db:5432/mattermost?sslmode=disable&connect_timeout=10 # in case your config is not in default location #- MM_CONFIG=/mattermost/config/config.jsonweb
最後に web も少しだけ書き換えます。
ポート番号の設定変更くらいですね。docker-compose.ymlweb: build: web ports: - - "80:80" - - "443:443" + - "8080:80" + - "8443:443" read_only: true restart: unless-stopped volumes: # This directory must have cert files if you want to enable SSL - ./volumes/web/cert:/cert:ro - - /etc/localtime:/etc/localtime:ro + # - /etc/localtime:/etc/localtime:ro + environment: + - TZ=`ls -la /etc/localtime | cut -d/ -f8-9`4. バージョンを指定する
今回は 5.27.0 のバージョンで動作させたかったので、
バージョンを指定するために環境変数を設定します。
mattermost-server/app/Dockerfile
をみてみると、mattermost-server/app/Dockerfile# Some ENV variables ENV PATH="/mattermost/bin:${PATH}" ENV MM_VERSION=5.27.0 ENV MM_INSTALL_TYPE=dockerバージョン指定のための環境変数があることがわかります。
他のバージョンに変更したい方は、MM_VERSION
の値を好きに変えてください。
デフォルトは 5.27.0 のようです。5. マウント用ディレクトリの作成
mkdir -pv ./volumes/app/mattermost/{data,logs,config,plugins,client-plugins}先にマウント用ディレクトリを用意しておきます。
これをすっ飛ばすとあとで怒られます。6. いざ、docker-compose up!
docker-compose up -d --buildお、なんだかできてそうな出力結果...!
Successfully tagged mattermost-docker_web:latest Creating mattermost-docker_app_1 ... done Creating mattermost-docker_db_1 ... done Creating mattermost-docker_web_1 ... done先ほど設定したポートは 8080 だったので、
http://localhost:8080 を開いてみましょう。おおー!ちゃんと表示されました!よかったよかった。
7. 停止
立ち上げたコンテナは止めましょう。ということで
docker-compose stopすれば、コンテナを止めることができます。
まとめ
というわけで、本記事では、
docker-compose.yml
を書き換えながら
Mattermost を三層構造のWebアプリケーションとして立ち上げました。
同じように環境構築で困っている人や、未来の自分に役立つ記事になっていれば嬉しいです。個人的には、
docker-compose.yml
まじでわからん、から
何書くもんなんか大体分かったわ、くらいにはなれたのが収穫です。物は試し。おまけ:プラグイン開発したい人向け
今回はプラグイン開発環境するぞー!ってことでこの環境を作ったわけですが、
プラグインをシステムコンソールからアップロードしようとすると
アップロードボタンが灰色になっている....というわけで、起動中のコンテナ(app)に入って書き換えました。
私は Docker Desktop から CLI を起動しちゃいましたが、docker psで app の ID を調べて、
docker exec -it <appのID> /bin/shとしたらコンテナに入れますね。
書き換えが必要なのは以下の部分。
app/config/config.json"PluginSettings": { "Enable": true, - "EnableUploads": false, + "EnableUploads": true, "Directory": "./plugins", "ClientDirectory": "./client/plugins", "Plugins": {},なんでデフォルトは
false
なんでしょうね...
なにはともあれ、これで解決。アップロード用のボタンが現れ、アップロードも無事に出来ました。
- 投稿日:2020-10-15T17:05:39+09:00
【AWS - RDS】MySQLに特定のDBのみのアクセスユーザー作成
1つのDBサーバーを使用して、複数のDBを管理している場合、
特定のDBへのみアクセス出来るユーザーを作成したい。RDSにアクセス
アクセス権のあるEC2から下記を実行。
※ RDSへアクセス権があることを確認。セキュリティグループ等$ mysql -h RDS_ENDPOINT -u root -p Enter password: パスワードを入力ユーザーの作成
ALL
で、全ての権限を付与。
DATABASE_NAME.*
で、全てのテーブルを対象とする。
USERNAME@%
で、全てのホストを対象とする。$ GRANT ALL ON DATABASE_NAME.* TO 'USERNAME'@'%' IDENTIFIED BY 'YOUR_PASSWORD';※
USERNAME
が存在しない場合は、新規でユーザーを作成
- 投稿日:2020-10-15T16:26:53+09:00
データベースの文字化けを直す
フォームなどを作っているとアルファベットはいいのですが、日本語投稿が?になってしまいます。その改善方法をまとめました。
データベースの文字コードをチェック
show variables like ‘character%’;を実行してみてください。するとutf8に混じってlatin1が出てこないでしょうか。
データベースの文字コードを修正
set character_set_database=utf8;こんな感じでlatin1のものをutf8に変更していきます。
テーブルの文字コードを修正
alter table table_name convert to character set utf8;以上を試した上で、もう一度日本語の投稿をしてみてください。
- 投稿日:2020-10-15T09:22:17+09:00
RustとMySQLで簡単なWebApplicationを実装する
Rustで業務アプリケーションを構築中の駆け出しプログラマーです。
今回は練習のためRustで簡単なWebアプリを実装しようと思います。
概要としては、WebからPOST/GETしてMySQLへ書き込みしたり読み出したり
します。正直なところ細かいところまで調べきれていないため勉強用記事というようりは備忘録になっています。随時新しい知識が身に付けば更新しまする予定ですのでお手柔らかににお願いします。
前提
各種環境は以下の通りです。エディタはVSコードでRustAnalyzerという
ツールを入れています。MacOS cargo 1.46.0 rustc 1.46.0 MySQL Ver 8.0.21プロジェクトの作成
% cargo new web_app Created binary (application) `web_app` package % cd web_appactix-webの導入
actixについては以下、引用させていただきました。
actixとは、Rust製のActorフレームワークです。
(Java/Scalaでいうと、Akkaがメジャーですね)
アクター同士が非同期でメッセージをやり取りし、安全に並行処理を行うことができます。
そのactixをベースとしてWeb開発用機能を追加したのが、
軽量・高速なWeb開発フレームワークであるactix-webです。
actix-webで開発されたアプリは、実行ファイルにHTTPサーバーを含んでいるため、
そのまま使うこともできるし、apacheやnginxの後ろに置くこともできます。
参照元cargo.tomlファイルにactix-webを使用することを宣言します。
[dependencies] actix-web = "3.1.0" actix-rt = "1.1.1"次に、actixを利用してウェブページを返えすためのソースを書きたいところですが今回はMVC的な感じのディレクトリ構成にして実装を進めたいため先にディレクトリを整理します。
以下のような構成にしてください。
ちなみに、ディレクトリ構成についてはこちらのサイトを参考にさせていただきました。web_app ├── Cargo.lock ├── Cargo.toml ├── src │ ├── controllers │ │ ├── index.rs │ │ └── mod.rs │ ├── lib.rs │ ├── main.rs │ ├── models │ └── routes.rs └── targetWebページを見れるようにする
それでは早速、main.rsをいじります。
ここら辺についてはこちらを参考にさせていただきました。
参考記事ではroutesというファイルは存在しないのですが、今回はMVC的な感じにするためroutesファイルを作成してルーティングを行います。
この時、routesを利用するよ、というuse宣言を記述し忘れないように気をつけましょう。main.rsuse actix_web::{App, HttpServer}; use web_app::routes; #[actix_rt::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| App::new().configure(routes::routes)) .bind("localhost:8000")? .run() .await }routes.rsは以下の通りです。
注意点は、routeの最後の()後に「;」が必要なのは常に一番最後の行のrouteになります。これを記述し忘れてはまったので備忘録として。routes.rsuse actix_web::{web, HttpRequest, HttpResponse, Responder}; use crate::controllers::index; pub fn routes(cfg: &mut web::ServiceConfig) { cfg.route("/", web::get().to(index::index)); }次にlib.rsにモジュールを定義します。
これはroutesとcontrollersを外部参照できるようにするためです。lib.rspub mod routes; pub mod controllers;次にcontrollersフォルダ内のmod.rsを以下の通り。
mod.rspub mod index;index.rsを以下の通り。
index.rsuse actix_web::{web, HttpRequest, HttpResponse, Responder}; pub async fn index() -> impl Responder { HttpResponse::Ok().body("Hello world!") }ここでcargo runを実行して、[localhost:8000]に接続すると
WEBページが帰ってくるはずです。Postmanの導入
DBへの接続へ進む前に、Get/Postメソッドを簡単に送ることができる便利ツールPostmanの導入をします。
https://chrome.google.com/webstore/detail/postman/fhbjgbiflinjbdggehcddcbncdddomop?hl=ja&pv
上記のサイトへいき、chromeの拡張機能へ登録してください。
その後アカウントを登録して、アプリを起動します。
chrome以外での使い方は調べていないので、追加で情報が必要な場合は公式サイトをご覧になると良いかと思います。
[公式サイト]ためしにcargo runをしてサーバーを立ち上げた後に、postmanから
localhost:8000/へGETメソッドを送信するとしっかりとHello worldが帰ってきます。DBへ接続
今回はMySQLへ接続してGet/PostしたいのでMySQLにテスト用データベースを用意します。
MySQLの起動
% mysql.server startMySQLへ接続
私の場合はパスワードつけてますが、おそらくrootユーザーでパスワード設定していない場合は-pがいらない、かもしれないです。
こちらに関しては各人の設定次第ですね。% mysql -u[ユーザー名] -pテスト用のDBを作成
DBの名前は任意です。私はrust_web_testにしました。% create database rust_web_testひとまずMySQはこれでOKです。次にRustのORM「Diesel」をインストールしていきます。
Dieselのインストールに関しては公式のチュートリアルを参考にしました。
まずは依存関係を定義します。cargo.toml[dependencies] actix-web = "3.1.0" actix-rt = "1.1.1" diesel = { version = "1.4.4", features = ["mysql"] } dotenv = "0.15.0"次に、web_app配下に.envファイルを作成してdieselをインストールしましょう。.
cargo install diesel_cli
先ほど作成した.envファイルに今回使用するDBへの接続情報を記述します。
DATABASE_URL=mysql://ユーザー名:パスワード@localhost/rust_web_test次に以下を実行。
これでweb_app配下にmigrationフォルダが作成されここでschemaをマネジメントしていきます。diesel setup試しにテーブルを作成してみましょう。
以下を実行するとmigrationフォルダの下に新しいフォルダが作成され、その配下に
・up.sql
・down.sql
が作成されます。% diesel migration generate usersup.sqlとdown.sqlにSQLを記述
up.sqlCREATE TABLE users ( id SERIAL PRIMARY KEY, name VARCHAR(64) NOT NULL );down.sqlDROP TABLE users;ターミナルで以下を実行して変更を反映させます。これでSQLは以上です。
% diesel migration run Running migration 2020-10-14-003024_users % diesel migration redo Rolling back migration 2020-10-14-003024_users Running migration 2020-10-14-003024_usersこれでshema.rsには以下のようなソースが追加されます。
schema.rstable! { users (id) { id -> Unsigned<Bigint>, name -> Varchar, } }試しに、MySQLに接続してテーブルを確認すると「users」テーブルが作成されているはずです。
//接続 % mysql -uユーザー名 -p //use mysql> use rust_web_app //show mysql> show tables; +----------------------------+ | Tables_in_rust_web_app | +----------------------------+ | __diesel_schema_migrations | | users | +----------------------------+ 2 rows in set (0.00 sec)ここまでやると自動的に以下のようなディレクトリになっていると思います。
util.rsは自分で付け足しました。
ここにはMySQLへ接続するための関数を記述します。web_app ├── Cargo.lock ├── Cargo.toml ├── diesel.toml ├── migrations │ └── 2020-10-14-003024_users │ ├── down.sql │ └── up.sql ├── src │ ├── controllers │ │ ├── index.rs │ │ └── mod.rs │ ├── lib.rs │ ├── main.rs │ ├── models │ ├── routes.rs │ ├── schema.rs └── targetついでにlib.rsを更新しておきましょう。
さらにファイルを追加していきます。
・util.rs
・models/mod.rs
・models/users.rs
・controllers/create_user
以下のようなディレクトリになってればOKです。web_app ├── Cargo.lock ├── Cargo.toml ├── diesel.toml ├── migrations │ └── 2020-10-14-062158_users │ ├── down.sql │ └── up.sql ├── src │ ├── controllers │ │ ├── create_user.rs │ │ ├── index.rs │ │ └── mod.rs │ ├── lib.rs │ ├── main.rs │ ├── models │ │ ├── mod.rs │ │ └── users.rs │ ├── routes.rs │ └── schema.rs │ └── util.rs ├── target ├── .envまずは各ファイルを外部参照できるように、lib.rsを以下のようにします。
lib.rs#[macro_use] extern crate diesel; extern crate dotenv; pub mod routes; pub mod controllers; pub mod models; pub mod schema; pub mod util;DBに値を書き込む
controllers配下のmod.rsに以下を追記します。
pub mod index; pub mod create_user;次にmodels配下のmod.rsに以下を追記
pub mod users;
create_user.rsに戻って以下を追記してください。
今回は「name」だけをDBに書き込みます。create_user.rsextern crate diesel; use crate::models::users::User; use actix_web::{web, HttpRequest, HttpResponse, Responder}; use serde::{Deserialize, Serialize}; #[derive(Debug, Serialize, Deserialize)] pub struct UserData { name: String, } pub async fn create(item: web::Json<UserData>) -> HttpResponse { let user = User::create(&(item.name)); println!("{:?}",user); HttpResponse::Created().body("Inserting") }models/users.rsを以下の通り
users.rsuse diesel::prelude::*; use crate::schema::users; use crate::util::establish_connection; #[derive(Debug, Queryable)] pub struct User { pub id: u64, pub name: String, } #[derive(Insertable)] #[table_name = "users"] pub struct NewUser<'a> { name: &'a str, } impl User { pub fn all() -> Vec<User> { let connection = establish_connection(); users::dsl::users .limit(30) .load::<User>(&connection) .expect("Error loading users") } pub fn create(name: &str) -> User { use self::users::id; let new_user = NewUser { name: name }; let connection = establish_connection(); diesel::insert_into(users::table) .values(&new_user) .execute(&connection) .expect("Error saving new user"); users::dsl::users .order(id.desc()) .first::<User>(&connection) .expect("Error finding users") } }次に、MySQLとのコネクションをするための関数をutilに記述します。
util.rsuse diesel::mysql::MysqlConnection; use diesel::prelude::*; use dotenv::dotenv; use std::env; pub fn establish_connection() -> MysqlConnection { dotenv().ok(); let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set"); MysqlConnection::establish(&database_url) .expect(&format!("Error connecting to {}", database_url)) }お次はcreate_userでシリアライズというアトリビュートを使用するので依存関係を定義します。
cargo.toml[dependencies] actix-web = "3.1.0" actix-rt = "1.1.1" diesel = { version = "1.4.4", features = ["mysql"] } dotenv = "0.15.0" serde = { version = "1.0.116", features = ["derive"] } serde_json = "1.0.58"最後にroutes.rsにcreate_userを追記して書き込みができるようになります。
routes.rsextern crate diesel; use crate::models::users::User; use actix_web::{web, HttpRequest, HttpResponse, Responder}; use serde::{Deserialize, Serialize}; #[derive(Debug, Serialize, Deserialize)] pub struct UserData { name: String, } pub async fn create(item: web::Json<UserData>) -> HttpResponse { let user = User::create(&(item.name)); println!("{:?}",user); HttpResponse::Created().body("Inserting") }cargo runを実行してpostmanでメソッドをGETからPOSTへ変更し、
アドレスをlocalhost:8000/create_userにしてください。
アドレスのすぐ下にあるタブに、「Headers」があるので
そこのKeyに「Content-Type」Valueに「application/json」と設定しましょう。次にBodyタブをクリックしてJson形式で値を入力してSendすれば値を書き込めます。
ターミナルログ
Finished dev [unoptimized + debuginfo] target(s) in 30.12s Running `target/debug/web_app` User { id: 2, name: "testuser1" }MySQLに接続してテーブルの中身を確認すれば値が格納されているはずです。
DBの読み込み
次は格納した値をGetメソッドで呼び出してみたいと思います。
ルートにアクセスした際に格納した値を取り出す処理にしようと思いますので、
indexファイルを以下のように修正します。index.rsuse actix_web::{web, HttpRequest, HttpResponse, Responder}; use crate::models::users::User; pub async fn index() -> impl Responder { let results = User::all(); let mut res = format!("Displaying {} users\n\n", results.len()); for user in results { let s = format!("id: {}, name: {}\n", user.id, user.name); res.push_str(&s); } HttpResponse::Ok().body(res) }終わりも近づいてきました。
PostmanでGetメソッドでルートにアクセスしてSendすると格納した値を取得できます。私は事前にtestuserを格納しているので値が2つありますね。
これで今回の目的は達成しました。
ほとんど備忘録的な感じで解説をはさめていないため、随時更新して解説も入れていきたいと思います。(自分の勉強のため)
- 投稿日:2020-10-15T02:42:13+09:00
Goでデータベースの内容を取得する関数を作る
データベースから目的の内容を全て取る関数について今から書きます。すでにデータベースには、なにか入っている状態でします
interface{} な変数を型が決まっている関数の引数にする
「Golang」 ×「Gorm」でシンプルに「Mysql」を操作する
【go + gin + gorm】webアプリにログイン機能を追加してみる
Goでの Mysql接続から構造体へのデータ割り当てまで
Gin と GORM で作るオレオレ構成 API
installimport ( _ "github.com/go-sql-driver/mysql"// これは、自分で追加が必要 "github.com/jinzhu/gorm" ) // ないとき //go get github.com/jinzhu/gorm //go get github.com/go-sql-driver/mysqlまず、データベースと接続をします
main.gofunc openGormDB() *gorm.DB { // localhost DBMS := "mysql" USER := "user"//mysqlのユーザー名 PASS := "password"//パスワード PROTOCOL := "tcp(localhost:3306)" DBNAME := "sample"//データベース名 CONNECT := USER + ":" + PASS + "@" + PROTOCOL + "/" + DBNAME + "?charset=utf8&parseTime=True&loc=Local" db, err := gorm.Open(DBMS, CONNECT) if err != nil { panic(err) } return db }これは、データベースの内容
main.gotype ShiromiyaChannelInfos struct { //ID uint64 ChannelID string ChannelName string ViewCount uint `gorm:"type:int"` SubscriberCount uint `gorm:"type:int"` VideoCount uint `gorm:"type:int"` CreatedAt time.Time }データベースの内容を取る関数
テーブルごとに書かくデータベースの内容を取る関数// この関数みたいな関数を何度も書かないといけない func GetDBShiro() []ShiromiyaChannelInfos/*<=①*/ { db := openGormDB() var shiroInfo []ShiromiyaChannelInfos/*<=①*/ db.Find(&shiroInfo)/*<=①*/ db.Close() return shiroInfo/*<=①*/ func GetDBHashi() []HashibaChannelInfos/*<=①*/ { db := openGormDB() var hashiInfo []HashibaChannelInfos/*<=①*/ db.Find(&hashiInfo)/*<=①*/ defer db.Close() return hashiInfo/*<=①*/ }データベースに接続して目的のテーブルの内容を全て取得する関数
上の①と、したところだけしが違う
あとは、ほとんど同じ上の(データベースの内容を取る関数)ようなものを何度も書かないといけないのでまとめた
main.go// これは、完成したものです func AllGetDBChannelInfo(chInfo string) (interface{}, error) { db := openGormDB() defer db.Close() switch chInfo { case "ShiromiyaChannelInfos": var channelInfo []entity.ShiromiyaChannelInfos db.Find(&channelInfo) return channelInfo, nil case "HashibaChannelInfos": var channelInfo []entity.HashibaChannelInfos db.Find(&channelInfo) return channelInfo, nil case "ChannelInfos": var videoInfo []entity.VideoInfos db.Find(&videoInfo) return videoInfo, nil default: return nil, errors.New("そのdb_nameありません") } }問題点:
AllGetDBはあとで関数を追加するときAllGetDBを上書きしなければならないGetDBは重複したものが多くなる関数も多くなる。でも、関数を上書きしなくていい追加するだけ