#はじめに
Docker container上で動くPythonからAWSのRDSインスタンスに接続したくなりました。
VPCのプライベートサブネットにRDSを配置しているために直接接続することができないため、
パブリックサブネットにEC2インスタンスを立ててBastion(踏み台)として機能させます。
というのが以前までのベストプラクティス?のようでした(注記参照)。
今回も上記方法で接続してみました。
#前提
AWS RDSインスタンスが構築されていること。
bastionとして機能させるEC2インスタンスが立ち上がっていること。
RDSのセキュリティグループでEC2(bastion)からの接続が許可されていること(参考ページ)。
EC2(bastion)のセキュリティグループでSSH接続が許可されていること。
検証環境
Windows10 Pro
Docker for Windows 2.1.0.3
RDSインスタンス:MySQL 5.7
#Bastion側の設定
###SSH接続をタイムアウトしないようにする(サーバ側設定)
sshdの設定ファイルを変更します。
sudo vi /etc/ssh/sshd_config
変更前
#ClientAliveInterval 0
変更後
ClientAliveInterval 30
今回はローカルフォワーディングを実現したいので、
特に他に変更することなく接続することができます。
GatewayPorts の設定も不要です。
(リモートフォワーディングとの違いについて図解が分かりやすいです→参考サイト)
###変更を反映させる
sshdを再起動しておきます。
sudo systemctl restart sshd
#コンテナ側の設定
###とりあえずDockerfile
Dockerfileはこのように作りました。
FROM python:3.7.3
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update \
&& apt-get -y install --no-install-recommends apt-utils dialog 2>&1 \
&& apt-get -y install mysql-client \
&& apt-get autoremove -y \
&& apt-get clean -y \
&& rm -rf /var/lib/apt/lists/*
COPY .ssh/* /root/.ssh/
RUN chmod 600 /root/.ssh/*
RUN echo "ServerAliveInterval 15" >> /etc/ssh/ssh_config
ENV DEBIAN_FRONTEND=
以下の部分ではEC2インスタンスにSSHで接続するためのキーファイルを.sshに配置し、
パーミッションを適正値に設定するよう記述しています。
COPY .ssh/rsa_id /root/.ssh/rsa_id
RUN chmod 600 /root/.ssh/rsa_id
###SSH接続をタイムアウトしないようにする(クライアント側設定)
また、SSH接続をタイムアウトさせないように、
クライアント側でも設定ファイルに記述を追加しておきます。
RUN echo "ServerAliveInterval 15" >> /etc/ssh/ssh_config
#接続
コンテナでsshクライアントを立ち上げます。
このとき、ポートフォワーディングを設定するオプションとRDSのエンドポイントを入力します。
docker container exec -it [コンテナ名] ssh -L 3306:[RDSのエンドポイント]:3306 ec2-user@[EC2のパブリックIPアドレス] -i /root/.ssh/id_rsa
MySQLクライアントでリモートのRDSに接続できるか確かめます。
docker container exec -it [コンテナ名] mysql -u [mysqlのユーザ名] -p -h 127.0.0.1:3306
#注記
SSMによるポートフォワーディング
参考:AWS Systems Manager のポートフォワーディング機能がリリースされました
ご指摘などありましたら大変ありがたいです!
###参考サイト
RDSにSSHポートフォワーディングを利用して接続してみた
SSHポートフォワード:OpenSSH の -L と -R オプションの動作を図解