在Docker和VSCode上搭建Go环境(支持热加载)
首先 / 先从…(说起) / 开始时 / 起初
最近因为个人开发,我开始频繁地使用Go语言。在使用Go语言进行开发时,我有了以下的感受:
-
- Dockerで動かしたい
-
- ホットリロード機能が欲しい
-
- 開発用・本番用でコンテナを分けたい
- 開発時は、VSCode上でコンテナ内とリモート接続して作業したい
我根据许多人的Docker环境创建了一个用于Go的Docker环境。
如果方便的话,请参考一下。
主机环境
-
- Docker: ver.19.03.8
-
- docker-compose: ver.1.25.4
- VSCode: ver.1.43.0
热加载
在研究Go语言进行热加载时,我发现了一个信息。
-
- fresh
- realize
我了解到了有这样的情况存在。
可是,作者意识到实现部分出现错误(错误:返回了非零代码:1),因此无法进行go get操作。
我们试图启动一个容器,并在容器内执行”go get”命令,但是无法解决问题。
因此,今次我們將使用「新鮮」。
操作步骤
-
- 创建Dockerfile(用于开发和生产)+ docker-compose.yml
-
- 配置远程容器
-
- 配置热重载
-
- 启动开发环境
-
- 确认开发环境运行正常
- 启动生产环境
软件开发环境
首先,我们会创建一个工作目录。
# 作業ディレクトリ作成
$ mkdir go-work
# 作業ディレクトリへ移動
$ cd go-work
创建 Dockerfile(开发版&生产版) + docker-compose.yml
接下来,我们将编写Dockerfile和docker-compose.yml文件。
请使用以下命令创建文件。
$ touch docker-compose.yml
$ mkdir -p docker/golang
$ touch docker/golang/Dockerfile.dev
$ touch docker/golang/Dockerfile.dep
※ Dockerfile的语言支持
由于VSCode并没有对Dockerfile.dev(.dep)进行语言支持,因此需要添加设置。
如果您已经进行了相应的设置,请跳过此步骤。
-
- [代碼] -> [基礎設置] -> [設定]
文件:檔案關聯在搜尋
透過 settings.json 進行編輯
{
"files.associations": {
"Dockerfile.dev": "dockerfile",
"Dockerfile.dep": "dockerfile"
}
}
Docker 和 docker-compose 的配置。
- 開発用Dockerfile
FROM golang:1.14.0-alpine3.11
SHELL ["/bin/ash", "-c"]
WORKDIR /go/src/app
COPY ./app ./
EXPOSE 8080
ENV GO111MODULE=on
RUN apk add --no-cache alpine-sdk
# Golang ホットリロード(freshのインストール)
RUN go get github.com/pilu/fresh
# Golang 環境構築(任意)
RUN go get github.com/go-delve/delve/cmd/dlv \
github.com/rogpeppe/godef \
golang.org/x/tools/cmd/goimports \
golang.org/x/tools/cmd/gorename \
sourcegraph.com/sqs/goreturns \
github.com/ramya-rao-a/go-outline \
golang.org/x/tools/gopls@latest
- 本番用Dockerfile
FROM golang:1.14.0-alpine3.11 as builder
WORKDIR /go/src/app
COPY ./app ./
ENV GO111MODULE=on
RUN go mod download
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -o /go/bin/app
FROM alpine:latest
RUN apk --no-cache add ca-certificates
COPY --from=builder /go/bin/app /go/bin/app
ENTRYPOINT [ "/go/bin/app" ]
EXPOSE 8080
- docker-compose
version: '3.7'
services:
app:
container_name: go-app
build:
context: .
# Remote Containerが立ち上がるまで待機
dockerfile: docker/golang/Dockerfile.dev
ports:
- 8080:8080
volumes:
- ./app:/go/src/app:cached
command: /bin/ash -c "while sleep 1000; do :; done"
2. 远程容器的配置
安装
如果您没有安装,请从 Remote-Containers 进行安装。
筹备或准备
请从 ‘docker-compose.yml’ 中进行选择。
选择后,将创建.devcontainer目录并存储配置文件。
设定
.devcontainer
├── devcontainer.json
└── docker-compose.yml
首先,由于docker-compose.yml已经被创建,所以请删除.devcontainer内的docker-compose.yml文件。
请执行以下命令以删除文件。
$ rm .devcontainer/docker-compose.yml
接下来,我们要编辑devcontainer.json文件。
{
"name": "go",
"dockerComposeFile": [
"../docker-compose.yml"
],
"service": "app",
"workspaceFolder": "/go/src/app",
"settings": {
"terminal.integrated.shell.linux": "/bin/ash",
"go.gopath": "/go"
},
"extensions": [
"ms-vscode.go",
],
"shutdownAction": "stopCompose"
}
3. 热重载的配置
備妥
首先,创建一个用于开发Go应用程序的工作目录。
然后,创建一个用于热重载的fresh配置文件。
顺便说一句,您无需创建配置文件,这是可选的!
请执行下面的命令。
$ mkdir app
$ cd app
# /go-work/app
$ touch .fresh.conf
设定
root: .
tmp_path: ./tmp
build_name: runner-build
build_log: runner-build-errors.log
valid_ext: .go, .tpl, .tmpl, .html
no_rebuild_ext: .tpl, .tmpl, .html
ignored: assets, tmp
build_delay: 600
colors: 1
log_color_main: cyan
log_color_build: yellow
log_color_runner: green
log_color_watcher: magenta
log_color_app:
上述的设定是从模板中引用的。
细节设定则是可选的!
4. 启动开发环境
好了,现在我们终于要启动容器了。
请从VSCode中点击左下角的图标。
然后,打开命令面板,然后搜索并选择”在容器中重新打开”。
然后,屏幕将切换。
在此时,Docker镜像将被创建,并且容器将自动启动。
启动可能需要一些时间,请稍等…
过了一会儿,容器就会与远程主机连接并切换到工作目录。
在VSCode左下角的图标应该也发生了变化。
在VSCode上打开终端时,会切换到容器内的终端。
/go/src/app #
5. 确认开发环境的运行情况
我們將在容器內進行工作。
為了確認熱重載的運作,我們將開發一個Go程式。
创建 main.go
创建用于开发的文件。
touch main.go
go mod init main
接下来我们将在main.go文件中创建一个简单的Web服务器。
// ...省略
func init() {
http.HandleFunc("/", index)
}
func index(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Hello World")
}
func main() {
fmt.Print("Server Start")
if err := http.ListenAndServe(":8080", nil); err != nil {
panic(err)
}
}
执行
我将运行main.go,但这次将使用fresh来执行。
虽然可以在VSCode容器内执行,但是由于我想在开发时使用它,所以这次我会在另一个终端中执行。
在另一个终端中进入容器,并启动热重载功能。
$ docker exec -it go-app /bin/ash
# コンテナ内: /go/src/app
fresh -c .fresh.conf
由于 main.go 被执行,我们开始确认工作。
确定
确认可以在浏览器或终端中进行确认。
-
- ブラウザの場合は、http://localhost:8080 にアクセス
- ターミナルの場合は、curl http://localhost:8080 を実行
如果收到“Hello World”,说明已成功启动。
改变
请继续保持 fresh 的运行状态,然后返回到 VSCode,以确认热重载是否正常启动。
请在VSCode上修改并保存main.go文件。
func index(w http.ResponseWriter, r *http.Request) {
- fmt.Fprint(w, "Hello World")
+ fmt.Fprint(w, "Hello Golang")
}
保存后,请再次进行确认工作。
如果返回了Hello Golang,那么热重载已成功启动。
6. 启动正式环境
只需要构建和运行Docker容器即可在生产环境中使用。
建立形象
$ docker build -t go-app -f ./docker/golang/Dockerfile.dep .
容器运行
$ docker run --name go-app go-app -p 8080:8080 -d . /bin/ash