为什么需要Docker?
使用docker的主要目标是容器化。也就是为你的应用程序提供一致的环境,而不依赖于它运行的主机。
想象一下你是否也会遇到下面这个场景,你在本地开发了你的应用程序,它很可能有很多的依赖环境或包,甚至对依赖的具体版本都有严格的要求,当开发过程完成后,你希望将应用程序部署到web服务器。这个时候你必须确保所有依赖项都安装正确并且版本也完全相同,否则应用程序可能会崩溃并无法运行。如果你想在另一个web服务器上也部署该应用程序,那么你必须从头开始重复这个过程。这种场景就是Docker发挥作用的地方。
对于运行我们应用程序的主机,不管是笔记本电脑还是web服务器,我们唯一需要做的就是运行一个docker容器平台。从以后,你就不需要担心你使用的是MacOS,Ubuntu,Arch还是其他。你只需定义一次应用,即可随时随地运行。
Docker部署示例
准备代码
这里我先用一段使用net/http
库编写的简单代码为例讲解如何使用Docker进行部署,后面再讲解稍微复杂一点的项目部署案例。
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/", hello)
server := &http.Server{
Addr: ":8888",
}
fmt.Println("server startup...")
if err := server.ListenAndServe(); err != nil {
fmt.Printf("server startup failed, err:%v\n", err)
}
}
func hello(w http.ResponseWriter, _ *http.Request) {
w.Write([]byte("hello liwenzhou.com!"))
}
上面的代码通过8888
端口对外提供服务,返回一个字符串响应:hello liwenzhou.com!
。
创建Docker镜像
镜像(image)包含运行应用程序所需的所有东西——代码或二进制文件、运行时、依赖项以及所需的任何其他文件系统对象。
或者简单地说,镜像(image)是定义应用程序及其运行所需的一切。
编写Dockerfile
要创建Docker镜像(image)必须在配置文件中指定步骤。这个文件默认我们通常称之为Dockerfile
。(虽然这个文件名可以随意命名它,但最好还是使用默认的Dockerfile
。)
现在我们开始编写Dockerfile
,具体内容如下:
注意:某些步骤不是唯一的,可以根据自己的需要修改诸如文件路径、最终可执行文件的名称等
FROM golang:alpine
# 为我们的镜像设置必要的环境变量
ENV GO111MODULE=on \
GOPROXY=https://goproxy.cn,direct \
CGO_ENABLED=0 \
GOOS=linux \
GOARCH=amd64
# 移动到工作目录:/build
WORKDIR /build
# 将代码复制到容器中
COPY . .
# 将我们的代码编译成二进制可执行文件app
RUN go build -o app .
# 移动到用于存放生成的二进制文件的 /dist 目录
WORKDIR /dist
# 将二进制文件从 /build 目录复制到这里
RUN cp /build/app .
# 声明服务端口
EXPOSE 8888
# 启动容器时运行的命令
CMD ["/dist/app"]
Dockerfile解析
From
我们正在使用基础镜像golang:alpine
来创建我们的镜像。这和我们要创建的镜像一样是一个我们能够访问的存储在Docker仓库的基础镜像。这个镜像运行的是alpine Linux发行版,该发行版的大小很小并且内置了Go,非常适合我们的用例。有大量公开可用的Docker镜像,请查看hub.docker.com/_/golang
Env
用来设置我们编译阶段需要用的环境变量。
WORKDIR,COPY,RUN
这几个命令做的事都写在注释里了,很好理解。
EXPORT,CMD
最后,我们声明服务端口,因为我们的应用程序监听的是这个端口并通过这个端口对外提供服务。并且我们还定义了在我们运行镜像的时候默认执行的命令CMD ["/dist/app"]
。
构建镜像
在项目目录下,执行下面的命令创建镜像,并指定镜像名称为goweb_app
:
docker build . -t goweb_app
等待构建过程结束,输出如下提示:
...
Successfully built 90d9283286b7
Successfully tagged goweb_app:latest
现在我们已经准备好了镜像,但是目前它什么也没做。我们接下来要做的是运行我们的镜像,以便它能够处理我们的请求。运行中的镜像称为容器。
执行下面的命令来运行镜像:
docker run -p 8888:8888 goweb_app
标志位-p
用来定义端口绑定。由于容器中的应用程序在端口8888上运行,我们将其绑定到主机端口也是8888。如果要绑定到另一个端口,则可以使用-p $HOST_PORT:8888
。例如-p 5000:8888
。
现在就可以测试下我们的web程序是否工作正常,打开浏览器输入http://127.0.0.1:8888
就能看到我们事先定义的响应内容如下:
hello liwenzhou.com!