之前讲了很多原理性的东西,基本上已经把Docker的大概原理阐述了一遍,这次我们就通过运行一个实例,把Docker容器用起来。
我们先自己用Go语言写一个简单的web服务器程序hello.go,然后再用Docker把它跑起来,Go程序源码如下:
package main
import (
"io"
"net/http"
)
func hello(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "Hello world!")
}
func main() {
http.HandleFunc("/", hello)
http.ListenAndServe(":8000", nil)
}
这个程序非常简单,就是启动一个简单的web服务器程序并监听8000端口,当使用浏览器访问IP:8000/
这个地址的时候,程序会给浏览器返回Hello world!
想把上面的程序通过Docker的方式运行起来,就需要制作一个Docker镜像,而制作Docker镜像非常方便的方式就是使用Dockerfile,Dockerfile在这里应该做的事主要是两个:
- 将上面的Go程序编译
- 把编译好的Go程序封装在Docker镜像中
上面说到的两个步骤,是可以直接通过一个Dockerfile来实现的,也就是Dockerfile的多阶段构建功能(multi-stage), Dockerfile内容如下:
# 使用官方提供的 GO 镜像来编译我们的程序
FROM golang:1.17
# 将工作目录切换为 /compile
WORKDIR /compile
# 将 hello.go 程序复制到镜像中的/compile目录下
COPY hello.go /compile
# 编译生成 hello 可执行程序
RUN GOOS=linux go build hello.go
# 使用alpine作为基础镜像
FROM alpine:3.15.0
# 将工作目录切换为 /app
WORKDIR /app
# alpine 执行 Go 程序需要先安装一下依赖
RUN mkdir /lib64 && ln -s /lib/libc.musl-x86_64.so.1 /lib64/ld-linux-x86-64.so.2
# 从第一阶段复制 hello 可执行程序到当前目录
COPY --from=0 /compile/hello ./
# 允许外界访问容器的 8000 端口,不写也会默认暴露端口,写上相当于起一个注释的作用
EXPOSE 8000
# 启动 hello 可执行程序
CMD ["./hello"]
在本机工作目录中,执行Dockerfile构建以生成新的镜像:
$ ls
Dockerfile hello.go
$ docker build -t hello .
-t 是给镜像起一个可读的名字,注意最后还有一个 . 代表Dockerfile所在的目录。
docker build正确执行成功后,就可以看到新的镜像已经生了:
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello latest 56173fb23f12 15 minutes ago 11.7MB
下面使用docker run命令将此镜像运行起来:
$ docker run -d -p 8000:8000 56173fb23f12
我们的Go程序监听的是容器的8000端口,这里使用-p指定把容器的8000端口映射到宿主机的8000端口,这样就可以直接使用我本机的浏览器进行访问了。
使用浏览器进行访问:
这样我们的镜像就已经测试完成了,通常我们制作的镜像希望分享给其它人使用,一般公司内部会使用Harbor搭建镜像仓库供内部人员使用,这里我们可以把镜像传到DockerHub公共镜像仓库上去,这样我们的镜像可以被互联网上所有人看到并下载使用,如果没有DockerHub帐号,则先要去官网创建帐号和自己的仓库:DockerHub
使用docker login命令登录到DockerHub上:
$ docker login
输入用户名和密码
Login Succeeded
我的Docker仓库的名字是hackercracker/test
,要根据这个仓库名称给本地的镜像改个名字:
$ docker tag hello hackercracker/test:v1
把镜像推到DockerHub上:
$ docker push hackercracker/test:v1
The push refers to repository [docker.io/hackercracker/test]
24ba23593bae: Pushed
639949c6c224: Pushed
c282b654e2d7: Pushed
8d3ac3489996: Mounted from library/alpine
v1: digest: sha256:0d45ef82dd579e51fe81b30f7e43071a745a485fcef51867e018970ec205a73d size: 1153
至此,镜像就成功推到DockerHub上了。