一、 前言
docker
就不在這裏介紹了,相關的文檔已經很完善,中文文檔 Docker —— 從入門到實踐 寫的很棒,推薦去看看。
docker
基於 Golang
開發,已經不用解釋了,而 Golang
天生適合運行在 docker
容器中,卻不是這個原因,這得益於:Golang
的靜態編譯,當在編譯的時候關閉 cgo
的時候,可以完全不依賴系統環境。
二、 Golang
代碼
我們打算在 docker
中測試 Golang
,所以先編寫一個 Golang
的測試代碼。
新建文件:vi main.go
package main
import (
"fmt"
"io/ioutil"
"net/http"
"os"
)
func main() {
resp, err := http.Get("https://www.baidu.com")
check(err)
body, err := ioutil.ReadAll(resp.Body)
check(err)
fmt.Println(len(body))
}
func check(err error) {
if err != nil {
fmt.Println(err)
os.Exit(1)
}
}
這是一個簡單的程序,拉取百度的頁面,並計算頁面的字節大小。
需要注意的時,這裏採用了
https
,這裏埋下一個伏筆,後面解釋。
三、 編寫 dockerfile
1. 基於完整鏡像
Docker官方提供了Golang
各版本的鏡像: Official Repository - golang.
新建文件:vi dockerfile
FROM golang:latest
RUN mkdir /app
ADD . /app/
WORKDIR /app
RUN go build -o main .
CMD ["/app/main"]
Docker的鏡像必須基於某個鏡像開始,然後開始創建新的鏡像,這裏基於
golang:latest
開始創建,在鏡像裏創建/app
文件夾,並將當前所在文件夾內所有內容添加到鏡像內的/app
文件內,將鏡像內的/app
設置爲容器工作目錄(這裏不可使用RUN cd /app
切換當前工作目錄); 然後編譯當前目錄下Golang
代碼,然後使用CMD
命令運行剛纔編譯出的程序。
具體命令解釋查看:Dockerfile 指令詳情
1) 當前目錄下文件
admin@dingdayu-DS:/volume1/docker/docker-golang$ ls
dockerfile main.go
2) 編譯鏡像
sudo docker build -t golang-latest-app .
受制於網絡和機器的性能,編譯鏡像,竟然花了20多分鐘。。。
鏡像編譯完成,完整大小739M,對於線上的部署,無論是編譯時間還是大小都是不合適的,下面的
scratch
鏡像,用來解決這個問題。
sudo docker run -it --rm --name my-golang-app golang-latest-app
執行鏡像,查看效果:
2. 基於scratch
鏡像
scratch
是一個特殊的鏡像,它是一個虛擬鏡像,也就是一個空白鏡像;利用Golang
的靜態化編譯無依賴性,可以大幅度減少編譯時間和鏡像大小。
1) 編譯Golang
基於scratch
必須先打包,然後才能進行運行。
CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .
GOOS=linux
是將交叉編譯的目標設置爲Linux
,這樣你在Mac
或者Win
下也不會出現問題。cgo
是爲了在靜態編譯中導入net
2) 編輯dockerfile
修改文件:vi dockerfile
FROM scratch
RUN mkdir /app
ADD main /app/
WORKDIR /app
CMD ["/app/main"]
3) 編譯鏡像
sudo docker build -t golang-scratch-app .
scratch
和golang:latest
的大小差了730多兆。。。。
4) 空白鏡像掛載文件
啓動鏡像
sudo docker run -it --rm --name my-golang-scratch golang-scratch-app
你會發現提示:
Get https://www.baidu.com: x509: failed to load system roots and no roots provided
這是一個非常常見的問題:爲了進行SSL請求,我們需要SSL根證書。
5) 掛載文件
根據操作系統,這些證書可以在許多不同的地方。如果您查看Go
的x509
庫,可以查看Go
搜索的所有位置。對於許多Linux發行版,這是/etc/ssl/certs/cacert.pem
。首先,我們將把我們的機器(或Linux VM
或在線證書提供者)的cacert.pem
複製到我們的存儲庫中。然後,我們將在Docker
文件中添加一個ADD,將這個文件放在Go所期望的位置:
下載 cacert.pem
到當前工作目錄:
wget https://curl.haxx.se/ca/cacert.pem
再次編輯dockerfile
FROM scratch
ADD cacert.pem /etc/ssl/certs/
ADD main /
CMD ["/main"]
6) 執行鏡像
sudo docker run -it --rm --name my-golang-scratch golang-scratch-app
完美執行!
四、 關鍵點
- Dockerfile 指令詳情
- 鏡像編譯命令:
sudo docker build -t golang-latest-app .
=>golang-latest-app 爲鏡像名
- 容器啓動命令:
sudo docker run -it --rm --name my-golang-app golang-latest-app
=>my-golang-app 爲容器名,golang-latest-app 爲鏡像名
- Golang的靜態編譯:
CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .