注:因為是第一次跟著教程做的邮旷。應(yīng)該還有優(yōu)化的空間,可能還會有比較蠢的代碼片段知纷。
Dockerfile分為兩段:
- 第一段,構(gòu)建一個臨時的build用的鏡像陵霉,用來編譯生成go的運(yùn)行文件琅轧。
- 第二段,構(gòu)建一個純凈版空鏡像scratch作為運(yùn)行鏡像撩匕,把編譯好的運(yùn)行文件和相關(guān)需要的配置文件什么的一起COPY到新的運(yùn)行鏡像里鹰晨。這樣運(yùn)行鏡像就可以非常小墨叛。如果為了調(diào)試方便止毕,還是建議用alpine鏡像。
PS漠趁,雖然我看到的教程里是可以用scratch來運(yùn)行g(shù)o編譯后的運(yùn)行文件扁凛。但是我沒成功,最后還是用了alpine鏡像闯传。
Go工程結(jié)構(gòu)
因為是練習(xí)谨朝,所以構(gòu)建了一個相對簡單的工程
image.png
打包思路
拋開docker,先梳理一下整個go工程的打包步驟:
- 編譯工程需要有g(shù)o 1.16的運(yùn)行環(huán)境
- 由于使用了go mod甥绿,需要設(shè)置GOPROXY=https://goproxy.io,direct
- 工程啟動文件是main.go字币,我習(xí)慣把工程編譯到一個新的work文件夾里,運(yùn)行文件起名server共缕。所以編譯命令是
go build -o work/server main.go
- 編譯后的運(yùn)行方式是
cd work
./server
第一段:編譯鏡像
- 使用go的官方基礎(chǔ)鏡像包洗出,alpine版本。
FROM golang:1.16-alpine AS build
go mod我使用的是1.16的版本图谷,對應(yīng)的golang鏡像也用對應(yīng)版本翩活。
注意這里用的是FROM ... AS ... (這個build要記住阱洪,后面要考)
- 定義工作目錄是/project,并且把相關(guān)編譯腳本拷貝到鏡像的/project目錄下
WORKDIR /project/
COPY ./project /project
- 運(yùn)行編譯命令菠镇,生成運(yùn)行文件
RUN go env -w GOPROXY=https://goproxy.io,direct
RUN go build -o /project/work/server main.go
第二段:運(yùn)行鏡像
- 運(yùn)行鏡像使用alpine作為基礎(chǔ)鏡像
FROM alpine
- 配置一些基礎(chǔ)設(shè)置,比如說時區(qū)
ENV TZ Asia/Shanghai
- 從編譯鏡像將運(yùn)行需要的工程文件拷貝過來
COPY --from=build /project/work/ /work/
注:這里的build就是之前那個FROM ... AS build
- 配置工作目錄和運(yùn)行相關(guān)
# 定義工作目錄為work
WORKDIR /work
# 開放http 80端口
EXPOSE 80
# 啟動http服務(wù)
ENTRYPOINT ["./server"]
完整的Dockerfile
# 編譯鏡像
FROM golang:1.16-alpine AS build
WORKDIR /project/
COPY ./project /project
RUN go env -w GOPROXY=https://goproxy.io,direct
RUN go build -o /project/work/server main.go
# 運(yùn)行鏡像
FROM alpine
ENV TZ Asia/Shanghai
COPY --from=build /project/work/ /work/
# 定義工作目錄為work
WORKDIR /work
# 開放http 80端口
EXPOSE 80
# 啟動http服務(wù)
ENTRYPOINT ["./server"]
構(gòu)建并推送鏡像
# 在Dockerfile所在文件夾運(yùn)行
docker build -t xxxx/xxxx:v1 .
# 構(gòu)建成功后,運(yùn)行測試一下
docker run -d xxxx/xxxx:v1
# docker ps查看一下運(yùn)行情況
docker ps
# 查看一下容器對應(yīng)的pid
docker inspect 554c4578242e|grep -i pid
# 查看對應(yīng)的IP配置
nsenter -t 256418 -n ip a