DockerでGo+React+TypeScript+Chakra-UI+MySQLの環境をつくる

# はじめに
業務でタイトルの環境を作ることが多くなってきたことと、今後教える際に楽をするためにまとめてみます。
以前にDockerでGo+MySQLの環境をつくる記事を出しているので、こちらと重複している部分があります

https://qiita.com/does_not_exist/private/0f948f137a926928ae07

# ディレクトリ構成
```
sample-project
┣ docker
┃   ┣ go
┃   ┃　┗ Dockerfile
┃   ┣ reactapp
┃　　　 ┗ Dockerfile
┣ .env
┣ docker-compose.yml
┣ my.cnf
```   


# ファイル作成

```Dockerfile
# docker/go/Dockerfile

FROM golang:1.18.0
RUN apt-get update && apt-get install -y build-essential make

# vscodeの拡張機能のためにインストール
RUN go install golang.org/x/tools/gopls@latest
RUN go install github.com/ramya-rao-a/go-outline@latest
RUN go install github.com/cosmtrek/air@latest
// RUN wget -O ~/vsls-reqs https://aka.ms/vsls-linux-prereq-script && chmod +x ~/vsls-reqs && ~/vsls-reqs

WORKDIR /go/src
```

```Dockerfile
# docker/reactapp/Dockerfile

FROM node

RUN apt-get update
```

```.env
ROOTUSER=root
ROOTPASS=password
DATABASE=sampledb
USERNAME=docker
USERPASS=docker
```

```docker-compose.yml
services:
  app:
    build: ./docker/reactapp
    container_name: reactapp
    tty: true
    working_dir: /usr/src/app
    volumes:
      - ./reactapp:/usr/src/app
    command: sh -c "yarn start"
    ports:
      - "3000:3000"

  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_USER: ${ROOTUSER}
      MYSQL_ROOT_PASSWORD: ${ROOTPASS}
      MYSQL_DATABASE: ${DATABASE}
      MYSQL_USER: ${USERNAME}
      MYSQL_PASSWORD: ${USERPASS}
      TZ: "Asia/Tokyo"
    volumes:
      - ./my.cnf:/etc/mysql/conf.d/my.cnf
    env_file:
      - .env
    container_name: db
    ports:
      - 3306:3306

  go:
    build: ./docker/go
    volumes:
      - ./go/src:/go/src
    container_name: go
    tty: true
    ports:
      - "8000:8000"
    depends_on:
      - db

```

```my.cnf
[mysqld]
character-set-server=utf8

[client]
default-character-set=utf8
```

# Docker準備
Dockerイメージの作成を行います
コンテナの起動は後述のreactappプロジェクトを作成してからになります
```
$ docker-compose build
```

# React

```
// reactappは作成したいプロジェクト名
$ npx create-react-app --template typescript reactapp
```


コンテナを起動します
```
$ docker-compose up
```

localhost:3000にアクセスして以下の画面が表示されていればOKです

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2889192/30dbaaae-d561-2812-aa1f-fcd72a488aba.png)


# Chakra-UI

https://chakra-ui.com/getting-started

```
// package.jsonのあるディレクトリでインストール
$ cd reactapp
$ yarn add @chakra-ui/react @emotion/react@^11 @emotion/styled@^11 framer-motion@^10
```

:::note warn
※2023/6/20 追記
chakraのモーダルコンポーネントを利用する際はframer-motionのバージョンに注意が必要です。バージョンが4系だとモーダルが再表示されなくなりました。追記時点では6系や10系で正しく動作することを確認できています。その他のバージョンについては確認していません。
:::

chakra-uiのインストールが完了したら忘れずにindex.tsxのAppタグをChakraProviderタグで囲みます

```index.tsx
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import { ChakraProvider } from "@chakra-ui/react";

const root = ReactDOM.createRoot(
  document.getElementById("root") as HTMLElement
);
root.render(
  <React.StrictMode>
    <ChakraProvider>
      <App />
    </ChakraProvider>
  </React.StrictMode>
);

reportWebVitals();

```

次にApp.tsxのreturnの中身をchakra-uiのbuttunコンポーネントに変更し、chakra-uiが適用されるか確認します

```App.tsx
import React from "react";
import "./App.css";
import { Button } from "@chakra-ui/button";

function App() {
  return <Button colorScheme="blue">Button</Button>;
}

export default App;
```


localhost:3000にアクセスして以下の画面になっていればOKです

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2889192/0f09eac0-8fef-e283-69da-cb30e26cc4d0.png)


# MySQL

dbのコンテナに入り、mysqlに接続できることを確認します

```
$ docker exec -it db sh
```

```
// passwordはpassword(.envのROOTPASS)
$ mysql -u root -p
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2889192/73cdba96-534d-c8de-dab5-2d79cef9b390.png)


# Go

goのコンテナに入ります

```
$ docker exec -it go sh
```

go/srcに移動してgo.modを作成します
```
// sample_goというモジュール名で作成
# go mod init sample_go
```

go/srcで以下内容のmain.goを作成します

```main.go
package main

import "fmt"

func main() {
    fmt.Println("Hello, World!")
}
```

以下を実行し、コンソール上にHello, World!が表示されたらOKです

```
# go run main.go
```


# おわりに
長くなってしまいましたが、これで同じようなことを調べる必要がなくなればと思います。