Template rendering

Now most of the web project is the separation of front and back side, we could start with the previous template rendering what is used in the framework of Gin, after the template is a good web page in the back-end process rendering sent directly to the user’s browser, the browser page almost don’t do any operation, is conducive to SEO, web page rendering speed is much faster. Gin needs to specify the path to match the static files when using template rendering, and package all files into it when compiling. I recently made a very simple demo showing a few static pages of a course, using a template rendering. To recap, first create a new TemplateTest folder, create a new main.go file in that folder and type:

package main

import (
	"net/http"

	"github.com/gin-gonic/gin"
)

func main(a) {
	r := gin.Default()
	r.LoadHTMLGlob("tem/**/*")  //** stands for folder, * stands for file, must be specified to the lowest file will not error
	r.GET("/index".func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "Hello Earthy Excavator".// We can prove that the framework is normal
		})
	})
	r.GET("/class".func(c *gin.Context) {
		class := c.DefaultQuery("class"."1") // Accept the URL argument
		c.HTML(http.StatusOK, "class"+class+".html", gin.H{"title": class})  // Concatenate the template file path to pass the render parameters
	})
	r.Run()
}
Copy the code

Create a folder TMP under TemplateTest, and create a folder HTML under TMP to save the HTML files. Create several NEW HTML files as shown below:

Then execute two commands to initialize the project’s go.mod and download the dependencies:

go mod init TemplateTest
Copy the code
go mod tidy
Copy the code

Run the go run main.go directly from the project root directory and access the index route, then test the access to the class path and the class parameter

Perfectly functioning,r.LoadHTMLGlob("tem/**/*") This code refers to the template folder, so the return path is directly specified when the file name, without the previous class folder and TEM folder, can still be usedengine.Static("./static", "static")Register static files to be used directly in HTMLstaticSpecifies the location of the static file.

Many section of the building

Ok, the project has been written, let’s try to package the project using Docker, first do a simple packaging demonstration to see how big the image is, and then see how big the image is using multi-terminal packaging. Create a new Dockerfile in the project root directory and enter the following contents:

Compile and run with this image
FROM golang:alpine

Set the working path
WORKDIR /build

Copy all project files to the root folder of the image
ADD . ./

Set environment variables for the Go language and enable the Go Module mode. Set the package download source to facilitate quick package download
ENV GO111MODULE=on \
GOPROXY=https://goproxy.cn

# Download the package inside go.mod
RUN go mod download

# compiler
RUN go build -o gin_docker .

# open port
EXPOSE 8080

# Run the project
ENTRYPOINT  ["./gin_docker"]
Copy the code

In the use of docker command to read Dockerfile content generated image

docker build -t gin:v1 .
Copy the code

Try running a container from this image

docker run -itd --name gin -p 8080:8080 gin:v1
Copy the code

Run the test successfully

The downside is that the packaged image is too big, just a few dozen lines of code, a few files and folders, and takes up 400MB of space

When I learned Docker, I learned its multi-section construction, which is a new feature after Docker17.05. I didn’t encounter this before using PHP to package images, but I happened to encounter it in Go, so I just used it. Because Go is a compiled language, it needs to be compiled into binary files before it can run. We can separate the compiled image from the running image. Now LET me change the Dockerfile file and look at the following example, which is very clear and simple:

# #
# ---------- building ----------
# #
# Compile with this image
FROM golang:alpine  AS builder

Set the working path
WORKDIR /build

Copy all project files to the root folder of the image
ADD . ./

Set environment variables for the Go language and enable the Go Module mode. Set the package download source to facilitate quick package download
ENV GO111MODULE=on \
GOPROXY=https://goproxy.cn

# Download the package inside go.mod
RUN go mod download

# compiler
RUN go build -o gin_docker .

# #
# ---------- run ----------
# #
# Change the mirror image
FROM alpine:latest

Use the same working directory
WORKDIR /build/

Copy the compiled file to the directory where the image is running
COPY --from=builder /build .

# open port
EXPOSE 8080

# Run the project
ENTRYPOINT  ["./gin_docker"]
Copy the code

Package V2 image:

docker build -t gin:v2 .
Copy the code

Run the container (delete the previous container, otherwise there will be port conflicts) :

docker run -itd --name gin -p 8080:8080 gin:v2
Copy the code

It works perfectly. Mirror size difference is 20 times

As you can see, many dependency files are required at compile time, and few dependencies are required at run time as binary files. As you can see, using a multi-segment build saves a lot of storage costs and time costs.