コンテナ上からbastion経由でRDSに接続する


はじめに

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

変更前

sshd_config
#ClientAliveInterval 0

変更後

sshd_config
ClientAliveInterval 30

今回はローカルフォワーディングを実現したいので、
特に他に変更することなく接続することができます。
GatewayPorts の設定も不要です。

(リモートフォワーディングとの違いについて図解が分かりやすいです→参考サイト

変更を反映させる

sshdを再起動しておきます。
sudo systemctl restart sshd

コンテナ側の設定

とりあえずDockerfile

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に配置し、
パーミッションを適正値に設定するよう記述しています。

Dockerfile
COPY .ssh/rsa_id /root/.ssh/rsa_id
RUN chmod 600 /root/.ssh/rsa_id

SSH接続をタイムアウトしないようにする(クライアント側設定)

また、SSH接続をタイムアウトさせないように、
クライアント側でも設定ファイルに記述を追加しておきます。

Dockerfile
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 オプションの動作を図解