OCI + docker でWordPress環境を簡単構築する

この記事は

- レンタルサーバーを借りずに簡単にWordPressサイトを構築したい
- OCIの無料枠（Always Free）を使ってお金をかけたくない
- OCIのArmインスタンスを使いたい

という人に向けた備忘録です。

## 概要
今回構築する概略図です。
![概略.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529987/0bb50de6-c1f3-df16-4ce9-e739bd73fecf.png)
- OCIでは、Ubuntuイメージのインスタンスを立ち上げます
    - CPUにはARMベースのAmpereを選択します
- インスタンス上で、リバースプロキシの役割を果たすnginx-proxyイメージを使ったDockerコンテナを立ち上げます
    - URLを自動で判定してHTTPリクエストを別のコンテナに割り振ります
- 各WPサイト毎にWordPress公式のイメージを使ったDockerコンテナを立ち上げます

## Step1. OCIに登録する
まずはOCIの登録を済ませてください。
次の記事が参考になります。
※東京リージョンは競争が激しいという噂があるため、こだわりがなければホームリージョンには大阪をおすすめします（2022/03/16時点）．

https://qiita.com/hrkt/items/223b02461bed5cee9d19

## Step2. VCNを作成
仮想クラウドネットワーク（VCN）の設定を行います。
VCNウィザードを使って一式の設定を一括で行います。

1. ネットワーキング > 仮想クラウド・ネットワーク > VCNウィザードの起動
1. VCN名に任意名（例：MainVCN）を入力、「VCNとサブネットの構成」等のその他の項目はデフォルトのまま。「次」を選択
1. そのまま「作成」を選択

続いて、ポートの開放を行います。

1. ネットワーキング > 仮想クラウド・ネットワーク > 先ほど作成したMainVCN
1. セキュリティ・リスト > Default Security List for MainVCN > イングレス・ルールの追加 と進みます
1. ソースCIDRに「0.0.0.0/0」、宛先ポート範囲に「80」を入力して、「イングレス・ルールの追加」
1. 同様に、ポート番号「443」も追加します。

![スクリーンショット 2022-03-16 18.33.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529987/2474da0e-e14c-5125-9951-7f27b1b6a0bc.png)

## Step3. Ubuntuインスタンスの起動

1. コンピュート > インスタンス > インスタンスの作成 と進みます
1. 名前は任意名（Main）に変更します
1. 配置はデフォルトのままで良いです
1. イメージは Canonical Ubuntu に変更
1. Shapeは Ampere の VM.Standard.A1.Flex を選択します。OCPUの数は変更できるので、4とします。
※単一のインスタンスを起動する場合Always Freeでは4 OCPU、メモリ24GBまで対象です。
![スクリーンショット 2022-03-16 18.41.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529987/3187ba9c-916d-8fdd-7cea-6cbec5783531.png)
1. ネットワーキング では先ほど作成したVCN名が選択されていることを確認します
1. 「秘密キーを保存」をクリックし、クライアント上に保存します。後ほどssh接続する際に使用しますのでお忘れなく。
1. ブート・ボリューム はそのまま
1. 作成

これでインスタンスが起動されます。

## Step4. インスタンスにsshアクセスする
コンピュート > インスタンス > 先ほど作成したインスタンス「Main」 と進み、「インスタンス・アクセス」の項目を確認します。
![スクリーンショット 2022-03-16 18.54.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529987/9f75167b-ac00-c751-dd64-b5e894d01b57.png)
この情報と先ほどダウンロードした秘密キーを使って、インスタンスにssh接続します。

~/.ssh/configでログインする場合は、
```:~/.ssh/config
Host ORACLE
    HostName 152.XX.XXX.XX
    User ubuntu
    IdentityFile ~/ssh-key-2022-03-16.key # Step3でダウンロードした秘密キー
```
といった具合です。

## Step5. Dockerのインストール
ssh接続できたら、インスタンス上にDocker環境を整えます。

### Docker Engine
公式のドキュメントに沿ってインストールしていきます。
https://docs.docker.com/engine/install/ubuntu/

```shell
# Set up the repository
$ sudo apt-get update
$ sudo apt-get install ca-certificates curl gnupg lsb-release
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
$ echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Install Docker Engine
$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io
```

### dockerグループにカレントユーザを追加
チュートリアルに従って、コンテナを起動してみます。
```
$ sudo docker run hello-world
```

コンテナ一覧を確認します。

```shell
$ docker ps -a
Got permission denied while trying to connect to the Docker daemon socket at unix:...
```

パーミッションエラーとなりました。カレントユーザをdockerグループに追加することで、dockerの各種操作をできるようになります。
（sudoで行えば追加は不要ですが、何度も付けるのは面倒なので）

```shell
# dockerグループに追加
$ sudo gpasswd -a ubuntu docker
# dockerを再起動する
$ sudo systemctl restart docker
```

最後に一旦ログアウトし、再度ログインすると

```shell
$ docker ps -a
CONTAINER ID   IMAGE         COMMAND    CREATED         STATUS                     PORTS     NAMES
8f8e74eafe7a   hello-world   "/hello"   6 minutes ago   Exited (0) 6 minutes ago             distracted_hypatia
```
のようにsudoなしで確認できるようになりました。

### docker-compose
参考：https://docs.docker.jp/compose/install.html#linux-compose

docker-compose最新版をダウンロードします。
※ダウンロードURLは https://github.com/docker/compose/releases を参照して最新のものに置換してください。

```shell
# curlを使ってダウンロード
sudo curl -L https://github.com/docker/compose/releases/download/v2.3.3/docker-compose-linux-aarch64 -o /usr/local/bin/docker-compose
# 実行権限を付与
sudo chmod +x /usr/local/bin/docker-compose
```

docker-composeのバージョンが確認できたらokです。

```shell
$ docker-compose --version
Docker Compose version v2.3.3
```

## Step6. Dockerコンテナを立ち上げる

簡単に各Dockerコンテナを立ち上げられるシェルスクリプトを作成しましたので、使っていきます。

https://github.com/KaiSugahara/docker_template

### リポジトリのダウンロード

```shell
$ mkdir git && cd git # ダウンロード先は自由です
$ git clone https://github.com/KaiSugahara/docker_template.git
```

### リバースプロキシ & SSL認証
リバースプロキシを実現しつつ、各WPサイトのSSL認証（Let's Encrypt）を自動設定してくれる2つのコンテナを立ち上げます。

```shell
$ cd ~/git/docker_template/nginx-proxy
$ docker-compose up -d
```

`$ docker ps` で起動中のコンテナを確認します。

```shell
$ docker ps
CONTAINER ID   IMAGE                                           COMMAND                  CREATED         STATUS         PORTS                                                                      NAMES
a15c2988959c   jrcs/letsencrypt-nginx-proxy-companion:latest   "/bin/bash /app/entr…"   2 minutes ago   Up 2 minutes                                                                              nginx-letsencrypt
6a6ad0ba8a81   jwilder/nginx-proxy:latest                      "/app/docker-entrypo…"   2 minutes ago   Up 2 minutes   0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp   nginx-proxy
```

`nginx-proxy` と `nginx-letsencrypt` の2つのコンテナが起動していればokです。

### MySQLコンテナとphpmyadminコンテナ
WordPressに必要となるMySQLコンテナを起動します。
またここでは一つのMySQLを複数のWPサイトで使用するため、データベースの編集ができるようにphpmyadminで操作できるようにしておきます。

```shell
# dbコンテナ用のディレクトリを作成
$ cd ~/git/docker_template/mysql
$ bash run.sh
phpmyadminにログインしたいポート番号を入力してください
> 8888
```

再びコンテナを確認します。

```shell
$ docker ps
CONTAINER ID   IMAGE                                           COMMAND                  CREATED          STATUS              PORTS                                                                      NAMES
a6840c9448b5   arm64v8/phpmyadmin                              "/docker-entrypoint.…"   3 seconds ago    Up 2 seconds        0.0.0.0:8888->80/tcp, :::8888->80/tcp                                      db-phpmyadmin
a7ea076ed824   mysql:oracle                                    "docker-entrypoint.s…"   3 seconds ago    Up 2 seconds        3306/tcp, 33060/tcp                                                        db-mysql
︙
```

ポートフォワーディング（例えば8888:localhost:8888）でssh接続すれば、
http://localhost:8888 でphpmyadminにアクセスできます。

ここではWPサイト domain-a.jp で使うためのデータベースを手動で作成します。
1. phpmyadminにアクセス
1. 「データベース」からデータベース `wp_domain_a_jp` を作成
![スクリーンショット 2022-03-16 21.17.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529987/4f3ed8d5-0246-ebc0-0de0-61d0f43bc384.png)
1. wp_domain_a_jp の権限にユーザ`wordpress`を追加します
    1. ホーム > ユーザアカウント > wordpress > データベース
    1. 入力欄に`wp_domain_a_jp`を入力し、実行
    1. すべてチェックする、実行

### WordPressコンテナ

WordPress公式が用意してくれているイメージを使用して起動します。

```shell
# domain-a.jpのWordPressコンテナ用のディレクトリを作成
$ cd
$ mkdir -p web/domain-a.jp && cd web/domain-a.jp
# UIDを確認
$ echo $UID
1001
# 起動用のシェルスクリプトを実行
$ sh ~/git/docker_template/wordpress/run.sh
作成するコンテナ名を入力してください（入力例「wp-domain-name」）
> wp-domain-a-jp
接続するデータベース名を入力してください（入力例「wp_db_name」）
> wp_domain_a_jp
割り当てたいドメイン名を入力してください（入力例「domain.com」または「domain0.com,domain1.com」）
> domain-a.jp,www.domain-a.jp
証明書取得に利用するメールアドレスを入力してください
> [メールアドレス]
あなたのUIDを入力してください
> 1001
カレントディレクトリに public_html を作成し、公開ファイルのマウント先として良いですか？ [y/n]
> y
︙
```

ここでもコンテナの起動を確認します。

```shell
$ docker ps
CONTAINER ID   IMAGE                                           COMMAND                  CREATED              STATUS              PORTS                                                                      NAMES
a7351f11b6ab   1001/wordpress:latest                           "docker-entrypoint.s…"   About a minute ago   Up About a minute   80/tcp                                                                     wp-domain-a-jp
︙
```

### DNSレコード設定
domain-a.jpのAレコードでUbuntuインスタンスのグローバルIPを指定すれば、全て完了です。
![スクリーンショット 2022-03-16 21.43.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529987/d53fcacf-7e45-8467-7011-dedd92c7a1fd.png)