文档章节

Golang的docker尝试

dingdayu
 dingdayu
发布于 2017/10/20 20:26
字数 1088
阅读 638
收藏 25

一、 前言

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 .

输入图片说明

scratchgolang: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) 挂载文件

根据操作系统,这些证书可以在许多不同的地方。如果您查看Gox509库,可以查看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 .

五、 链接

  1. Building Minimal Docker Containers for Go Applications
  2. [创建超小的Golang docker 镜像](http://colobu.com/2015/10/12/create-minimal-golang-docker-images/

© 著作权归作者所有

dingdayu

dingdayu

粉丝 34
博文 119
码字总数 59598
作品 3
海淀
后端工程师
私信 提问
加载中

评论(3)

dingdayu
dingdayu 博主

引用来自“抢小孩糖吃”的评论

没看懂,文章的目的是说go运行在docker系统中。解除cgo,能够让docker系统最小化么?

如果可以,还请对文章提些改进建议,今年就是要积累这方面的技能的,感谢!
dingdayu
dingdayu 博主

引用来自“抢小孩糖吃”的评论

没看懂,文章的目的是说go运行在docker系统中。解除cgo,能够让docker系统最小化么?

确实有点没有主旨,不过确实是你所说的意思,是便实验便写的,整理的不是太好,感觉或许累赘。不过最近忙考试,没时间也没心思好好整理,回头再梳理一遍。
抢小孩糖吃
抢小孩糖吃
没看懂,文章的目的是说go运行在docker系统中。解除cgo,能够让docker系统最小化么?
Go应用程序使用dockerfile multi-stage的问题

场景重现 一个简单的go应用,准备通过docker部署,为了减少运行时的镜像和容器体积,使用了构建: dockefile生成构建是正常,运行container的时候会报错: 问题原因 据说是镜像和的操作系统虽然都是...

taadis
2018/02/15
93
3
[J+]移动互联网沙龙——docker构建与golang实战

春光易虚度,不如早相逢!大好的时光,何不出来感受下济南春天的移动互联网氛围?借这美好的季节,新的一期技术沙龙如约而至,本期活动依然聚焦那些有意思的话题,当然不仅仅限于视野的拓展,...

缪斯的情人
2015/04/12
4.1K
24
[J+]移动互联网沙龙——docker构建与golang实战

春光易虚度,不如早相逢!大好的时光,何不出来感受下济南春天的移动互联网氛围?借这美好的季节,新的一期技术沙龙如约而至,本期活动依然聚焦那些有意思的话题,当然不仅仅限于视野的拓展,...

缪斯的情人
2015/04/12
81
0
Hyperledger Fabric(v1.1.0)编译时遇到的问题

Hyperledger Fabric(v1.1.0)编译时遇到的问题 0. 编译过程的坑 编译时,按照如下顺序编译 make release,编译源码生成二进制文件 make docker,生成一系列的docker镜像 第一步没什么问题,第...

gexin1023
2018/07/05
0
0
理解Docker的多阶段镜像构建

理解Docker的多阶段镜像构建 Tony Bai2017-11-111 阅读 centosbuilderBuild Docker 技术从 2013年诞生 到目前已经4年有余了。对于已经接纳和使用 Docker技术 在日常开发工作中的开发者而言,...

Tony Bai
2017/11/11
0
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周日乱弹 —— 我,小小编辑,食人族酋长

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @宇辰OSC :分享娃娃的单曲《飘洋过海来看你》: #今日歌曲推荐# 《飘洋过海来看你》- 娃娃 手机党少年们想听歌,请使劲儿戳(这里) @宇辰OSC...

小小编辑
今天
446
10
MongoDB系列-- SpringBoot 中对 MongoDB 的 基本操作

SpringBoot 中对 MongoDB 的 基本操作 Database 库的创建 首先 在MongoDB 操作客户端 Robo 3T 中 创建数据库: 增加用户User: 创建 Collections 集合(类似mysql 中的 表): 后面我们大部分都...

TcWong
今天
4
0
spring cloud

一、从面试题入手 1.1、什么事微服务 1.2、微服务之间如何独立通讯的 1.3、springCloud和Dubbo有哪些区别 1.通信机制:DUbbo基于RPC远程过程调用;微服务cloud基于http restFUL API 1.4、spr...

榴莲黑芝麻糊
今天
3
0
Executor线程池原理与源码解读

线程池为线程生命周期的开销和资源不足问题提供了解决方 案。通过对多个任务重用线程,线程创建的开销被分摊到了多个任务上。 线程实现方式 Thread、Runnable、Callable //实现Runnable接口的...

小强的进阶之路
昨天
7
0
maven 环境隔离

解决问题 即 在 resource 文件夹下面 ,新增对应的资源配置文件夹,对应 开发,测试,生产的不同的配置内容 <resources> <resource> <directory>src/main/resources.${deplo......

之渊
昨天
8
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部