GCSをマウントしたWeb Server Containerをcreate-with-container でサックリ動かす - Cloud shell で 開発環境要らず

# 要約
1. Chromeのみで
2. GCP Console 付属の Cloud Shell を駆使し
3. Cloud Storage をマウントした Docker Container を
4. gcloud compute instances create-with-container コマンドで
5. サックリ簡単にWebサーバを立ち上げます
6. Croud Run は gVisor が強力にコンテナ外へのアクセスを制限しているのでgcsfuseが使えないよ

# 動機
あっ、Webサーバ立てなきゃ、、という時に、IDEやgcloudコマンドやDockerコマンド、その他諸々開発ツールがインストールされたマシンが手元にないケースって割とありますよね。急いでるのに、諸々コマンドやら開発ツールなんか入れてる時間なんて無い…
そんな時でも、ChromeがインストールされたWindows,MAC,iPhone,iPad,Android,Chromebookの何れかがあれば、30分くらいでサックリ目的を達成することができます。

# 手順
## Chromeが動くなにかを用意する
スマートフォンでできなくも無いですが、できれば少し大きめな画面とキーボードは欲しいです。
## GCPコンソールを起動する
https://console.cloud.google.com/ からGCPコンソールを起動します。
GCPをまだ使ったこと無い、アカウントが無い、という方は、[この辺の記事](https://qiita.com/karo-jp/items/67c8488385d83e26f705)の頭の方を参考にしてGCPコンソールを使えるようにしてください。 

## Google Cloud Shell を起動する
###Cloud Shell とは
Google Cloud Shell は、Google Cloud Platform でホストされているリソースを管理するためのシェル環境です。無料で週80時間まで使えます。gcloud コマンドや、go コンパイラ、git, dockerコマンドなど、開発に必要なものは一通り揃ってて便利です。
詳しくはこちら⇒https://cloud.google.com/shell/docs/?hl=ja

###起動方法
GCPコンソール右上のCloud Shell 起動アイコンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12857/63c1a885-b425-a761-4a7d-9681512aff04.png)
ブラウザ画面下部にShell画面が立ち上がります。
## Cloud Shell を初期化する
Cloud Shell 環境に、ターゲットのGCP ProjectID を設定します。

```shell
gcloud config set project [project id]
```

## Google Cloud Strage のバケットを作る
GCS bucketを作ります。
cloud shell内で以下のコマンドを叩いてください。
[bucketname-for-you] の部分は適当な名前を入れてください。名前は全世界で一意で早いものがちです。testとかfoobarとかは誰かがきっととってます。

```
gsutil mb -l asia-northeast1 -b on gs://[bucketname-for-you]
```


## エディタを立ち上げる
Cloud Shell 画面右側にある鉛筆アイコンをクリックしてエディタを立ち上げます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12857/b634f851-3eb0-535d-bcb2-9148c507ec28.png)
すると、今までダッシュボードが表示されていたブラウザ上部がエディタ画面に切り替わります。

## Dockerfile他色々書く
エディタ部分の左側ペインにフォルダ構造が表示されています。
適当なフォルダ（ここではwebserverとします）を作り、作ったフォルダのサブフォルダにhtmlフォルダを作ります。
作ったフォルダ直下にDockerfile,php.ini,entrypoint.shを置きます。
htmlフォルダ下にindex.phpを置きます。

```
📁webserver
 ├─📁html
 │　└─📝index.php
 ├─📝Dockerfile
 ├─📝php.ini
 └─📝entrypoint.sh
```

今回のコンテナは、以下の構成とします。

- apache
- php7
- gcsfuse
- gosu



```dockerfile:Dockerfile
FROM php:7-apache

ENV GCSFUSE_REPO gcsfuse-jessie

RUN apt-get update && apt-get install --yes --no-install-recommends \
    && apt-get install --yes gnupg \
    ca-certificates \
    curl \
  && echo "deb http://packages.cloud.google.com/apt $GCSFUSE_REPO main" \
    | tee /etc/apt/sources.list.d/gcsfuse.list \
  && curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - \
  && apt-get update \
  && apt-get install --yes gcsfuse \
  && apt-get install --yes gosu \
  && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \
  && mkdir /data

COPY php.ini $PHP_INI_DIR
COPY ./html /var/www/html
COPY entrypoint.sh /usr/local/bin/entrypoint.sh

RUN chown -R www-data:www-data /var/www/html \
 && chown -R www-data:www-data /data \
 && chmod a+x /usr/local/bin/entrypoint.sh \
 && sed -i 's/80/${PORT}/g' /etc/apache2/sites-available/000-default.conf /etc/apache2/ports.conf

#EXPOSE 80 443
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
```

```php:index.php
<?php 
phpinfo();
?>
```

```php:php.ini
[Date]
date.timezone = "Asia/Tokyo"
[mbstring]
mbstring.internal_encoding = "UTF-8"
mbstring.language = "Japanese"
```

gcsfuseは、マウントしたフォルダを使うユーザーで実行しないとフォルダにアクセスできません。ので、gosuでユーザーを指定して実行します。
Dockerfile内でUSER www-data でもマウントできますが、そうするとapacheが80番ポートをListenできなくなります。

```shell:entrypoint.sh
#!/bin/bash
gosu www-data gcsfuse $GCS_PATH /data
source /etc/apache2/envvars
exec apache2 -D FOREGROUND
```

## Dockerをビルドし、立ち上げる
Cloud Shell でビルドします。
カレントフォルダを./webserver に移動し、ビルドします。

```shell
docker build -t web-container .
```

cloud shell内でコンテナを起動します。cloud shell 自体もDocker Container なのですが、その中で更にテストの為にContainerを起動します。

```
docker run -e PORT=8080 -e GCS_PATH=[bucketname-for-you] \
  --device /data --privileged -p 8080:8080 -d \
  --name php-web-container web-container
```

## 結果を見る
エディタ画面右上の枠の中に菱形が描かれたよくわからないアイコンをクリックすると、 `ポート8080でプレビュー` というメニューが出てくるので選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12857/c2fb6321-0777-53d0-80fa-c879f902b04c.png)
新しいタブで動作確認しましょう。

## Google Container Registory に登録する
駆け足で

```
docker build -t gcr.io/$(gcloud config get-value project)/web-container .
docker push gcr.io/$(gcloud config get-value project)/web-container
```

## インスタンスを作る


```
gcloud compute instances create-with-container web-container-instance \
  --container-image gcr.io/$(gcloud config get-value project)/web-container \
  --container-privileged \
  --container-env PORT=80,GCS_PATH=[bucketname-for-you] \
  --tags http-server \
  --zone=asia-northeast1-a \
  --scopes=default,storage-full
```

インスタンスができて80番ポートでListen開始です。

## まとめ
これでChromeブラウザさえあれば、いつでもどこでもWebサーバが立てられます。
1コンテナ1プロセスとか、マウントしたGCSバケット使ってないよね、とか、そういった事は適宜調整してくれれば、と思います。
SSL/TLSはCloud Loadbalancerを使いましょう。無料のSSL証明書がいい感じに使えます。
Static なHTMLだけのWebサイトなら、GCSバケットを直接Cloud Loadbalancerから参照すれば、インスタンス分のお金がかからずいい感じです。