Scott

docker image creation for golang a year ago

go
docker
4073个字符
共有170人围观

一个简单的“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

浏览器测试: