
先日 (2020/7/10), Heroku のアドオン mLab MongoDB が 2020/11/10 にシャットダウンするとアナウンスがありました[参考文献1]。
mLab (旧 MongoLab) といえば、Heroku 界隈では無料でサクッと MongoDB を試せる便利な DBaaS として多くの採用例がありました。 有償プランも充実しており、最大ストレージ 700GB / RAM 64GB までスケールさせることができるのも強みで、本番用には有償プラン、開発用環境や Review Apps などでは無料の sandbox、みたいに使っていた方も多いのではないでしょうか。
しかし 2018/10/9 に MongoDB の開発元 MongoDB, Inc. が mLab を買収します[参考文献2]。 MongoDB, Inc. では独自の DBaaS である Atlas をローンチしており、mLab は完全に競合サービスとなっていました。買収アナウンスによれば今後 12 ヶ月以内にすべての顧客を Atlas に移行させることを期待しているとあり、競合潰しのための買収であることは明らかです。 この買収と方針を受け、mLab ではマイグレーションを支援するためのツールを開発する方針を示し[参考文献3]、実際にリリースされました。しかしマイグレーションガイドは 11 ステップもあり、ワンクリックで終わり!みたいなツールではありません。
移行先の選定
では、残された時間で開発者が取れる選択肢はどれだけあるでしょうか?
Heroku はシャットダウン予告のメールの中で別の MongoDB Add-on の「ObjectRocket」への移行を提案しています。

Heroku Add-on の使い勝手の良さを引き続き享受するにはこれしかありません。引き続き Add-on 代を徴収したい Heroku としても、こちらを推したいはずです (※ Add-on 自体の提供元は Heroku ではないサードパーティ)。
とはいえマイグレーションの手間がかかることには代わりありません。それに ObjectRocket にはたくさんの Heroku ユーザーが求めている無料 Sandbox がありません! Atlas には無料 Sandbox があります。やっぱり Atlas しかありませんね!
なお、ObjectRocket や Atlas 以外にもまだまだ選択肢もあります。一応紹介しておきます。
- Azure Cosmos DB (API 互換のベツモノ)
- Amazon DocumentDB (API 互換のベツモノ)
- IBM Cloud Hyper Protect DBaaS for MongoDB (ホンモノの MongoDB クラスター)
DBaaS 自体をやめるという選択肢もあります。でも MongoDB を自分でホストするのは大変な苦痛を伴います。個人的にはおすすめできません。
本記事では、表題どおり MongoDB Atlas を選定します。11 ステップの地獄のマイグレーション作業の始まりです。コーヒーと頭痛薬を用意したら、早速はじめましょう!
なお本記事は mLab の Sandbox (無料) を Atlas の Sandbox (無料) に移行することを想定しています。有償の場合は手順が異なる場合があります。
マイグレーション前の準備
A. Atlas 組織とプロジェクトの作成
次の URL にアクセスしてサインアップします。
Managed MongoDB Hosting | Database-as-a-Service | MongoDB

Start free ボタンを押して、個人情報を入力してサインアップします。
私は実行したら CORS_ORIGIN_DENIED
というエラー画面になってしまいました😇
先行きがとっても不安です・・・。しかし大丈夫、ちゃんとサインアップメールが届いていました。メールのリンクをクリックしてログインします。

同じ画面になりましたか?それでは次のステップです。
B. Atlas 組織と mLab アカウントの接続

画面左上の葉っぱ (失礼) の右側にある歯車アイコン⚙️をクリックし、 “Organization Settings” 画面を開いてください。

一番下までぐぐっとスクロールすると、”Connect to mLab” というペインが登場しています!素晴らしい! 早速 [Connect to mLab] ボタンを押します。

mLab のログイン画面になりますね。でも Heroku Add-on だとアイパスがわかりません。 で、どうするかというと、ここで一旦、 同じブラウザで別タブ を開き、Heroku Dashboard にアクセスします。
Heroku Dashboard
ログイン後、目的のアプリを開きます。そして “Installed add-ons” ペインにある mLab をクリックし、mLab のダッシュボードを開きます。

mLab のダッシュボードが開きましたね!この時点でブラウザには次の 3 つのタブがあるはずです。
- mLab ログイン画面のタブ
- Heroku Dashboard のタブ
- mLab のタブ
タブ 3 から 1 に切り替え、 ログイン画面をリロード します。
するとあら不思議、画面が変わりました。

次は ブラウザの戻るボタンで Atlas に戻ります。

もう一回 [Connect to mLab] ボタンを押します。 あらあら不思議、新しい画面が現れました。

[Authorize] ボタンを押すと、Atlas の画面に戻ります。

指定したデータベースのマイグレーション
C. 指定したデータベースのマイグレーション処理の開始
先程の画面で行の右端に […] ボタンがあります。押してメニューを開き、続いて [Configure Migration] を選択します。

お待たせしました・・・こちらが「マイグレーションウィザード」です!
冒頭で言及した「11ステップ」というのはここから始まります! (いままでのは事前準備…)

D. マイグレーションウィザードのタスクの実施
Step 1. 対象プロジェクトの設定
マイグレーションウィザードの1番目のボタン [Create or Select Target Project] を押しましょう。

“Project 0” がありましたのでこれを選択します。いったいつ作ったんでしょう?きっとサインアップしたときですね。もしなければ画面に従って作ってください。
準備できたら [Confirm Project and Continue] ボタンを押します。
Step 2. データベースユーザーのインポート

マイグレーションガイドでは特に何も指示されていません。警告アイコンが気になりますが、そのまま進めましょう。 [Import Database Users And Continue] ボタンを押します。
Step 3. IP ホワイトリストの設定

“Allow all IP address…” と続くチェックボックスを入れます。Heroku は原則ソース IP が不定ですからね。
チェックを入れたら [Allow All And Continue] ボタンを押します。
Step 4. 対象 Atlas クラスターの作成

“Cluster” のプルダウンを開くと “Create most equivalent new cluster RECOMMENDED” という唯一の選択肢があるので選択します。
するとクラスターの設定を選ぶ重要な画面になります。各項目を確認しながら一番下までスクロールしてください。

M0 が無料の Sandbox です!お値段の見積もりも表示されていますね。M0 なら $0 なのを確認してください。 十分に確認したら [Confirm Target And Continue] ボタンを押します。
すると、クラスター作成中表示が現れます。しばらく待ちましょう。私は3分待ちました。

終わるとこんな表示になります。

Step 5. 移行元と移行対象を確認
マイグレーションウィザードの [Confirm Source and Target] ボタンを押します。
(and だったり And だったりが気になりますね…)

確認したら [Confirm And Continue] ボタンを押します。
Step 6. マイグレーションのテスト

マイグレーションのテストを実行するかどうかを選択できます。
このテストは実際に以下の手順を行い、マイグレーション実行時間の見積もりやデータ・インデックスが実際に移行可能であることを検証できます。 マイグレーションガイドでも “strongly recommend” (強く推奨) とあるので、実施しない手はないでしょう。
- Atlas クラスターを消去
- mLab で
mongodump
を実行 - Atlas クラスターで
mongorestore
を実行
テストする場合はそのまま (選択肢にチェックを入れずに) [Begin Test Run] ボタンを押します。
テスト実行中は以下のような画面になります。しばらく待ちましょう。私は2分待ちました。

終わったら次のような画面になるので、 [Confirm Connectivity] ボタンを押します。

Step 7. 接続テスト

接続テストの案内画面になりました。
テスト方法は色々とあります。 まず、MongoDB Atlas のクラスターに接続するには 2 つの接続文字列があります[参考文献5,6]。
- DNS Seedlist Connection Format (SRV):
mongodb+srv://<username>:<password>@<host>/<db>?retryWrites=true&w=majority
- Standard Connection String Format:
mongodb://<username>:<password>@<shard0_host>:27017,<shard1_host>:27017,<shard2_host>:27017/<db>?ssl=true&replicaSet=<shard0_name>&authSource=admin&retryWrites=true&w=majority
1番目のやり方はページに書いてあります。2番目のやり方は “Having trouble connecting?” の中に書いてあります。 お勧めは当然シンプルでモダンな1番目のほうです。しかし1番目でうまくいかない場合は2番目を試すことになります。
このような仕様になっているため、単に Mongo Shell から繋いで試すだけでなく、実際のアプリケーション (ドライバー) の DB 設定を書き換えてローカルで実行する等して検証する事が重要です。
私のアプリは Java 11 + Spring Boot + Spring Data MongoDB という環境でしたが、 spring.data.mongodb.uri
に挿して試したところ以下のようなエラーになってしまいました:
{"ok": 0, "errmsg": "no SNI name sent, make sure using a MongoDB 3.4+ driver/shell.", "code": 8000, "codeName": "AtlasError"}
これは使っていた AdoptOpenJDK 11 が SNI をサポートしていないことによる問題で[参考文献7]、結局 Azul Zulu OpenJDK に置き換えて解決しました。
確認したら [Confirm And Continue] ボタンを押します。
Step 8. Heroku アドオンの config var からの独立性確保

マイグレーション完了後、mLab アドオンは削除することになりますが、その際に MONGODB_URI
config var (環境変数) も Heroku App から削除されてしまいます。
そのため、MONGODB_URI
以外の config var を別に作り、アプリが参照する環境変数をそちらに切り替える作業を行ってください。
もちろん、複数アタッチされている場合は色の名前で区別されたそれぞれにおいて対応が必要です。
私は画面にある例そのまま DB_URI
にすることにしました。具体的な手順は次の通り:
- Heroku Dashboard の App の “Settings” タブを開き、 [Reveal Config Vars] ボタンを押す
- 追加欄で KEY =
DB_URI
, VALUE = (MONGODB_URI
の値をコピペ) を記入し [Add] ボタンを押す - アプリケーションの設定で参照環境変数を変更してデプロイ

完了したら [Confirm And Continue] ボタンを押します。
Step 9. マイグレーション
いよいよマイグレーション実行のときが来ました。

必要に応じてアプリケーションを止め (メンテナンスモードにするなど)、注意事項を確認したら、 “I understand that…” のチェックボックスを入れて、
いざ、
[Begin Migrasion] を押します!
マイグレーション実行中は以下のような画面になります。しばらく待ちましょう。私は3分待ちました。

終わりましたか?おめでとうございます!では [Start Using Atlas] ボタンを押しましょう。

Step 10. Atlas の利用を開始

先程作った Heroku config var の DB_URI
を、Step 7 でテストした接続文字列に置き換えます。

config ver を変更するとほぼ即座に Dyno がリスタートすることにご注意ください。
無事に変わりましたか?おめでとうございます🎉
マイグレーションウィザードはもう用無しですが、一応画面は続いているので進めましょう。
最後のステップは mLab の削除です。
Step 11. mLab Add-on の削除

注意事項が表示されるだけです。削除操作は自分で操作する必要があります。
Heroku Dashboard の App の “Configure Add-ons” リンクから削除できます。

くちばしみたいなアイコンに “Delete Add-on” があります。

削除後もアプリが動いていることを確認し、残ったコーヒーをすべて飲み干したら、全てが終了です。お疲れさまでした。
Happy hacking!
参考文献
- Shutdown of mLab’s Heroku Add-on on November 10, 2020 | mLab Documentation & Support
- mLab is becoming a part of MongoDB, Inc.
- Migrating to MongoDB Atlas | mLab Documentation & Support
- Guide to Migrating a Sandbox Heroku Add-on to Atlas | mLab Documentation & Support
- Troubleshooting connection issues to MongoDB Atlas | mLab Documentation & Support
- Connection String URI Format — MongoDB Manual
- java - MongoCommandException: Command failed with error 8000 (AtlasError): 'no SNI name sent, make sure using a MongoDB 3.4+ driver/shell.' - Stack Overflow