orbstack(docker)で開発環境をvite(vue3)、フロントエンドをnginxで構築

## まず初めに
以下のエントリにてdocker上でvite-vue3環境を構築する記事を書いたのですが、viteはあくまでも開発環境であり、「フロントエンド」とするのは違うよな…と。
フロントエンドであるWEBサーバはnginxとし、viteはvue3の開発環境としてのコンテナを構築するための手順です。後ほどバックエンドとしてrails-apiコンテナを追加することを想定しています。

https://qiita.com/devzooiiooz/items/45079e52d4a7d4d25d40

## 概要
![nginx-vite-vue.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82975/23cafd15-dd4f-41d1-6c22-70489689302c.jpeg)
今回は上図フロントエンドnginxとvue-viteまでの手順です。

開発環境はMacでdockerコンテナの実行環境としてorbstackを使用します。
orbstackはFQDNでアクセスできるため、ローカル環境でのポートどれにしよう問題を考える必要がありません。

https://zenn.dev/tyamahori/articles/b4feb23e98642e

https://qiita.com/wand_ta/items/fac7de8d6786af8e7fca

### プロジェクトフォルダとcompose.yaml作成
ではこっからdocker composeで構築していきます。
```sh:
mkdir project && cd project
mkdir frontend && touch compose.yaml
```

### 環境変数はdirenvを使用
```sh:
touch .envrc
```
必要な環境変数はここに書き込む
今はprojectnameを定義しているだけですが、後々便利なので。
```env:.envrc
# projectname
export PJNAME='project'
```
環境変数を設定したらdirenv allow
```sh:
direnv allow
```
### nginxディレクトリとDockerfile作成
```sh:
mkdir frontend/nginx && touch frontend/Dockerfile
```
#### この時点でのディレクトリ＆ファイル構成
```sh:tree
./project
    ├── .envrc
    ├── compose.yaml
    └── ./frontend
        ├── Dockerfile
        └── ./nginx
```
### nginx用のDockerfile
これだけ
```docker:Dockefile
FROM  nginx:latest
```

### compose.yaml
orbstackを使用するので外部ポートは指定しない
```yaml:compose.yaml
services:
  nginx:
    build: ./frontend/
    restart: always
    # コンテナ名を明示的に指定する
    container_name: ${PJNAME}-nginx
    networks:
      - nw
networks:
  # コンテナ間通信用のネットワークセグメント
  nw:
    name: ${PJNAME}_nw
```

### 一旦build
```sh:
docker compose build
```
## nginxの起動確認
```sh:
docker compose up -d
```
orbstack画面からコンテナを選択し、Domain（おそらくhttp://nginx.project.orb.local/ になっているはず）からnginxの起動確認
![スクリーンショット 2024-11-04 16.24.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82975/a9da47b9-61d9-1bf6-ba0b-7adbee28c897.png)

## コンテナ内のnginxのdefault.confをコピーする
ここでorbstackのコンテナでproject=>nginxを選択し、Filesでコンテナ内のフォルダを参照する。
nginxのdefault.conf(/etc/nginx/conf.d/default.conf）をローカルのfrontend/nginx/にコピーしておく。

## nginxコンテナを停止
```sh:
docker compose down
```

## nginxログをローカルで確認できるようにする
```sh:
mkdir frontend/nginx/log
```
## logフォルダとdefault.confをbindマウントさせる
```diff_yaml:compose.yaml
services:
  nginx:
    build: ./frontend/
    restart: always
    # コンテナ名を明示的に指定する
    container_name: ${PJNAME}-nginx
    networks:
      - nw
+    # Timezoneを日本にしておくとログもJSTになる
+    environment:
+     TZ: Asia/Tokyo
+    volumes:
+      #confファイルをローカルで変更できるようにする
+      - type: bind
+        source: ./frontend/nginx/default.conf
+        target: /etc/nginx/conf.d/default.conf
+      #nginxのlogフォルダを確認できるように
+      - type: bind
+       source: ./frontend/nginx/log
+        target: /var/log/nginx
networks:
  # コンテナ間通信用のネットワークセグメント
  nw:
    name: ${PJNAME}_nw
```
この時点ではnginxは自分のコンテナのhtmlを参照する設定になっています。
compose up -dしてもlogがローカルで見られるようになっているぐらいです。

# 開発用vue3-vite環境の追加
次にこのプロジェクトにvue3-viteの環境を追加します。
まずvueのvite開発用ディレクトリdevを作成。
その配下にvueディレクトリを切りDockerfileを作成します。
```sh:
mkdir dev
mkdir dev/vue && touch dev/Dockerfile
```

### vue-vite用のDockerfileを編集
こっちのDockerfileはdev/Dockerfileです。
```Dockerfile:dev/Dockerfile
FROM node:lts-alpine
WORKDIR /
RUN apk update
```
### compose.yamlにvueの設定を追加
```diff_yaml:compose.yaml
services:
  nginx:
    build: ./frontend/
    restart: always
    # コンテナ名を明示的に指定する
    container_name: ${PJNAME}-nginx
    networks:
      - nw
    # Timezoneを日本にしておくとログもJSTになる
    environment:
        TZ: Asia/Tokyo
    volumes:
      #confファイルをローカルで変更できるようにする
      - type: bind
        source: ./frontend/nginx/default.conf
        target: /etc/nginx/conf.d/default.conf
      #ここはnginxのlogフォルダを確認できるように
      - type: bind
        source: ./frontend/nginx/log
        target: /var/log/nginx
+  vue:
+    build: ./dev/
+    # Timezoneを日本に
+    environment:
+       TZ: Asia/Tokyo
+    volumes:
+      - type: bind
+       source: ./dev/vue
+       target: /vue
networks:
  # コンテナ間通信用のネットワークセグメント
  nw:
    name: ${PJNAME}_nw
```
### 一旦build
```sh:
docker compose build
```

### create-vueでプロジェクトの作成
```sh:
docker compose run vue npm init vue@latest
```
対話式でvueプロジェクトを構築していきます。
```sh:
create-vue@3.11.2
Ok to proceed? (y) y

> npx
> create-vue


Vue.js - The Progressive JavaScript Framework

✔ Project name: … vue #ここはdev配下に作成したvueと同じにする
✔ Add TypeScript? … No / Yes #=>No まだTypeScriptに手を出していない
✔ Add JSX Support? … No / Yes #=>No
✔ Add Vue Router for Single Page Application development? … No / Yes #=>Yes
✔ Add Pinia for state management? … No / Yes #=>Yes
✔ Add Vitest for Unit Testing? … No / Yes #=>No
✔ Add an End-to-End Testing Solution? › No #=>No
✔ Add ESLint for code quality? … No / Yes #=>Yes
✔ Add Prettier for code formatting? … No / Yes #=>Yes
✔ Add Vue DevTools 7 extension for debugging? (experimental) … No / Yes #=>No

Scaffolding project in /vue...

Done. Now run:

  cd vue
  npm install
  npm run format
  npm run dev
```
完了するとfrontend/vue配下にファイルが作成される。

### dev/Dockerfileを変更
WORKDIRを’/’から'/vue'へ変更
COPYコマンドを追加
```diff_docker:Dockerfile
FROM node:lts-alpine
+ #変更
- WORKDIR /
+ WORKDIR /vue
RUN apk update
+ # 起動コマンドを追加
+ CMD ["yarn", "dev", "--host"]
```

### 再度build
Dockerfileの変更を反映させるため、再度build
```sh:
docker compose build
```

### 確認
コンテナに入り、プロンプト(カレントディレクトリ：WORKDIR)が/vueだったらOK。
カレントが/vueにならないと次項のyarnが/vue配下にインストールされない。
確認後exitで抜ける
```sh:
docker compose run --rm vue sh
/vue #　exit
```

### yarnのインストール
```sh:
docker compose run --rm vue yarn install
```
インストール完了後vue配下にyarn.lockファイルとnode_modulesフォルダができる。

### コンテナ起動
ここでコンテナを起動させ、nginxとvueが表示されることを確認する。
```sh:
docker compose up -d
```
orbstackから
http://vue.project.orb.local/ で以下のvueの画面が確認できていればOK
![スクリーンショット 2024-11-04 17.06.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82975/d20576ff-9f30-044a-5969-0b519373f62e.png)

## vite buildでvueをbuildする
vueコンテナでビルドコマンドを投入する。
yarnを入れたのでyarnでbuild。
npmの場合はnpm run buildでもよい。
```sh:
docker compose exec vue yarn build
```
dev/vue/distにbuildされる。

一旦docker compose down
```sh:
docker compose down
```
## nginxの参照フォルダを変更
compose.yamlを変更し、
nginxのhtmlフォルダをvueコンテナのdev/vue/distを参照するようにする。
```diff_yaml:compose.yaml
services:
  nginx:
    build: ./frontend/
    restart: always
    # コンテナ名を明示的に指定する
    container_name: ${PJNAME}-nginx
    networks:
      - nw
    # Timezoneを日本にしておく
    environment:
        TZ: Asia/Tokyo
    volumes:
      #confファイルをローカルで変更できるようにする
      - type: bind
        source: ./frontend/nginx/default.conf
        target: /etc/nginx/conf.d/default.conf
      #ここはnginxのlogフォルダを確認できるように
      - type: bind
        source: ./frontend/nginx/log
        target: /var/log/nginx
+      #ここはvueからyarn run buildで生成されるdistフォルダを指定する
+      - type: bind
+        source: ./dev/vue/dist
+        target: /usr/share/nginx/html
  vue:
    build: ./dev/
    # Timezoneを日本に
    environment:
      TZ: Asia/Tokyo
    volumes:
      - type: bind
        source: ./dev/vue
        target: /vue
networks:
  # コンテナ間通信用のネットワークセグメント
  nw:
    name: ${PJNAME}_nw
```
## 確認
この状態でdocker compose up -dすれば、nginxの方もvueをbuildしたものに変更されているはずです。

![スクリーンショット 2024-11-04 17.06.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82975/d20576ff-9f30-044a-5969-0b519373f62e.png)