五分鐘用 Docker 快速搭建 Go 開發環境

KevinYan發表於2020-01-30


挺早以前在我寫過一篇用 Docker搭建LNMP開發環境的文章:用Docker搭建Laravel開發環境,裡面詳細介紹了將 nginxmysqlphp三個容器用 docker-compose編排成 LNMP開發環境的步驟,今天來說說怎麼用 Docker快速搭建 Go語言專案的開發環境。

因為靠Go本身自帶的標準庫就能實現高效能的 HTTP伺服器,不熟悉的同學買它,呃說錯了,看它:深入學習用Go編寫HTTP伺服器。所以用 Docker 構建 Go的開發環境比構建 LNMP 開發環境要簡單很多,如果沒有太多定製化要求甚至都不用寫 Dockerfile自己構建映象,直接使用官方的 golang映象即可。

獲取Docker映象

我們使用官方最新穩定版的映象 golang:latest, 獲取映象前先得確保你電腦上執行了 Docker 客戶端,沒有的去官網下載一下吧這裡就不多說了。

下載dockerHub上的映象直接使用命令:

docker pull golang

下載完映象後用映象執行一個容器:

docker run --rm -it --name go-http-demo golang bash

上面這個命令用映象 golang建立了一個名為 go-http-demo的容器,在容器中建立了一個 Bash會話。--rm選項指定容器退出後自動移除容器。

執行完上面的命令後我們就進入了執行的容器中,執行 go version 檢視以下 go的版本:

root@965425c5bdcf:/go# go version 
go version go1.13.6 linux/amd64
root@965425c5bdcf:/go# 

你可以根據自己的需要在https://hub.docker.com/_/golang 中查詢自己需要的版本的 golang映象執行容器。

在容器中執行Go專案

我們使用《深入學習用Go編寫HTTP伺服器》中最後寫的支援優雅關停服務的 HTTPServer的原始碼,將它放到 Docker容器裡伺服宿主機的請求。HTTP Server的原始碼如下,想探究程式碼具體怎麼實現的看連結裡的文章就好了。

package main

import (
    "context"
    "fmt"
    "log"
    "net/http"
    "os"
    "os/signal"
    "syscall"
)

func main() {
    mux := http.NewServeMux()
    mux.Handle("/", &helloHandler{})

    server := &http.Server{
        Addr:    ":8080",
        Handler: mux,
    }

    // 建立系統訊號接收器
    done := make(chan os.Signal)
    signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
    go func() {
        <-done

        if err := server.Shutdown(context.Background()); err != nil {
            log.Fatal("Shutdown server:", err)
        }
    }()

    log.Println("Starting HTTP server...")
    err := server.ListenAndServe()
    if err != nil {
        if err == http.ErrServerClosed {
            log.Print("Server closed under request")
        } else {
            log.Fatal("Server closed unexpected")
        }
    }
}

type helloHandler struct{}

func (*helloHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello World")
}

把原始碼放在本地電腦的 /Code/go/src/example.com/http-demo/main.go中,檔案目錄你們做的時候根據自己的情況寫路徑。

接下來就要把這個程式碼放到容器裡去執行了,切到程式碼目錄裡執行如下命令:

docker run --rm -it --name go-http-demo \
  -v $PWD:/go/src/example.com/go-http-demo \
  -p 8000:8080
  golang

-v選項允許我們掛載多個本地目錄或者資料捲到容器中,更改會在容器內外相互同步,上面的命令將 /Code/go/src/example.com/go-http-demo/掛載到了容器的 /go/src/example.com/go-http-demo

-p指定主機和容器的埠對映,因為程式碼裡 HTTP服務是監聽 8080埠的,所以我們將主機的 8000埠和容器的 8080埠做了對映。

執行完上面的命令,我們切換到到容器裡的 Bash會話,切到程式碼目錄執行 go run main.go後,在自己的電腦上開啟瀏覽器訪問 http:localhost:8080看到下圖中的頁面就證明伺服器在容器裡已經正常執行起來了。

用 docker-compose 管理容器

通過上面的內容我們已經用 Docker構建好了一個 Go的開發環境,不過每次打那堆命令,還要進容器執行 go命令啟動程式太費事了,我們用 docker-compose把上面那些流程自動化一下。

在專案程式碼根目錄建立docker-compose.yml

version: '3'
services:
  app:
    image: golang:latest
    volumes:
      - $PWD:/go/src/examplecom/http_demo
    ports:
      - "8000:8080"
    command: go run /go/src/examplecom/http_demo/main.go

如果你們專案裡不允許就找個目錄放這個檔案,我自己就是單獨有個目錄裡面放了好幾個專案的 Docker配置檔案,有 PHP專案的也有 Go專案的。

上面的編排檔案裡只定義了一個叫 app的服務,其他的也很容易理解我就不說了,唯一要注意的一點就是如果 yml檔案在專案外 volumes裡的配置就換成絕對路徑不要用 $PWD

接下來啟動 docker-compose:

docker-compose up -d

如果啟動不成功先不要在 daemon模式下執行把 -d去掉,就能看到具體什麼錯誤,等除錯正常了再後臺啟動。

程式碼有修改後,需要重新編譯專案,針對我們的容器執行下面的命令即可

docker-compose restart

想要進入執行的容器中執行操作使用命令:

docker exec -it <container name> bash

給我們建立的 app傳送 go test命令讓它在容器內執行:

docker-compose exec app go test

最近想嘗試把老專案換成用 go mod管理,專案還是在用 go1.12所以我就先用 Docker搭環境,容器隔離的環境怎麼瞎折騰也沒事。今天做的這個開發環境還是很簡單的,沒有用 Dockerfile自己建立映象, docker-compose配置檔案裡的設定也很簡單,後面用著不順手有更新了我再推送。下面的兩篇老文章對 Docker映象和 docker-compose講的都比較深入,例子也多,感興趣的可以看看。

教你如何做出想要的PHPDocker映象

用Docker搭建Laravel開發環境

如果自己搭建環境的時候遇到什麼問題了,可以在這裡留言反饋,也可以在我的公眾號裡留言反饋。

本作品採用《CC 協議》,轉載必須註明作者和本文連結

公眾號:網管叨bi叨 | Golang、PHP、Laravel、Docker等學習經驗分享

相關文章