一、 前言
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
下也不会出现问题。-installsuffix cgo
是为了在静态编译中导入net
2) 编辑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 .