社内向けOSSWebアプリケーション環境をDockerで作成するまで

# 概要

社内だけで利用したいOSSのWebアプリケーションをDockerを利用して環境構築するまでの手順を記載します。
今回の例では、Redmine を構築するまでの手順を記載します。

### 目指す構成

```plantuml
@startuml
actor user
skinparam componentStyle rectangle

component vpc {
  [firewall]
  note top of firewall
   社内の外部IPアドレスからのみアクセスを受け付けるように設定
  end note
  node application-gce-instance {
    [https_portal]
    [Redmine]
  }
  node database-gce-instance {
    [PostgreSQL]
  }
}

user -> firewall
firewall -> https_portal
https_portal -> Redmine
Redmine --> PostgreSQL

@enduml
```

### 構成のねらい

- 今後の拡張も考え、DBとアプリケーションサーバを分ける構成にしている。
- https-portalを利用することで、無料でSSLのマネージメント環境を構築。
- 一つのGCEインスタンスに複数アプリを動作させることで、料金を安く済ませたい。
    - 社内業務で利用するアプリなので、そもそも利用頻度やアクセス数を考慮すると複数同居させても問題ないと想定

## DBサーバの構築

### GCE インスタンス作成

- Debianでマシンを作成する
- 以下を参考にdockerインストール
https://matsuand.github.io/docs.docker.jp.onthefly/engine/install/debian/

### dockerでPostgreSQLの環境を構築

- docker-compose.yml 作成
```yaml
version: '3.1'
 
services:
 
  db:
    image: postgres
    restart: always
    ports:
      - 5432:5432
    volumes:
      - db_data:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: password
 
volumes:
  db_data:
```
- 起動
```bash
$ sudo docker compose up -d
```

## Redmineアプリケーションサーバの構築

### GCEインスタンスを作成

- Debianでマシンを作成
- 以下を参考に外部IPを静的IPに変更
https://cloud.google.com/compute/docs/ip-addresses/reserve-static-external-ip-address?hl=ja

### DNSの設定

DNSのAレコードで、ドメインと上記で設定した静的IPアドレスを紐づけ設定を行う。
※ここで手順詳細は記載しない。
例) ドメインが redmine.example.comの場合
```
redmine.example.com IN A {外部IP}
```
### redmineを構築
- docker-compose.yml 作成
```yaml
version: '3.0'
services:
  redmine:
    image: redmine:4
    restart: always
    ports:
      - 9010:3000
    volumes:
      - ./data/plugins:/usr/src/redmine/plugins
      - ./data/themes:/usr/src/redmine/public/themes
      - ./data/files:/usr/src/redmine/files
    environment:
      REDMINE_DB_POSTGRES: {DBの内部IPアドレス}
      REDMINE_DB_DATABASE: redmine
      REDMINE_DB_USERNAME: postgres
      REDMINE_DB_PASSWORD: password
      REDMINE_SECRET_KEY_BASE: xxxxxxx
```

※pluginを入れる場合は、Dockerfileを利用し、独自にビルドする方が良い。

- 起動
```bash
$ sudo docker compose up -d
```

### https-portalを利用し、SSLプロキシを構築
- docker-compose.yml 作成
```yaml
version: '2.0'
  https-portal:
    image: steveltn/https-portal:1
    depends_on:
      - redmine
    ports:
      - '80:80'
      - '443:443'
    restart: always
    environment:
      DOMAINS: >-
        redmine.example.com -> http://{このGCEインスタンスの内部IPアドレス}:9010
      STAGE: 'production'
      WEBSOCKET: 'true'
      CLIENT_MAX_BODY_SIZE: '100M'
      ACCESS_LOG: 'on'
```

# 今後の拡張性
以下のような流れで、別のアプリケーションも追加可能

- 利用したいアプリケーションを同じインスタンス内にdockerで構築
- 利用したいアプリケーションのDNSを追加
- https-portalの docker-compose.yml を修正
```yaml
...以上省略
    environment:
      DOMAINS: >-
        redmine.example.com -> http://{このGCEインスタンスの内部IPアドレス}:9010
        # 以下の行を追加
        xxx.example.com -> http://{Webアプリケーションが動作しているGCEインスタンスの内部IPアドレス}:{ポート}
      STAGE: 'production'
...以下省略
```
- https-portalのdockerインスタンスを再作成
```
$ sudo docker compose up -d --force-recreate
```

結果としては以下のような構成が出来ると良さそう

```plantuml
@startuml
actor user
skinparam componentStyle rectangle

component vpc {
  [firewall]
  note top of firewall
   社内の外部IPアドレスからのみアクセスを受け付けるように設定
  end note
  node application-gce-instance {
    [https_portal]
    [Redmine]
    [new_webapp]
  }
  node database-gce-instance {
    [PostgreSQL]
  }
}

user -> firewall
firewall -> https_portal
https_portal --> Redmine
https_portal --> new_webapp
Redmine --> PostgreSQL
new_webapp --> PostgreSQL

@enduml
```