docker image creation for golang a year ago
一个简单的“hello scott” image
首先我们创建一个最基本的“hello scott”程序,不使用任何库,不依赖任何配置文件
以下是示例代码:
package main
import "log"
func main() {
log.Println("hello scott!")
}
接着创建Dockerfile
FROM golang:1.21.3
WORKDIR /app
COPY main.go .
COPY go.mod .
RUN go build -o hello .
ENTRYPOINT [ "/app/hello" ]
构建image:
$ docker build . -t hello:latest
查看image
运行容器:
查看容器的filesystem
使用第三方库
示例代码如下:
package main
import (
"log"
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"code": 200,
"msg": "pong",
})
})
log.Fatal(r.Run(":9999"))
}
创建Dockerfile:
FROM golang:1.21.3
WORKDIR /app
COPY main.go .
COPY go.mod .
# go get 会读取go.mod 然后自动拉取pkg
RUN go get
RUN go build -o hello .
ENTRYPOINT [ "/app/hello" ]
构建image:
发现失败了,原因是github被墙了,所以我们需要使用代理,更新我们的Dockfile
FROM golang:1.21.3
RUN go env -w GOPROXY=https://goproxy.io,direct
WORKDIR /app
COPY main.go .
COPY go.mod .
# go get 会读取go.mod 然后自动拉取pkg
RUN go get
RUN go build -o hello .
ENTRYPOINT [ "/app/hello" ]
再构建,发现ok了
查看image
接着启动容器:
$ docker run -p 22222:9999 api-test
我们用浏览器测试下:
使用配置文件
在开始这个demo之前,我们需要知道,指定WORKDIR
后,如果路径不存在,docker会自动帮我们创建,如:
WORKDIR /go/src/github.com/scott-x/go-docker
那么docker
1, 测试相对路径在docker中是否能识别
测试代码:
package main
import (
"io/ioutil"
"log"
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"code": 200,
"msg": "pong",
})
})
r.GET("/test", func(c *gin.Context) {
filename := "./test.txt"
bs, err := ioutil.ReadFile(filename)
if err != nil {
c.JSON(http.StatusOK, gin.H{
"code": 200,
"msg": "failed to read test.txt",
})
return
}
c.JSON(http.StatusOK, gin.H{
"code": 200,
"msg": string(bs),
})
})
log.Fatal(r.Run(":9999"))
}
测试文件 test.txt
:
更新Dockerfile
FROM golang:1.21.3
RUN go env -w GOPROXY=https://goproxy.io,direct
WORKDIR /go/src/github.com/scott-x/go-docker
COPY main.go .
COPY go.mod .
COPY test.txt .
# go get 会读取go.mod 然后自动拉取pkg
RUN go get
RUN go build -o hello .
ENTRYPOINT [ "/go/src/github.com/scott-x/go-docker/hello" ]
构建image
启动容器
浏览器测试
use local package
现在把程序变得稍微复杂点,我们创建一个本地包test,如下:
修改Dockerfile
FROM golang:1.21.3
RUN go env -w GOPROXY=https://goproxy.io,direct
WORKDIR /go/src/github.com/scott-x/go-docker
COPY . .
# go get 会读取go.mod 然后自动拉取pkg
RUN go get
RUN go build -o hello .
ENTRYPOINT [ "/go/src/github.com/scott-x/go-docker/hello" ]
开始构建:
run起来,然后浏览器测试:
可能很多人会很好奇,我们未指定$GOPATH
,但是程序却能识别
接下来我们进入容器来一探究竟
$ docker exec -it 570aef4dd13c bash
原来go docker image默认的$GOPATH
是/go
ENV
设置容器的环境变量,语法:
ENV key=value
修改我们的示例代码:
package main
import (
"fmt"
"log"
"net/http"
"os"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"code": 200,
"msg": "pong",
})
})
r.GET("/test", func(c *gin.Context) {
name := os.Getenv("NAME")
if name == "" {
name = "$NAME is not setted"
} else {
name = fmt.Sprintf("ENV $NAME: %s", name)
}
c.JSON(http.StatusOK, gin.H{
"code": 200,
"msg": name,
})
})
log.Fatal(r.Run(":9999"))
}
更新Dockerfile:
FROM golang:1.21.3
ENV NAME=Scott
RUN go env -w GOPROXY=https://goproxy.io,direct
WORKDIR /go/src/github.com/scott-x/go-docker
COPY . .
# go get 会读取go.mod 然后自动拉取pkg
RUN go get
RUN go build -o hello .
ENTRYPOINT [ "/go/src/github.com/scott-x/go-docker/hello" ]
构建:
run起来并用浏览器测试:
我们尝试从docker启动时指定环境变量来覆盖默认的:
$ docker run -p 22222:9999 -e NAME="hello, my name is Scott" api-test
浏览器测试: