docker上にgoの環境作れたと思ったけど補完ツールとかがなくて困ったので改善した話
以前dockerを使ってgoの環境構築やdockerを使ってgoの環境構築(DBと接続), docker上にgoの環境作れたと思ったけど作れていなかった話を書きました。これでgoを使ってサーバを作れるぞと意気込み作業を始めたのですが切り分けたモジュールに対して読み込んだファイルで補完が効かなかくてめちゃくちゃやりづらくて困ったので書き残します。
具体的には以下を解決します。
- コンテナ上では問題なく動作するファイルに対してvscodeがエラーを示す。
- vscodeでの開発で入力補完が効かない(特に自作モジュール)。
vscodeを使っている人には参考になるかもしれません。
RemoteContainers
インストール
remote containersはvscodeの拡張機能でDockerコンテナ上でvscodeを開くことができます。なのでエラーや入力補完などをコンテナの環境に合わせて吐いてくれます。
インストールは簡単で、vscodeのエクステンションから'remote container'で検索し、出てきたものをインストールするだけです。
インストールしたら、左下に緑のアイコンが出てくるのでそこから設定していきます。
設定
緑のアイコンを押すと以下のように一覧が出てくるので
Remote-Containers:Add Developement Container Configration Files...
を選択し設定ファイルを作成します。
すると次にどのファイルを元に設定ファイルを作成するか聞いてきます。今回ですとdocker-compose.yml
を元に作るコンテナなので
From 'docker-compose.yml'
を選択します。
複数のサービスがある場合どちらのサービスを元に作成するかを聞いてきます。今回はワーキングディレクトリが'app'なので'app'を選択します。ちなみに今回のdocker-compose.ymlは以下のようになります。
version: "3"
services:
app:
build: ./app/
tty: true
ports:
- "8080:8080"
volumes:
- ./app:/go/src/app
depends_on:
- mysql
mysql:
build: ./mysql/
volumes:
- ./mysql/init:/docker-entrypoint-initdb.d
- ./mysql/data:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=golang
# - TZ=Asia/Tokyo
ports:
- "3306:3306"
container_name: mysql-container
すると以下のように設定ファイルが作成されます。
$ tree -a
.
├── .devcontainer
│ ├── devcontainer.json
│ └── docker-compose.yml
重要なのはdevcontainer.json
です。docker-compose.yml
は削除して構いません。作成されたファイルを以下のように書き換えます。
{
"name": "Existing Docker Compose (Extend)",
"dockerComposeFile": [
"../docker-compose.yml"
// "/docker-compose.yml"は使用しないので削除
],
// vscodeで開くコンテナ
"service": "app",
// マウンティング先のディレクトリを指定
"workspaceFolder": "/go/src/app",
// 各種セッティング
"settings": {
"terminal.integrated.shell.linux": "/bin/sh",
"go.gopath": "/go",
"go.inferGopath": true,
"go.useLanguageServer": true
},
// コンテナ内で使用するエクステンションの指定
"extensions": [
"golang.go",
"wholroyd.jinja"
]
}
- 各種セッティングのところはよく分からなければ上をそのまま写していいと思います。
- 使用するエクステンションはエクステンションのIDを指定します。IDの名前が分からない時は以下のように歯車マークから
Add to devcontainer.json
を選ぶと自動でextensionsに書き込まれます。
緑のアイコンを押して
Remote-Containers: Open Folder in Container...
でディレクトリを指定して開きましょう。指定するディレクトリは特別な理由がなければ'docker-compose.yml'を置いているディレクトリになると思います。
初めての起動だとイメージの取得などが入るので時間がかかるかもしれません。上手くいくと"workspaceFolder"に指定したディレクトリのファイル一覧を読み込んだvscodeが立ち上がります。
立ち上げの際のビルドの状況をログで確認することもできます。初めての立ち上げ時はエラーが出ることもあるので表示しながら立ち上げるといいと思います。
補完ツールのインストール
この状態だと補完機能等はまだインストールされていない状態です。エクステンションに'golang.go'を読み込んでいますが、これはおそらくgoの補完機能などをvscodeに反映させるためのもので補完機能自体は'gopls'や'guru', 'golint'などが提供しています。これらは、これまでにインストールしてきたパッケージと同じように go get
で取得するものになります。
それでは手順を説明していきます。
まずcommand + shift + P
(macの場合)で入力ボックスを開いてGo: Install/Update Tools
を選択します。
以下のようにインストールする機能の一覧が出てくるので必要なものにチェックを入れて'OK'を押します。分からない場合は全てにチェックを入れましょう。ただし、gocode
とgocode-gomod
は代わりとなるgopls
があるのでインストールする必要はないようです。一応それぞれ簡単な説明を入れておきます。
- dlv
デバッガ - godef
定義情報の参照、ジャンプ - gopkgs
インポート可能なパッケージのリストを表示 - go-outline
JSON表現を抽出するためのシンプルなユーティリティ - go-symbols
ワークスペースシンボル検索 - golint
Linter - goplay
Webインターフェース - goreturns
余分なimportを消す、必要なimportを追加する、フォーマットを揃える、function 内で戻り値に合わせた return の補完(zero value)をしてくれる - impl
インターフェースを実装するためのメソッドスタブ生成 - fillstruct
構造体のフィールド初期化を行うリファクタリングツール - gomodifytags
golang の struct にタグを付ける - gopls
コードの自動補完補完ツール - gotests
特定のソースファイルまたはディレクトリ全体のテスト生成 - godoctor
リファクタリング支援ツール - gorename
変数名や関数名のリネーム等ができるリファクタリングツール - guru
ソースコードの静的解析など行うツール
'OK'を押すとシェルが走ると思います。インストールが終わったらgo/bin
を見てみてください。以下のように選択した機能がインストールされていると思います。
/go/bin # ls
dlv go-symbols golint goplay goreturns impl
fillstruct godef gomodifytags gopls gotests realize
go-outline godoctor gopkgs gorename guru
私は試していませんがgo get
で取得しても問題ないと思います。
コンテナの更新
DockerのコンテナはDockerfileを元に作られたイメージを元に立ち上げられるので、そのままだとコンテナを落とした時に補完ツールのインストールで行った作業が消えてしまいます。
そのためコンテナのイメージを今の状態に更新する必要があります。
別のターミナルを開いてまず立ち上がっているコンテナを確認しましょう。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7bf8827150fa 08go_db_app "realize start" About an hour ago Up 3 minutes 0.0.0.0:8080->8080/tcp 08go_db_app_1
ae2d4ac8e7be 08go_db_mysql "docker-entrypoint.s…" About an hour ago Up 3 minutes 0.0.0.0:3306->3306/tcp, 33060/tcp mysql-container
今回やりたいのは'08go_db_app'というイメージを今立ち上がっている'7bf8827150fa'というコンテナの状態にアップデートすることです。アップデートはdocker commit
コマンドでできます。
$ docker commit 7bf8827150fa 08go_db_app
sha256:16946147685a7bf4a40c25711b97f59a3611d219ec2a35d4648d6a3c8c5c8a80
これで元になるイメージがアップデートされたので次回以降に再度インストールする必要はありません。
目的であったコード補完もしっかりやってくれています。
最後に
これまでJavaScriptのライブラリである"react"などを使っていましたがエクステンションのインストールやcreate react app
などのコマンドでそのような補完機能も含めてよしなに環境を構築してくれていたので今回の静的解析や補完機能を自分で構築するのはとても良い経験になりました。
最近テストについてのZennの記事を見てテストのイメージが出来てきたので、次は単体テストをやってみようかなと思っています。
Discussion