docker多阶段构建镜像

概览

利用docker多阶段构建镜像的机制,可以使构建出来的最终镜像体积大大减小,从而方便传输

比如我们使用go语言构建程序,在编译环境需要安装go等一些依赖,而构建出来的二进制文件只需要在一个很小的Linux容器中即可运行

环境信息

CentOS Linux release 7.9.2009 (Core)
go version go1.15.5 linux/amd64
Docker version 18.09.9, build 039a7df9ba

准备环境

#1 安装docker
https://blog.csdn.net/xys2015/article/details/109370082

#2 安装go
https://blog.csdn.net/xys2015/article/details/113770562

在宿主机构建一个简单的Go HTTP Server

1 目标

  • 使用Go编译一个程序
  • 运行该程序监听8180端口
  • 请求 localhost:8180/xxx ,返回 Hello, you requested: /xxx
  • 记录请求的日志到标准输出

2 书写代码

package main

import (
    "fmt"
    "log"
    "net/http"
)

// HelloServer responds to requests with the given URL path.
func HelloServer(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, you requested: %s\n", r.URL.Path)
    log.Printf("Received request for path: %s", r.URL.Path)
}

func main() {
    var addr string = ":8180"
    handler := http.HandlerFunc(HelloServer)
    if err := http.ListenAndServe(addr, handler); err != nil {
        log.Fatalf("Could not listen on port %s %v", addr, err)
    }
}

3 编译

go build hello.go

3 运行

./hello

4 访问

[root@192_168_31_100 ~]# curl localhost:8180/xxx
Hello, you requested: /xxx
[root@192_168_31_100 ~]# curl localhost:8180/hello
Hello, you requested: /hello
[root@192_168_31_100 ~]# curl localhost:8180/world
Hello, you requested: /world

5 查看输出的日志

[root@192_168_31_100 /data/gitee-dld/hello-go/http-server]# ./hello 
2021/02/09 15:26:32 Received request for path: /xxx
2021/02/09 15:26:35 Received request for path: /hello
2021/02/09 15:26:39 Received request for path: /world

6 结束程序

CTRL + C

参考地址 https://gitee.com/as4k/gitee-dld/tree/master/hello-go/http-server

把上面这个程序放到容器中运行

1 书写 Dockerfile

cat Dockerfile
FROM golang:1-alpine as build
# golang:1-alpine 这个标签的含义是 最新1.x版本,基础镜像是 alpine linux

WORKDIR /app
COPY http-server http-server
RUN go build /app/http-server/hello.go
#这里生成的二进制文件会放在 /app/hello

FROM alpine:latest

WORKDIR /app
COPY --from=build /app/hello /app/hello
#--from=build 这里即用到第一阶段的镜像

EXPOSE 8180
ENTRYPOINT ["./hello"]

2 构建镜像

#处在Dockerfile所在目录下
docker build -t hello-go:v1 .

3 运行容器

docker run -d --name hello-go --rm -p 8180:8180 hello-go:v1

4 访问容器

curl localhost:8180/hello-world

5 相关输出信息

5.1 镜像大小对比
====================
# docker images | egrep "hello|golang"
hello-go                 v1                  abe1c3a706e0        About a minute ago   12.1MB
golang                   1-alpine            1463476d8605        7 weeks ago          299MB
可以看到,节省了不少磁盘空间,如果go程序有大量依赖,效果更明显

5.2 容器运行信息和访问信息
====================
[root@192_168_31_100 /data/gitee-dld/hello-go]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                    NAMES
e964f390ac91        hello-go:v1         "./hello"           2 seconds ago       Up 1 second         0.0.0.0:8180->8180/tcp   hello-go
[root@192_168_31_100 /data/gitee-dld/hello-go]# curl localhost:8180/hello-world
Hello, you requested: /hello-world

参考地址 https://gitee.com/as4k/gitee-dld/tree/master/hello-go

https://blog.csdn.net/xys2015/article/details/113771678