Go 博客

使用 Docker 部署 Go 服务器

Andrew Gerrand
2014 年 9 月 26 日

简介

本周 Docker 宣布为 Go 及其他主要语言提供了官方基础镜像,为程序员构建 Go 程序容器提供了一种可靠且简便的方法。

在本文中,我们将逐步介绍如何为一个简单的 Go Web 应用程序创建 Docker 容器并将其部署到 Google Compute Engine。如果您不熟悉 Docker,建议您在继续阅读前先阅读 理解 Docker

示例应用程序

在本次演示中,我们将使用 Go 示例仓库中的 outyet 程序,这是一个简单的 Web 服务器,用于报告下一个 Go 版本是否已发布(旨在为 isgo1point4.outyet.org 等站点提供支持)。它除了标准库外没有其他依赖项,运行时也不需要额外的数据文件;对于 Web 服务器来说,这已经算是非常简单了。

使用 “go get” 在您的工作区中获取并安装 outyet

$ go get golang.org/x/example/outyet

编写 Dockerfile

outyet 目录中名为 Dockerfile 的文件替换为以下内容

# Start from a Debian image with the latest version of Go installed
# and a workspace (GOPATH) configured at /go.
FROM golang

# Copy the local package files to the container's workspace.
ADD . /go/src/golang.org/x/example/outyet

# Build the outyet command inside the container.
# (You may fetch or manage dependencies here,
# either manually or with a tool like "godep".)
RUN go install golang.org/x/example/outyet

# Run the outyet command by default when the container starts.
ENTRYPOINT /go/bin/outyet

# Document that the service listens on port 8080.
EXPOSE 8080

这个 Dockerfile 指定了如何构建一个运行 outyet 的容器,从基本依赖项(安装了 Go 的 Debian 系统;官方 golang docker 镜像)开始,然后添加 outyet 包的源代码,构建它,最后运行它。

ADDRUNENTRYPOINT 步骤对于任何 Go 项目来说都是常见的任务。为了简化这个过程,golang 镜像有一个 onbuild 变体,它会自动复制包源代码,获取应用程序依赖项,构建程序,并将其配置为在启动时运行。

使用 onbuild 变体,Dockerfile 要简单得多

FROM golang:onbuild
EXPOSE 8080

构建并运行镜像

outyet 包目录中调用 Docker,使用 Dockerfile 构建镜像

$ docker build -t outyet .

这将从 Docker Hub 获取 golang 基础镜像,将包源代码复制到其中,在其中构建包,并将生成的镜像标记为 outyet

从生成的镜像运行容器

$ docker run --publish 6060:8080 --name test --rm outyet

--publish 标志告诉 docker 将容器的端口 8080 发布到外部端口 6060

--name 标志为我们的容器提供一个可预测的名称,使其更容易使用。

--rm 标志告诉 docker 在 outyet 服务器退出时移除容器镜像。

容器运行后,在 Web 浏览器中打开 http://localhost:6060/,您应该会看到类似这样的内容

(如果您的 docker daemon 在另一台机器上运行(或在虚拟机中),您应该将 localhost 替换为该机器的地址。如果您在 OS X 或 Windows 上使用 boot2docker,您可以使用 boot2docker ip 找到该地址。)

既然我们已经验证了镜像可以工作,请从另一个终端窗口关闭正在运行的容器

$ docker stop test

在 Docker Hub 上创建仓库

Docker Hub 是我们之前拉取 golang 镜像的容器注册表,它提供了一个名为 自动构建 (Automated Builds) 的功能,可以从 GitHub 或 BitBucket 仓库构建镜像。

通过将该 Dockerfile 提交到仓库并为其创建自动构建,任何安装了 Docker 的人都可以通过一个命令下载并运行我们的镜像。(我们将在下一节看到其作用。)

要设置自动构建,请将 Dockerfile 提交到您的 GitHubBitBucket 仓库,在 Docker Hub 上创建一个账户,然后按照创建自动构建的说明操作。

完成后,您可以使用自动构建的名称运行您的容器

$ docker run goexample/outyet

(将 goexample/outyet 替换为您创建的自动构建的名称。)

将容器部署到 Google Compute Engine

Google 提供了容器优化型 Google Compute Engine 镜像,可以轻松启动运行任意 Docker 容器的虚拟机。在启动时,实例上运行的程序会读取一个配置文件,指定要运行哪个容器,获取容器镜像,然后运行它。

创建一个指定要运行的 docker 镜像和要暴露的端口的 containers.yaml 文件

version: v1beta2
containers:
- name: outyet
  image: goexample/outyet
  ports:
  - name: http
    hostPort: 80
    containerPort: 8080

(注意,我们将容器的端口 8080 发布为外部端口 80,这是服务 HTTP 流量的默认端口。同样,您应该将 goexample/outyet 替换为您自动构建的名称。)

使用 gcloud 工具 创建运行容器的 VM 实例

$ gcloud compute instances create outyet \
    --image container-vm-v20140925 \
    --image-project google-containers \
    --metadata-from-file google-container-manifest=containers.yaml \
    --tags http-server \
    --zone us-central1-a \
    --machine-type f1-micro

第一个参数 (outyet) 指定实例名称,方便管理使用。

--image--image-project 标志指定要使用的特殊容器优化系统镜像(原样复制这些标志)。

--metadata-from-file 标志将您的 containers.yaml 文件提供给 VM。

--tags 标志将您的 VM 实例标记为 HTTP 服务器,调整防火墙以在公共网络接口上暴露端口 80。

--zone--machine-type 标志指定运行 VM 的区域和要运行的机器类型。(要查看机器类型和区域列表,请运行 gcloud compute machine-types list。)

完成后,gcloud 命令应打印一些关于实例的信息。在输出中,找到 networkInterfaces 部分以找到实例的外部 IP 地址。几分钟内,您应该就能通过 Web 浏览器访问该 IP,并看到“Go 1.4 发布了吗?”页面。

(要查看新 VM 实例上正在发生什么,您可以使用 gcloud compute ssh outyet 通过 ssh 登录。登录后,尝试运行 sudo docker ps 查看哪些 Docker 容器正在运行。)

了解更多

这只是冰山一角——Go、Docker 和 Google Compute Engine 还有很多其他用途。

要了解更多关于 Docker 的信息,请参阅他们的详尽文档

要了解更多关于 Docker 和 Go 的信息,请参阅官方 golang Docker Hub 仓库以及 Kelsey Hightower 的优化静态 Go 二进制文件的 Docker 镜像

要了解更多关于 Docker 和 Google Compute Engine 的信息,请参阅容器优化型 VM 页面google/docker-registry Docker Hub 仓库

下一篇文章:Google I/O 和 Gopher 夏日嘉年华上的 Go
上一篇文章:常量
博客索引