GCE上のDockerコンテナ内のMySQLへ、一発で接続


## やりたいこと
GCE上にDockerを使ってWebとDBのサーバーを動作させている。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42540/3de79397-5703-1227-fee0-8c56657d0cb9.png)


アプリケーションは、お馴染みのWordPressとする。

手元のPCから、直接MySQLにログインしたい。

## 現状
手元のPCからMySQLにログインするには、以下の3ステップが必要。

1. GCEへSSHログイン
2. DB Serverとして起動しているDockerコンテナへログイン
3. MySQLへログイン

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42540/2883eee4-0ac7-6baa-fbd8-c4cada671f17.png)


この1~3を一発で行いたい。

## 1. SSHログイン
#### SSH鍵が未作成なら、以下コマンドで作成

```bash:
(外部PC)$ ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
```
cf. [お前らのSSH Keysの作り方は間違っている - Qiita](https://qiita.com/suthio/items/2760e4cff0e185fe2db9)

#### 公開鍵を登録
手元のSSH鍵でサーバーへログインできるように登録する必要がある。
以下の操作を、権限のある人に依頼する。

**Compute Engine > Metadata > SSH Keys**
で上の公開鍵を追加する。
（メールアドレスの `@`より前がユーザー名。）

#### SSH接続確認
```bash:
(外部PC)$ ssh -i ~/.ssh/id_rsa [username]@[IP]
```
ログインできたらOK。

## 2. Dockerコンテナへログイン
まずはDockerでWordPressが起動していることを確認する。
以下は[WordPress公式のdocker-compose.yml](https://hub.docker.com/_/wordpress/)。

```yml:docker-compose.yml
version: '3.1'

services:

  wordpress:
    image: wordpress
    restart: always
    ports:
      - 8080:80
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: exampleuser
      WORDPRESS_DB_PASSWORD: examplepass
      WORDPRESS_DB_NAME: exampledb
    volumes:
      - wordpress:/var/www/html

  db:
    image: mysql:5.7
    restart: always
    environment:
      MYSQL_DATABASE: exampledb
      MYSQL_USER: exampleuser
      MYSQL_PASSWORD: examplepass
      MYSQL_RANDOM_ROOT_PASSWORD: '1'
    volumes:
      - db:/var/lib/mysql

volumes:
  wordpress:
  db:
```

起動できた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42540/2a1b68c7-177b-ee5c-3129-0ac7a0da0c53.png)

コンテナへのログインはこのコマンド。

```bash:
(GCE)$ docker exec -it [コンテナID] bash
root@[コンテナID]:/var/www/html#
```
ログインできた。（プロンプトが切り替わってる）

(`Ctrl + C` でログアウトしておく。)


## 3. MySQLへログイン
```bash:
(GCE)$ docker exec -it [コンテナID] mysql -u exampleuser -pexamplepass
mysql>
```
cf. [Docker上でMySQLにログインする - Qiita](https://qiita.com/ymstshinichiro/items/01f6a4c299fdb4b832a2)

ログインできた。

## 実行してみる
DB接続は、[Sequel Pro](https://www.sequelpro.com/)というツールを使っている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42540/7700badb-3492-3622-e9ce-1ab6253714f0.png)

#### 接続失敗！
ログを見てみると、SSHログインできているけど、 `127.0.0.1 port 3306` への接続で失敗しているみたい。

```bash:
...
debug1: Connection established.
...
debug1: Authentication succeeded (publickey).
...
debug1: Connection to port 53983 forwarding to 127.0.0.1 port 3306 requested.
...
open failed: connect failed: Connection refused
```

#### 原因はPort
MySQLが動作しているのは、Dockerコンテナ内の3306番ポート。
アクセスしようとしていたのは、GCEの3306番ポート。
この２つを繋ぐ必要があった。
cf. [Dockerでポートフォワーディング解説 - Qiita](https://qiita.com/tatsuo-iriyama/items/e4bf2404411343116e3e)

以下のように修正。

```yml:docker-compose.yml
version: '3.1'

services:

  wordpress:
    image: wordpress
    restart: always
    ports:
      - 8080:80
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: exampleuser
      WORDPRESS_DB_PASSWORD: examplepass
      WORDPRESS_DB_NAME: exampledb
    volumes:
      - wordpress:/var/www/html

  db:
    image: mysql:5.7
    restart: always
    ports:
      - 3306:3306 # 追加した
    environment:
      MYSQL_DATABASE: exampledb
      MYSQL_USER: exampleuser
      MYSQL_PASSWORD: examplepass
      MYSQL_RANDOM_ROOT_PASSWORD: '1'
    volumes:
      - db:/var/lib/mysql

volumes:
  wordpress:
  db:
```

再起動させる。

```bash:
(GCE)$ docker-compose down
(GCE)$ docker-compose up
```

プロセスを表示すると、Portsの表示が変わった。
`0.0.0.0:3306->3306/tcp` になってる。

```bash:変更前
(GCE)$ docker-compose ps
      Name                    Command               State          Ports
--------------------------------------------------------------------------------
test_db_1          docker-entrypoint.sh mysqld      Up      3306/tcp, 33060/tcp
test_wordpress_1   docker-entrypoint.sh apach ...   Up      0.0.0.0:8080->80/tcp
```

```bash:変更後
(GCE)$ docker-compose ps
      Name                    Command               State                 Ports
---------------------------------------------------------------------------------------------
test_db_1          docker-entrypoint.sh mysqld      Up      0.0.0.0:3306->3306/tcp, 33060/tcp
test_wordpress_1   docker-entrypoint.sh apach ...   Up      0.0.0.0:8080->80/tcp
```

## 再実行
接続できた！🎉