之前写过一个文档 《从源代码构建 Go 开发环境》, 今天增加一个使用 Docker 构建 golang 环境的文档。

文章目录:


    1. 安装 Docker

    1. 配置 Docker 镜像仓库的地址

    1. 下载 golangDocker 镜像

    1. 使用 golang 镜像

    1. golangDocker 镜像的一种使用方式

    1. 一个例子

    1. 方便以后查阅和直接使用,完整命令如下

1. 安装 Docker

我当前使用的系统环境是 CentOS7 ,安装 Docker 使用的命令是 yum install docker*。至于其它系统,可以到百度查找其对应的安装方式。

2. 配置 Docker 镜像仓库的地址

目前来说,直接访问 Docker 官网的 DockerHub 会比较慢, 不过幸好现在国内出现了一些 DockerHub 的加速网站。 下面使用 ustc 加速器。

修改文件 /etc/docker/daemon.json,将其内容修改为

  1. {
  2. "registry-mirrors": ["https://docker.mirrors.ustc.edu.cn"]
  3. }

配置完成后,重启 Docker 服务:systemctl restart docker

这样就可以使用 https://docker.mirrors.ustc.edu.cn 加速器了。

如果 ustc 的加速器速度不够快,还可以尝试一下其它的加速器,具体请参考这里 Docker 镜像加速器

3. 下载 golangDocker 镜像

现在就可以下载 golangDocker 镜像了。

执行命令 docker search golang 就可以查询 golang 镜像的信息了。

  1. $ docker search golang
  2. INDEX NAME DESCRIPTION STARS OFFICIAL AUTOMATED
  3. docker.io docker.io/golang Go (golang) is... 1649 [OK]
  4. docker.io docker.io/circleci/golang Go (golang) is... 8
  5. docker.io docker.io/resin/artik710-golang Go (golang) is... 1
  6. docker.io docker.io/resin/artik10-golang Go (golang) is... 0

可以看到,在查询结果中排名第一的,STARS 数量最多, 并且 OFFICIAL 选项下面是 OK ,说明是官方的,所以理论上应该是更可信的。 所以我们就选择使用第一个了。

执行命令 docker pull docker.io/golang 来下载 golang 的官方镜像吧。

  1. [root@fengbo golang]$ docker pull docker.io/golang
  2. Using default tag: latest
  3. Trying to pull repository docker.io/library/golang ...
  4. latest: Pulling from docker.io/library/golang
  5. 723254a2c089: Extracting [===============================> ] 40.83 MB/45.12 MB
  6. abe15a44e12f: Download complete
  7. 409a28e3cc3d: Download complete
  8. 503166935590: Download complete
  9. abe52c89597f: Download complete
  10. ce145c5cf4da: Downloading [===============> ] 31.36 MB/104.3 MB
  11. 96e333289084: Download complete
  12. 39cd5f38ffb8: Download complete
  13. 39cd5f38ffb8: Pulling fs layer

下载好了之后,查看一下镜像的信息 docker images golang

  1. [root@fengbo golang]$ docker images golang
  2. REPOSITORY TAG IMAGE ID CREATED SIZE
  3. docker.io/golang latest 138bd936fa29 4 weeks ago 733.3 MB

4. 使用 golang 镜像

执行命令 docker run -it --rm golang bash ,测试一下刚刚下载的 golang 镜像

  1. [root@fengbo golang]$ docker run -it --rm golang bash
  2. root@9e46b1255f4b:/go# go version
  3. go version go1.9.2 linux/amd64

可以看到,最新的是 1.9.2 版本的。

查看进到容器后的默认目录

  1. root@9e46b1255f4b:/go# pwd
  2. /go

看来是在 /go 目录下面。

不过因为我们在创建容器的时候加了 --rm 参数,所以当我们执行 exit 命令退出容器的时候,这个临时容器会被删除。

那我们如何使用这个 golang 的镜像来工作呢?

5. golangDocker 镜像的一种使用方式

首先,如果我们把文件直接写在 Docker 容器里面的话,那么数据是无法持久化的。 即使可以使用 docker cp 命令这样的方式把我们的文件复制到容器内部, 或者把文件从容器中复制出来,但是在操作的时候仍会有很多不方便的地方。

而且,在 golang 的镜像中进行 build 操作的时候,程序依赖的第三方包, 会被下载到容器的 /go 目录下面。如果每次容器都删除, 或者每次创建新的容器的时候,都需要从网络上拉取一次第三方包。 如果网速快的话还好,否则时间浪费的有点儿严重。

所以,我们要把主机的目录映射到容器中,这样就可以把文件进行持久化了。

我们可以使用 docker 命令的 -v 参数,把主机的目录映射到容器中。 不过只使用 -v 参数的话,在容器内部操作目录会有权限限制, 所以还需要增加 --privileged 参数给容器放权。

  1. [root@fengbo golang]$ pwd # 查看当前所在的目录
  2. /root/golang
  3. [root@fengbo golang]$ ls -l # 查看当前目录下的子目录和文件等
  4. total 0
  5. drwxrwxrwx. 2 root root 6 Jan 10 01:19 code
  6. drwxrwxrwx. 2 root root 6 Jan 10 01:20 go
  7. [root@fengbo golang]$ docker run \ # 执行 docker 命令,创建一个新的容器并运行这个容器
  8. > -it \ # 使用交互模式
  9. > --rm \ # 当退出这个容器时,系统自动删除这个容器
  10. > -v /root/golang/go:/go \ # 把主机的目录 '/root/golang/go' 映射为容器内的目录 '/go'
  11. > -v /root/golang/code:/code \ # 把主机的目录 '/root/golang/code' 映射为容器内的目录 '/code'
  12. > --privileged \ # 给这个容器超级权限,否则无法操作上面映射进去的两个目录
  13. > docker.io/golang \ # 基于镜像 'docker.io/golang' 创建容器
  14. > bash # 在容器内执行命令 'bash'
  15. > root@fe6be9f3b22d:/go# # 已经进入容器了

我们可以在容器的两个目录 /go/code 里面创建一些文件, 然后返回主机查看。

  1. root@bb2942f33960:/go# echo "hello" > /go/h.txt # 在容器内,创建文件 '/go/h.txt' 并写入数据
  2. root@bb2942f33960:/go# echo "world" > /code/w.txt # 在容器内,创建文件 '/code/w.txt' 并写入数据
  3. root@bb2942f33960:/go# exit # 退出容器
  4. exit
  5. [root@fengbo golang]# find # 已经回到主机了。在主机的 '/root/golang' 目录下查看文件
  6. .
  7. ./code
  8. ./code/w.txt # 可以看到文件 'w.txt'
  9. ./go
  10. ./go/h.txt # 以及文件 'h.txt'
  11. [root@fengbo golang]# cat go/h.txt
  12. hello
  13. [root@fengbo golang]# cat code/w.txt
  14. world

使用上面的方法,每次创建了容器,都会把主机上指定的目录映射到容器中,修改的数据也会反映到主机上。

6. 一个例子

在主机的目录 /root/golang/code 里面创建一个 go 源码文件:aha.go,其内容如下:

  1. package main
  2. import "fmt"
  3. func main() {
  4. fmt.Println("Hello Docker !")
  5. }

接下来启动容器:

  1. [root@fengbo code]$ docker run \
  2. > -it \
  3. > --rm \
  4. > -v /root/golang/go:/go \
  5. > -v /root/golang/code:/code \
  6. > --privileged \
  7. > docker.io/golang bash
  8. root@de6baf248f0c:/go# # 进入容器内了

现在已经进入容器中了。接下来进入目录 /code,查看文件:

  1. root@de6baf248f0c:/go# cd /code/ # 进入容器内的目录 '/code'
  2. root@de6baf248f0c:/code# ls
  3. aha.go # 可以看到在主机上创建的文件 'aha.go'

使用 go build 命令编译我们刚刚的源码文件;

  1. root@de6baf248f0c:/code# go build aha.go # 编译 'aha.go'
  2. [root@fengbo code]# ls # 查看编译命令执行后的文件状态,多了一个 'aha'
  3. aha aha.go

说明正确编译了。现在回到主机上,执行以下这个编译完成的二进制文件:

  1. root@de6baf248f0c:/code# exit # 退出容器
  2. exit
  3. [root@fengbo code]# ls # 此时已经回到了主机,查看主机目录 '/root/golang/code' 下的文件
  4. aha aha.go # 多了一个 'aha',这个就是在容器中编译的文件了
  5. [root@fengbo code]# ./aha # 在主机上执行编译完成的文件
  6. Hello Docker ! # 执行结果
  7. [root@fengbo code]#

有了 Docker 就是方便不少,前提是网速要快。

7. 方便以后查阅和直接使用,完整命令如下

开启容器

  1. docker run -it --rm -v /root/golang/go:/go -v /root/golang/code:/code --privileged docker.io/golang bash