Go＆React(Next.js)環境をDockerで作る

## 目的
GoとReactの環境をdockerで作成
調べてみると、reactコンテナフォルダの中にReactプロジェクトフォルダが作成されて、そこにインストールされるという情報が多い。
しかし、プロジェクトフォルダが作成される場合、１階層深く潜らないといけないので、コンテナフォルダ直下にReactをインストールしたい。


## Reactプロジェクト作成コマンド

```sh
npx create-react-app my-app
```

my-appというフォルダが作成される。
このフォルダを作成したくない。

:::note warn
※create-react-appは非推奨となっているそうです。
現在はフレームワークを利用してインストールすることが推奨されているようです。
:::

※Reactはフレームワークではなく、JavaScriptライブラリー。

### Reactフレームワーク
https://ja.react.dev/learn/start-a-new-react-project

よく目にするのは、Next.js でしょうか。

```sh
npx create-next-app@latest
```

# まずは失敗例

## フォルダ構成

```
.
┣  go - goコンテナ
┃  ┗　Dockerfile
┣ react - Reactコンテナ
┃ ┗　Dockerfile
┗ docker-compose.yml
```

### GO環境DockerFile
```dockerfile
# 開発環境
FROM golang:1.21

WORKDIR /api
COPY . .

RUN go build main.go
```

### React環境DockerFile
```dockerfile
FROM node:20-alpine
ENV NODE_ENV=development

WORKDIR /usr/src/app
```



### docker-compose.yml
```yml
version: '3'

services:
  react-app:
    container_name: react-app
    build: ./react
    volumes:
      - ./react:/usr/src/app
    command: sh -c "yarn start"
    ports:
      - 3000:3000
    stdin_open: true
  go:
    container_name: go-api
    build: ./go
    volumes:
      - ./go:/api
    ports:
      - 8888:8888
    tty: true
  ```


## コマンド
### ビルド
```sh
docker-compose build
```

### reactプロジェクトを作成
コンテナ直下にreactプロジェクトを作成する場合
```sh
docker-compose run --rm react-app sh -c 'npx create-react-app . --template typescript'
```

create-react-app の後に「.」を指定することでプロジェクトフォルダを作成せずに、コンテナ直下に作成できる。


## 失敗
```sh
 % docker-compose run --rm react-app sh -c 'npx create-react-app . --template typescript'
[+] Building 0.0s (0/0)                                    docker:desktop-linux
[+] Creating 1/0
 ✔ Network go_react_helloworld_default  Created                            0.0s
[+] Building 0.0s (0/0)                                    docker:desktop-linux
Need to install the following packages:
create-react-app@5.0.1
Ok to proceed? (y) y
The directory . contains files that could conflict:

  Dockerfile

Either try using a new directory name, or remove the files listed above.
```

どうやら、フォルダの中にファイルがあるとプロジェクトを作成できないらしい。
ということでフォルダ構成を変更してみる。


#成功例

## フォルダ構成とdockerファイルの変更

```
.
┣  go - goコンテナ
┣ react - Reactコンテナ
┗ docker-compose.yml
┣ DockerfileGO
┗　　DockerfileReact

```

DockerFileとdocker-compose.ymlを以下のように編集。


### GO環境DockerFile
パス変更
```dockerfile
# 開発環境
FROM golang:1.21

WORKDIR /api
COPY ./go/ /api/
#ENV GO111MODULE=auto

#RUN go get github.com/pilu/fresh
#CMD ["fresh"]
RUN go build main.go
```

### React環境DockerFile
変更なし
```dockerfile
FROM node:20-alpine
ENV NODE_ENV=development

WORKDIR /usr/src/app

```

### docker-compose.yml
Dockerfileの指定
```yml
version: '3'

services:
  react-app:
    container_name: react-app
    build:
      context: .
      dockerfile: DockerfileGo
    volumes:
      - ./react:/usr/src/app
    command: sh -c "yarn start"
    ports:
      - 3000:3000
    stdin_open: true
  go:
    container_name: go-api
    build:
      context: .
      dockerfile: DockerfileReact
    volumes:
      - ./go:/api
    ports:
      - 8888:8888
    tty: true
  ```

## コマンド（二回目）
### dockerコンテナビルド
```sh
docker-compose build
```

### reactプロジェクトを作成
コンテナ直下にreactプロジェクトを作成する場合
```sh
docker-compose run --rm react-app sh -c 'npx create-react-app . --template typescript'
```

create-react-app の後に「.」を指定することでプロジェクトフォルダを作成せずに、コンテナ直下に作成できる。


### フォルダ構成

```
.
┣  go - goコンテナ
┣ react - Reactコンテナ
┃  ┣　node_modules
┃  ┣　public
┃  ┣　src
┃  ┣　.gitignore
┃  ┣　package-lock.json
┃  ┗　package.json
┣ docker-compose.yml
┣ DockerfileGO
┗　　DockerfileReact

```



## Next.jsの場合


### docker-compose.ymlの変更
commandの変更
  ```yml
version: '3'

services:
  react-app:
    container_name: react-app
    build:
      context: .
      dockerfile: DockerfileGo
    volumes:
      - ./react:/usr/src/app
    command: sh -c "yarn run dev"
    ports:
      - 3000:3000
    stdin_open: true
  go:
    container_name: go-api
    build:
      context: .
      dockerfile: DockerfileReact
    volumes:
      - ./go:/api
    ports:
      - 8888:8888
    tty: true
  ```
  
### インストールコマンド
```sh
docker-compose run --rm react-app sh -c 'npx create-next-app .'
```

インストール時に次の質問が表示されます。
```sh
? Would you like to use TypeScript? › No / Yes
```
このプロジェクトでTypeScriptを使いたいですか？

```sh
? Would you like to use ESLint? › No / Yes
```
このプロジェクトでESLintを使いたいですか？

```sh
? Would you like to use Tailwind CSS? › No / Yes
```
このプロジェクトでTailwind CSSを使いたいですか？

```sh
? Would you like to use `src/` directory? › No / Yes
```
このプロジェクトでsrc/ディレクトリを使いたいですか？

```sh
? Would you like to use App Router? (recommended) › No / Yes
```
App Routerを使いたいですか？（推奨）

```sh
Would you like to customize the default import alias?
```
デフォルトのインポートエイリアスをカスタマイズしたいですか？

### フォルダ構成

```
.
┣  go - goコンテナ
┣ react - Reactコンテナ
┃  ┣　node_modules
┃  ┣　public
┃  ┣　src
┃  ┣　.eslintrc.json
┃  ┣　.gitignore
┃  ┣　next-env.d.ts
┃  ┣　next.config.mjs
┃  ┣　package-lock.json
┃  ┣　package.json
┃  ┣　postcss.config.js
┃  ┣　README.md
┃  ┣　tailwind.config.ts
┃  ┗　tsconfig.json
┣ docker-compose.yml
┣ DockerfileGO
┗　　DockerfileReact

```


## React/Next.JSの確認

`http://localhost:3000/`にアクセス

## Goの確認

goディレクトリ内にファイル作成

ファイル名　hello.go
```go
package main

import "fmt"

func main() {
  fmt.Printf("Hello World\n")
}
```

コマンドラインで実行

```sh
docker-compose run --rm go sh -c 'go run hello.go'
```

```sh
[+] Building 0.0s (0/0)                                    docker:desktop-linux
[+] Building 0.0s (0/0)                                    docker:desktop-linux
Hello World
```

無事、Hello Worldと表示された。