LoginSignup
0
0

【Docker】Docker Composeで踏み台サーバー経由のMySQLサーバーにphpMyAdminでつなぐ

Posted at

タイトルの通り、Docker Composeで踏み台サーバー経由のMySQLサーバーにphpMyAdminでつなぐ方法を記載します。

環境

この記事の作業は、以下の環境で実施しました。

※Rancher Desktopを使用していますが、Docker Desktopでもおそらく問題ありません。

実現したいことと条件

  • MySQLサーバーが2台(複数)ある
  • MySQLサーバーはそれぞれ踏み台サーバーを経由する必要がある
  • 踏み台サーバーはパスフレーズ付きの鍵認証である
    • 鍵については共通のものを使用
  • MySQLサーバーをphpMyAdminで操作したい

構成

ファイルを作成

以下のファイルを作成します。

.env

使用する環境変数を以下のように定義します。以下の値は一例ですのでそれぞれの環境に合わせ書き換えてください。

.env
BASTION_KEY_FILE=~/.ssh/id_rsa
BASTION_KEY_PASS=~/.ssh/id_rsa_pass
BASTION1_HOST=bastion1.example.com
BASTION1_USER=user1
DB1_HOST=db1.example.com
BASTION2_HOST=bastion2.example.com
BASTION2_USER=user2
DB2_HOST=db2.example.com

上記、環境変数の内容について説明します。

  • BASTION_KEY_FILE
    踏み台サーバーのSSHの秘密鍵ファイルのパス

  • BASTION_KEY_PASS
    踏み台サーバーのパスフレーズが書かれたテキストファイルのパス

  • BASTION*_HOST
    踏み台サーバーのホスト名(IPアドレス)

  • BASTION*_USER
    踏み台サーバーに接続するときのユーザー名

  • DB*_HOST
    MySQLサーバーのホスト名(踏み台サーバーからアクセスできるもの)

docker-compose.yml

以下にdocker-compose.ymlを以下のように定義します。
サービスは、2台の踏み台サーバー(db1,db2)、phpMyAdmin(pma)として定義しています。

.yml
version: "3"
services:
  db1: &db_bastion_base
    image: alpine
    volumes:
      - $BASTION_KEY_FILE:/root/.ssh/id_rsa:ro
      - $BASTION_KEY_PASS:/root/.ssh/pass:ro
    environment:
      BASTION_HOST: $BASTION1_HOST
      BASTION_USER: $BASTION1_USER
      DB_HOST: $DB1_HOST
    healthcheck:
      test: "nc -zv localhost 3306"
      interval: 1s
      timeout: 10s
      retries: 3
      start_period: 1s
    command: >
      sh -c "
      apk add --update-cache --no-cache openssh-client sshpass &&
      sshpass -f /root/.ssh/pass -P 'Enter passphrase for key' ssh $$BASTION_USER@$$BASTION_HOST -L *:3306:$$DB_HOST:3306 -N -o StrictHostKeyChecking=no"
  db2:
    <<: *db_bastion_base
    environment:
      BASTION_HOST: $BASTION2_HOST
      BASTION_USER: $BASTION2_USER
      DB_HOST: $DB2_HOST
  pma:
    image: phpmyadmin/phpmyadmin
    ports:
      - 8096:80
    environment:
      PMA_HOSTS: db1,db2
      PMA_PORT: 3306
    depends_on:
      db1:
        condition: service_healthy
      db2:
        condition: service_healthy
  • &db_bastion_base,*db_bastion_base
    db1db2でほとんどの定義が共通です。そのためアンカーとエイリアスを使用し定義の重複定義を避けています。
    &db_bastion_baseがアンカーで、*db_bastion_baseがエイリアスです。なお、これはYAMLの仕様です。
    environment:以外は共通定義のため、db2では省略できるようにしています。

  • - $BASTION_KEY_PASS:/root/.ssh/pass:ro
    ホスト機で定義されたパスフレーズが書かれたテキストファイルをマウントしています。各定義ファイルやコマンドライン引数で直接指定しないように配慮しこのようにしました。(イメージやコマンドライン履歴に残らないように)
    これが完全に安全な方法かはわかりませんが、比較的安全と思われるためこの方法にしました。
    パスフレーズを消してしまう方法も考えられましたが、その方法も避けました、

  • environment:(db1,db2)
    db1,db2それぞれの接続情報の環境変数定義です。

  • healthcheck:
    踏み台サーバーへの接続が確立しているか確認するための定義です。後述のdepends_on:で使用しています。

  • command:
    apkコマンドを使用し必要なツールをインストールしています。
    その後sshコマンドを使用し踏み台サーバーへ接続しMySQLのポートのトンネルを作成しています。
    なお、その際にパスフレーズ入力が求められるためsshpassを使用し自動化しています。

  • PMA_HOSTS
    複数のMySQLにつなぐため、そのホスト名(上記で定義した踏み台サーバーのサービス名)をカンマ区切りで指定します。
    この環境変数の変数名が複数形であることに注意してください。(1つでけホスト名を指定するためのPMA_HOSTもあります)

  • depends_on:
    このサービスを起動するための依存関係を定義しています。条件をservice_healthyとすることにより、上記で定義した、db1,db2healthcheck:がパスした後にこのサービスが起動されるようになります。

最後に

MySQL Workbench使えばいいじゃんという意見もありそうですが、値の変更時にBIT型のものが'1'とかでクエリが生成されエラーになって更新されないという現象がありました。しかも表向きエラーになるわけでもなく気が付けないこともあったのがきっかけでこの方法を取ってみました。
これ以外にも色々なツールはありますが、なんだかんだでphpMyAdminが使いやすいというのもあります。(個人の感想です)

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0