💡

[ Docker & CI/CD ] SSHポートフォワードを利用してDBとの接続を行う

2022/03/30に公開

はじめに

ローカル環境でdockerを使用してアプリケーションコンテナを構築した際に、コンテナ内からリモートサーバーのDBに接続するということがありました。
その際に、sshのポートフォワードについて色々と調べた上で試行錯誤を行なったので記事にまとめます。

早速リモートサーバーとローカル環境を繋いでみよう

踏み台サーバーを経由して、その先にあるリモートサーバーとローカル環境とでsshを接続する際には以下のコマンドを実行します。(多段ssh ポートフォワード)

$ ssh -f -N -L 29017:localhost:29017 -i ~/.ssh/id_rsa -4 root@11:11:11:11 -o ProxyCommand='ssh user@222.222.222.222 -W %h:%p' -A

このコマンドで設定されるのは、 localhostの 29017ポートへのアクセスを 222.222.222.222サーバーを経由して11.11.11.11サーバーのlocalhostの29017ポートへと転送する。

configファイルを使ってssh ポートフォワード

上記のコマンドを毎回打つのは非常に煩わしいので、configファイルに諸々の設定を行なっていると、以下のようにHost名を指定するだけでポートフォワードを繋ぐことができる。

CI上でsshポートフォワードを行う際には、-tオプションが必要であるようだ。
gitlab-runnerを使用した際には、不思議なことに -t オプションが2つ必要であった。

terminal
ssh -t -t tep_overseas_db -f -N

以下のconfigファイルの設定をもとに上のsshコマンドを実行すると、はじめに解説したsshポートフォワード と同様の設定ができる。

terminal
ssh -t tep_overseas_db -f -N

以下、configファイルの設定

~/.ssh/config
Host step_server
  HostName 222.222.222.222
  User deployer
  LocalForward 29017 localhost:29017
  ForwardAgent yes
  IdentityFile ~/.ssh/id_rsa

Host target_db
  HostName 11.11.11.11
  User root
  LocalForward 29017 localhost:29017
  ProxyCommand ssh -W %h:%p step_server
  ForwardAgent yes
  IdentityFile ~/.ssh/id_rsa
  AddressFamily inet

CI上ではどうする

CI/CDパイプラインを構築して、CI上で自動テストを行いたいということがあると思います。
私の開発現場ではCIのdockerコンテナ上からsshのポートフォワードを開発環境のDBに直接、接続してテストを実行していました。

※注意

CI上でsshポートフォワードを行う際には、-tオプションが必要であるようです。
私の開発現場では gitlab-runner を使用してCI/CDパイプラインを構築したのですが、なんと不思議なことに -t オプションが2つ必要でした。。
(これは、結構ハマってしまいましたね。。。)

terminal
ssh -t -t tep_overseas_db -f -N

上記のコマンドをCIの処理の中に含めることで、CIのdockerコンテナ上からもsshのポートフォワードを接続することができるようになり、自動でテストを実行することが可能となりました。

そもそも自動テストってDBとの接続はどうするんだろうか

私の開発現場では上記のsshポートフォワードでクラウドサーバー上の開発DBに直接接続して自動テストを回していましたが、

本来は、DBのdockerコンテナを同時に立ち上げて、モックデータとかを投げ込んでからテストを回すのが理想、という気もしますよね。

sshコマンドのオプション

一応、sshポートフォワードで頻繁に使用するオプションをまとめておきます。

オプション 意味
-L ローカルのポートを指定するときに必要
-f ssh 先でコマンドを実行したあとに, バックグラウンドへと潜るオプション
-N ssh 先でなんのコマンドも実行しないオプション
-t 仮想端末を割り当てるオプション(CIでsshを実行する際などに必要)
-i 秘密鍵のパスを指定するオプション
-A ssh接続する際に、リモートサーバーに秘密鍵を転送する
-4 ipv4だけを使用する際に必要

その他のオプションは以下を参照

ssh オプション

最後に

今回は、dockerを使用してローカル開発環境を構築する場合と、CI/CDパイプラインを構築してCI上から自動テストを回す場合とで、sshポートフォワードを使用しました。
他のCIサービスなどを利用する時にもsshポートフォワードを使用することがあるかどうかは分かりませんが、もしその際には今回キャッチアップした内容を基にしてCI/CDパイプラインを構築したいと思います。

Discussion