どうも、めちゃくちゃお久しぶりです。
もち256です。
最近は転職したりなどで、3ヶ月くらいブログが更新できていませんでした。
今回は技術的につまずいたところのTipsになります。
はじめに
サーバをリモートコントロールするために使用するsshコマンドですが、このコマンドはサーバにリモートアクセスする以外にも、ポートフォワードを行うことができます。
例えば、下記の図のような場面があると想定します。
下記のように開発機、中継サーバ、DBサーバがあってDBサーバに対して変更を行いたい場合、sshで中継サーバやDBサーバにアクセスをして作業を行うことが多いと思います。
今回は中継サーバやDBサーバで作業を行えない場合(作業に必要なコマンドがないなど)、手元の開発機でDBサーバにアクセスを行なって作業をすることとします。
実験用のDockerfile
以下に、Dockerfileとdocker-compose用のファイルを用意しておきました。
実験したい人は「docker compose up」などで試してみてください。
Dockerfile
FROM centos:7
ENV LANG=ja_JP.utf8
ENV LC_ALL=ja_JP.utf8
RUN yum update -y
RUN yum install -y openssh-server
RUN ssh-keygen -A
RUN sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
RUN echo "root:root" | chpasswd
ENTRYPOINT [ "/bin/bash" ]
docker-compose.yml
version: "3"
services:
ssh-server:
build:
context: .
dockerfile: ./Dockerfile
image: centos:7
ports:
- 20022:22
privileged: true
tty: true
mysql-server:
image: mysql:latest
restart: always
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_PORT: 3306
tty: true
networks:
servers:
上記のファイルを実行した後、下記のコマンドを実行して、中継サーバでsshdを起動しておきます。
# コンテナに接続
docker compose exec ssh-server /bin/bash
# sshdの起動
/usr/sbin/sshd -D
つまずいたところ
手元の開発機からDBサーバにアクセスするためには、下記のsshコマンドを使用して、中継サーバでポートフォワードを行います。
# "ssh-server"はDockerであればローカルホストなど、sshdを実行している端末の名前解決をできるようにしておきます。
ssh -N -L 3306:mysql-server:3306 root@ssh-server -p 20022
上記のコマンドを実行すると、開発機(localhost)の3306番ポートがフォワードされるため、中継サーバ(ssh-server)を介して、DBサーバ(mysql-server)の3306番ポートへ通信することができます。
つまり、sshを実行している開発機の3306番ポートへ接続をしようとすることで、DBサーバの3306番ポートへ接続できるようになります。
ここで、下記のコマンドを実行すると、開発機からDBサーバへアクセスすることができるはずだったのですが...
mysql -h localhost -u root -p
# => ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)
なんか、エラーが出てしまいましたね。
どうやら、開発機内のmysql.sockを探しに行き、そんなもの見つからないぞってことらしいです。
まあ、MySQLを実行しているのは別のサーバなので、当たり前なのですが...
上記のエラーですが、下記のコマンドで解決できます。
mysql -h 127.0.0.1 -u root -p
# => Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
# => mysql>
どうやら、ホスト名で「localhost」を指定すると、mysql.sockを使用した接続になってしまうらしく、「127.0.0.1」を指定することで、この問題を回避できます。
この仕様は、下記ドキュメントに書かれており、同じ意味をもつ単語でも、違う挙動になるため各位気をつけてください、というお話でした。
たとえば、Unix 上の `--host=localhost` では、TCP/IP のポート番号を指定するために `--port`または `-P` オプションが指定されている場合でも、クライアントは Unix ソケットファイルを使用してローカルサーバーへの接続を試みます。
MySQL 8.0 リファレンスマニュアル - コマンドオプションを使用した MySQL Server への接続