Dockerfile实现GO语言编写httpserver的多阶段构建容器化
Go实现httpserver的源代码
创建main.go文件
package main
import (
"fmt"
"log"
"net"
"net/http"
"net/http/pprof"
"os"
"strings"
)
func main() {
mux := http.NewServeMux() //多路复用处理函数
mux.HandleFunc("/", mainIndex) //handler,谁来处理request
mux.HandleFunc("/healthz", healthz) //healthz, 返回200,作为健康检查
mux.HandleFunc("/debug/pprof/", pprof.Index) //mux的debug模块
mux.HandleFunc("/debug/pprof/profile", pprof.Profile)
mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
mux.HandleFunc("/debug/pprof/trace", pprof.Trace)
err := http.ListenAndServe(":8080", mux) //启动服务
if err != nil {
log.Fatal("start server failed: %s \n", err.Error())
}
}
func mainIndex(w http.ResponseWriter, r *http.Request) {
//w.Write([]byte("Welcome to <go> http server")) //如果返回页面就没有header了
for k, v := range r.Header {
for _, vv := range v {
w.Header().Add(k, vv)
fmt.Println(k, vv)
}
}
w.Header().Add("systemEnv", os.Getenv("GOPATH"))
log.Printf("Success! Response code: %d", 200)
clientip := Clinetip(r)
log.Printf("Success! client ip: %s", clientip)
}
func healthz(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "200")
}
//ClientIP 尽最大努力实现获取客户端 IP 的算法。
//当请求头不存在即不存在代理时直接获取ip, RemoteAddr
//解析 X-Real-IP 和 X-Forwarded-For以便于反向代理(nginx 或 haproxy)可以正常工作。
func Clinetip(r *http.Request) string {
ip := strings.TrimSpace(strings.Split(r.Header.Get("x-Forwarded-For"), ",")[0])
if ip != "" {
return ip
}
ip = strings.TrimSpace(r.Header.Get("X-Real-Ip"))
if ip != "" {
return ip
}
if ip, _, err := net.SplitHostPort(strings.TrimSpace(r.RemoteAddr)); err == nil {
return ip
}
return ""
}
编写Dockerfile
FROM golang:1.17 AS builder
ENV GO111MODULE=off \
CGO_ENABLED=0 \
GOOS=linux \
GOARCH=amd64
WORKDIR /build
COPY . .
RUN go build -o httpserver .
FROM scratch
COPY --from=builder /build/httpserver /
EXPOSE 8080
ENTRYPOINT ["/httpserver"]
搭建镜像
docker build读取Dockerfile文件,搭建镜像,-t为容器添加tag
docker build . -t httpserver:0.0.1
docker run -d -p 8080:8080 httpserver:0.0.1
测试httpserver服务是否成功开启,并通过nsenter查看容器网络配置
httpserver容器运行成功
[root@localhost httpserver]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d2e1fe4e03f2 httpserver:0.0.1 "/httpserver" 2 hours ago Up 2 hours 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp brave_chaum
[root@localhost httpserver]# PID=$(docker inspect --format "{{ .State.Pid }}" brave_chaum)
[root@localhost httpserver]# nsenter -t $PID -n ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
24: eth0@if25: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
上传到Docker hub
[root@localhost httpserver]# docker tag 3fe3921ec1f0 henryli98/httpserver:0.0.1
[root@localhost httpserver]# docker push henryli98/httpserver:0.0.1
The push refers to repository [docker.io/henryli98/httpserver]
af92bb057461: Pushed
0.0.1: digest: sha256:06cb18e9d2cb4d79f3891eb848b23e5e89b80bc1f535c74766bfc1fe2644180d size: 528
另一种Dockerfile编写方式
FROM golang:1.17 AS build
WORKDIR /httpserver/
COPY . .
ENV CGO_ENABLED=0
ENV GO111MODULE=on
ENV GOPROXY=https://goproxy.cn,direct
RUN GOOS=linux go build -installsuffix cgo -o httpserver main.go
FROM busybox
COPY --from=build /httpserver/httpserver /httpserver/httpserver
EXPOSE 8360
ENV ENV local
WORKDIR /httpserver/
ENTRYPOINT ["./httpserver"]
本文章参考极客时间课程内容,个人学习记录使用