Golang✖︎Next.jsの開発環境を見直してみた

全般

はじめに

上野です!
以前に「VSCodeでGolang✖︎Next.jsの開発環境を構築してみた」という記事を投稿したのですが、記事の内容通りの環境だと色々と不便なことが出てきたので、改めて開発環境を見直してみました。
特に不便だと感じたのが、GolangとNext.jsのコンテナが別々になっていることによって、VSCodeのWindowを二つ開かないといけないのが特に不便に感じました。どうせなら、一つのWindowでソースコードの編集できれば楽だということに気づきました…

ということで、今回は一つのコンテナ上でGolangとNode.jsが動作する環境を作成し、そのコンテナにVSCodeで接続して開発ができるようにしていきたいと思います!

GolangとNode.jsが動作するDockerfileを作成

フォルダ構成は以前のを使用します。
以前の「VSCodeでGolang✖︎Next.jsの開発環境を構築してみた」の記事を参考にGolang✖︎Next.jsのフォルダを作成してください。

新しく追加したファイルに関しては「(New)」と記載しています。

go-next
|_.devcontainer
|       |_devcontainer.json (New)
|
|_.vscode
|       |_launch.json (New)
|
|_server
|       |_.devcontainer
|       |           |_devcontainer.json
|       |_.vscode
|       |           |_launch.json
|       |_Dockerfile  
|       |_.air.toml
|       |_main.go
|
|_client
|       |_.devcontainer
|       |           |_devcontainer.json
|       |_Dockerfile  
|
|_docker-compose.yml
|
|_Dockerfile.dev (New)

では、最初にDockerfile.devのファイルを作成します。

# ------------------------ Golang ---------------------------
FROM golang:1.17-alpine AS golang

# 環境変数設定
ENV ROOT=/go/src/app

WORKDIR ${ROOT}

RUN apk update && apk add git

RUN go install golang.org/x/tools/cmd/goimports@latest \
    && go install golang.org/x/tools/gopls@latest \
    && go install golang.org/x/tools/cmd/godoc@latest \
    && go install golang.org/x/lint/golint@latest \
    && go install github.com/rogpeppe/godef@latest \
    && go install github.com/nsf/gocode@latest \
    # hot relord
    && go install github.com/cosmtrek/air@latest \
    # debug
    && go install github.com/go-delve/delve/cmd/dlv@latest

ADD ./server/shell/mysqldef.sh ${ROOT}/shell/mysqldef.sh

RUN sh ${ROOT}/shell/mysqldef.sh

# GO MODULEインストール
COPY ./server/go.mod .
COPY ./server/go.sum .
RUN go mod download

# # ------------------------ Node ---------------------------
FROM node:17-alpine as node

# # ------------------------ Develop ---------------------------
FROM alpine as dev

# 環境変数設定(GO)
ENV GOPATH=/root/go
ENV PATH $PATH:/usr/local/go/bin/:/usr/local/go/bin/go:/go/bin
ENV GO111MODULE=on

WORKDIR /app

RUN apk update && \
    apk add --no-cache && \
    apk add curl && \
    apk add tzdata && \
    apk add git && \
    apk add openssh && \
    apk add make

# Golang用
COPY --from=golang /usr/local/bin /usr/local/bin
COPY --from=golang /usr/local/go /usr/local/go
COPY --from=golang /go/bin /go/bin
COPY --from=golang /go/pkg ${GOPATH}/pkg

# Node.js用
COPY --from=node /usr/local/bin /usr/local/bin
COPY --from=node /usr/local/lib/node_modules/npm /usr/local/lib/node_modules/npm
COPY --from=node /opt/yarn* /opt/yarn

RUN ln -fs /opt/yarn/bin/yarn /usr/local/bin/yarn && \
    ln -fs /opt/yarn/bin/yarnpkg /usr/local/bin/yarnpkg

# Gin Port
EXPOSE 8080
# Next.js Port
EXPOSE 3000

こちらのDockerifleでは、マルチステージビルドを利用しています。
GolangとNode.jsのステージから必要なフォルダ抽出しalpineステージにコピーしています。

次に.devcontainer/devcontainer.jsonを作成します。

{
  "name": "Go devcontainer",
  "build": {
    "dockerfile": "../Dockerfile.dev",
    "target": "dev"
  },
  "mounts": [
    "source=${localWorkspaceFolder},target=/app,type=bind,consistency=cached"
  ],
  "workspaceFolder": "/app",
  "appPort": ["7777:8080", "3434:3000"],
  "settings": {
    "editor.tabSize": 2,
    "editor.formatOnPaste": true,
    "editor.formatOnType": true,
    "editor.renderWhitespace": "all",
    "editor.bracketPairColorization.enabled": true,
    "editor.guides.bracketPairs": "active",
    "files.trimTrailingWhitespace": true,
    "files.trimFinalNewlines": true,
    "go.toolsManagement.checkForUpdates": "off",
    "go.inferGopath": true,
    "go.useLanguageServer": true,
    "eslint.packageManager": "yarn",
    "eslint.run": "onSave",
    "eslint.nodePath": "/app/client",
    "editor.defaultFormatter": "esbenp.prettier-vscode",
    "editor.codeActionsOnSave": {
      "source.fixAll.eslint": true
    },
    "[go]": {
      "editor.defaultFormatter": "golang.go",
      "editor.insertSpaces": true,
      "editor.formatOnSave": true,
      "editor.codeActionsOnSave": {
        "source.organizeImports": true
      },
      "editor.suggest.snippetsPreventQuickSuggestions": false
    },
    "[javascript]": {
      "editor.formatOnSave": true
    },
    "[typescript]": {
      "editor.formatOnSave": true
    },
    "eslint.validate": [
      "javascript",
      "javascriptreact",
      "typescript",
      "typescriptreact"
    ]
  },
  "extensions": [
    "golang.go",
    "esbenp.prettier-vscode",
    "dbaeumer.vscode-eslint",
  ],
  "shutdownAction": "none"
}

devcontainerファイルは以前のGolangとNode.jsのdevcontainerファイルを合体させたものになります。
異なっている点としては、docker-composeファイルの指定からDockerfileの指定になっている点です。

Golangでデバックができるよう.vscode/launch.jsonファイルを作成します。

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Go",
      "type": "go",
      "debugAdapter": "dlv-dap",
      "request": "attach",
      "mode": "remote",
      "cwd": "${workspaceFolder}/server",
      "port": 2345,
      "host": "0.0.0.0",
      "showLog": true,
    }
  ]
}

以上でコンテナ一つで開発ができる環境ができました。
開発する際は、VSCodeの一番左下のボタンから「Reopen in Container」を選択し接続してみてください。

まとめ

以前の開発環境だとわざわざ二つのwindowを開かないといけず、gitの操作も以前の環境だとできませんでした。ただ、今回の一つのコンテナに接続して開発する方法だと一つのwindowを開くだけで済み、かつgitの操作もコンテナ内で行えるようになりました。今後はこの開発環境をベースにGolangとNext.jsのアプリを作ってみたいと思います。

今回は以上となります。ありがとうございました!

コメント