我尝试在Golang中使用Docker启动web服务器

我最近想使用golang来进行并行批处理。而且我想要并行处理大量数据,所以我想使用可以轻松增加资源的docker。
如果只是在docker上启动和开发golang,那么并不是太困难。但是,当我想要在docker上启动守护进程时,就必须熟练掌握docker命令,所以我打算在docker的圣诞节日历上悄悄地发布一下。

1. 准备包含golang的Docker。

有一个由社区管理的 Docker 镜像,我要拿来用。

$ docker pull golang

为了在Docker内进行开发,安装vim。

$ docker run -it golang
(dockerコンテナ内)
# apt-get update && apt-get upgrade
# apt-get vim

c. 提交并推送 Docker

$ docker commit [container ID] [dockerhub username]/golang
$ docker push [container ID]

d. 从新创建的映像中再次启动容器

$ docker run -it [dockerhub username]/golang

用Go语言编写服务器脚本。

当运行 docker run -it 进入 docker 时,我认为会进入 root 用户的 /go 目录。在该目录下,我创建了以下类似的 server.go 文件。

package main
import (
    "fmt"
    "net/http"
)

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":8080", nil)
}

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Your url path is %s", r.URL.Path[1:])
}

3. 启动服务器

我试图在2状态下停止或附加容器,并添加端口映射,但是只找到了先提交镜像再重新启动新容器的方法。

为了进行端口映射,需要再次commit image。

まずはコンテナから抜ける
# exit

commit (pushしてもよい)
$ docker commit [container ID] [dockerhub username]/goserver

b. 在新创建的镜像中添加了端口映射规则后,在守护模式下启动。

$ docker run -p 8080:8080 -td [dockerhub username]/goserver

c. 进入启动的容器

$ docker exec -it [container ID] /bin/bash

执行服务器脚本

# go run server.go

e. 访问http://localhost:8080

使用Dockerfile来搭建服务器。

在前3个项目中,我已经能够使用Docker搭建Go的Web服务器了。
但是,我遇到了两个问题:
1. 它已经包含了vim编辑器。
2. 它还包含了src文件(因为Go是一种编译语言,所以只需要执行文件就可以了)。

在构建Docker镜像时,我们希望只包含必要的部分,并保持尽可能简单。否则,会浪费启动时间和多个容器的资源。

从docker镜像中移除vim。

我需要一个编辑器才能进行开发,但是除了Vim之外,我想抛弃它。
这次我试着将在本地创建的server.go文件放入Docker中来组织。

准备Dockerfile。

FROM golang
MAINTAINER vankobe
ADD . /go/src/
EXPOSE 8080
CMD ["/usr/local/go/bin/go", "run", "/go/src/server.go"]

b. 运行build

# ビルドを実行するフォルダの中
$ ls
Dockerfile server.go

$ docker build .
...
(実行ログ)
...
Successfully built a176df9f6c3e

c. 使用已构建的镜像来启动容器
(如果容器启动失败,可能是CMD参数等设置有误。可以使用docker logs查看日志以查找问题的原因)

$ docker run -p 8080:8080 -td a176df9f6c3e 

访问 http://localhost:8080

将4.2中的源代码文件从Docker镜像中排除。

由于 Go 是一种编译语言,所以只需有编译后的可执行文件即可。
这次我尝试使用 GoLang 图像创建的可执行文件,将其复制到 Alpine 镜像上并执行。

a. 更改文件名
我之前将 server.go 放在 /go/src 中,现在我会将 main.go 放在 /go/src/server 中。
首先,将 server.go 重命名为 main.go。

$ mv server.go main.go
$ ls
Dockerfile main.go

b. 准备一个Dockerfile

FROM golang
MAINTAINER vankobe
ADD . /go/src/server
RUN go install server

FROM alpine
COPY --from=0 /go/bin/server .
ENV PORT 8080
CMD ["./server"]

c. 进行构建

$ docker build .
...
(実行ログ)
...
Successfully built 19ace85b6019

使用构建的镜像启动容器。

$ docker run -p 8080:8080 -td 19ace85b6019 

e. 访问 http://localhost:8080

当您进入启动的容器中,您会发现除了可执行文件外,其他文件并没有被复制过。

最后

AWS和GCP都加强了对容器的支持功能。
由于GCP的container-engine-samples中有许多示例,我打算尝试一下。
(当我在写的过程中,发现这个示例与上述样本内的hello-app几乎相同。我感到有点失望。)

用Docker享受生活。

附录

在当前目录中进行ADD操作会导致Dockerfile也被复制,因此建议准备.dockerignore。

Dockerfile
广告
将在 10 秒后关闭
bannerAds