使用docker来部署go-web项目

一、基础代码

  • 1、使用gorm封装对mysql的操作

    // utils/db.go 文件
    package utils
    
    import (
     "fmt"
     _ "github.com/go-sql-driver/mysql"
     "gorm.io/driver/mysql"
     "gorm.io/gorm"
     "gorm.io/gorm/logger"
     "gorm.io/gorm/schema"
    )
    
    var GormDb *gorm.DB
    
    func init() {
     var err error
     sqlStr := fmt.Sprintf("root:123456@tcp(localhost)/beego?charset=utf8mb4&parseTime=true&loc=Local")
     GormDb, err = gorm.Open(mysql.Open(sqlStr), &gorm.Config{
        Logger: logger.Default.LogMode(logger.Info),
        //DisableForeignKeyConstraintWhenMigrating: true, // 禁止创建外键
        NamingStrategy: schema.NamingStrategy{
           SingularTable: true,
           // 全部的表名前面加前缀
           //TablePrefix: "mall_",
        },
     })
     if err != nil {
        fmt.Println("数据库连接错误", err)
        return
     }
    }
    
  • 2、main.go文件

    package main
    
    import (
     "docker_go/utils"
     "fmt"
     "github.com/gin-gonic/gin"
     "net/http"
    )
    
    type User struct {
     Id       int    `gorm:"id" json:"id"`
     Username string `gorm:"username" json:"username"`
     Password string `gorm:"password" json:"password"`
    }
    
    func main() {
     router := gin.Default()
     router.GET("", func(ctx *gin.Context) {
        var userList []User
        if result := utils.GormDb.Find(&userList).Error; result != nil {
           fmt.Println("进来了", result)
        }
        ctx.JSON(http.StatusOK, gin.H{
           "code":    0,
           "message": "成功",
           "data":    userList,
        })
     })
     router.Run(":9000")
    }
    
  • 3、简单的sql文件

    
    SET NAMES utf8mb4;
    SET FOREIGN_KEY_CHECKS = 0;
    
    -- ----------------------------
    -- Table structure for user
    -- ----------------------------
    DROP TABLE IF EXISTS `user`;
    CREATE TABLE `user` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `username` varchar(50) COLLATE utf8mb4_bin DEFAULT NULL,
      `password` varchar(50) COLLATE utf8mb4_bin DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
    
    -- ----------------------------
    -- Records of user
    -- ----------------------------
    BEGIN;
    INSERT INTO `user` (`id`, `username`, `password`) VALUES (1, 'admin', '123456');
    INSERT INTO `user` (`id`, `username`, `password`) VALUES (2, 'test', '123456');
    COMMIT;
    
    SET FOREIGN_KEY_CHECKS = 1;
    
  • 4、先在本地数据库创建一个beego的数据库,将数据表导入,测试本地运行是否正常

二、使用Dockerfile来部署项目

  • 1、简单的示例代码

    package main
    
    import (
     "github.com/gin-gonic/gin"
     "net/http"
    )
    
    func main() {
     router := gin.Default()
     router.GET("", func(ctx *gin.Context) {
        ctx.JSON(http.StatusOK, gin.H{
           "code":    1,
           "message": "成功",
        })
     })
     router.Run(":8000")
    }
    
  • 2、编写Dockerfile文件

    FROM golang:alpine
    
    # 为镜像设置环境变量
    ENV GO111MODULE=on \
        CGO_ENABLED=0 \
        GOOS=linux \
        GOARCH=amd64
    
    # 移动到工作目录
    WORKDIR /app
    
    # 将代码复制到容器中
    COPY go.mod .
    COPY go.sum .
    # 安装依赖包
    RUN go mod tidy
    # RUN go mode download
    
    COPY . .
    # 将我们的代码main.go编译成二进制可执行的文件go_app
    RUN go build -o go_app main.go
    
    # 暴露出去端口
    EXPOSE 8000
    
    # 启动容器运行的命令
    CMD ["/app/go_app"]
    
  • 3、打包成镜像

     docker build . -t go_app:v1 
     docker build . -t go_app:v1 -f 指定文件名 
    
  • 4、运行镜像

    # 容器中8000端口,自己浏览器上访问的是8080
    docker run --rm -p 8080:8000 容器id
    
  • 5、浏览器端测试

三、分阶段构建

  • 1、修改上面的Dockerfile文件

    FROM golang:alpine AS builder
    
    # 为镜像设置环境变量
    ENV GO111MODULE=on \
        CGO_ENABLED=0 \
        GOOS=linux \
        GOARCH=amd64
    
    # 移动到工作目录
    WORKDIR /app
    
    # 将代码复制到容器中
    COPY go.mod .
    COPY go.sum .
    # 安装依赖包
    RUN go mod tidy
    # RUN go mode download
    
    COPY . .
    # 将我们的代码main.go编译成二进制可执行的文件go_app
    RUN go build -o go_app main.go
    
    ###################
    # 接下来创建一个小镜像
    ###################
    FROM scratch
    
    # 从builder镜像中把go_app拷贝到当前目录下
    COPY --from=builder /app/go_app /
    # 暴露出去端口
    EXPOSE 8000
    
    # 启动容器运行的命令
    CMD ["/go_app"]
    
  • 2、运行打包

  • 3、对比镜像大小

    image-20220731103757618.png

  • 4、同样的运行容器,浏览器访问一切都正常

四、使用docker-compose来部署gin+mysql项目

注意点如果项目中没有关联其它容器的话,可以不需要使用docker-compose来编排,直接有Dockerfile文件就可以

  • 1、Dockerfile文件的书写

    # 获取go的版本,这里也可以直接写golang:1.17.1 但是体积会比较大点
    FROM golang:alpine
    
    # 为镜像设置必须的环境变量
    ENV GO115MODULE=on\
        CGO_ENABLED=0\
        GOOS=linux\
        GOARCH=amd64\
        GOPROXY="https://goproxy.cn,direct"
    
    # 当前的工作目录
    WORKDIR /app
    # 复制项目中的 go.mod 和 go.sum文件并下载依赖信息
    COPY go.mod .
    COPY go.sum .
    RUN go mod download
    
    # 将别的文件拷贝到工作目录中
    COPY . .
    
    # 编译代码
    RUN go build -o docker_go main.go
    # 端口
    EXPOSE 9000
    
    # 启动命令
    CMD ["./docker_go"]
    
  • 2、docker-compose.yml文件的编写

    version: '3'
    
    services:
      docker_go:
        build:
          context: . # 指定目录
          dockerfile: Dockerfile # 指定文件
        image: docker_go
        ports:
          - "8000:9000"
        depends_on:
          - db
    
      db:
        image: mysql:8.0.19
        container_name: go_mysql_db # 指定名字
        environment:
          MYSQL_ROOT_PASSWORD: '123456'
          MYSQL_USER: 'beego'
          MYSQL_PASSWORD: 'a123456'
          MYSQL_DATABASE: 'beego'
        command:
          # 将mysql8.0默认密码策略 修改为 原先 策略 (mysql8.0对其默认策略做了更改 会导致密码无法匹配)
          --default-authentication-plugin=mysql_native_password
          --character-set-server=utf8mb4
          --collation-server=utf8mb4_general_ci
          --explicit_defaults_for_timestamp=true
          --lower_case_table_names=1
        volumes:
          - ./mysql/data:/var/lib/mysql
          - ./mysql/conf:/etc/mysql/conf.d
          - ./mysql/logs:/log
    #      - ./mysql/init/:/docker-entrypoint-initdb.d/ 如果多个初始化文件的话建议直接这样,全部放在init文件夹下
          - ./beego.sql:/docker-entrypoint-initdb.d/beego.sql
    
    
  • 3、修改utils/db.go文件

    // 其中db是直接是docker-compose.yml文件中定义的db,根据这个来写,这个跟docker网络有关系
    sqlStr := fmt.Sprintf("root:123456@tcp(db)/beego?charset=utf8mb4&parseTime=true&loc=Local")
    
  • 4、启动

    docker-compose up
    
  • 5、查看docker网络信息,确保项目下的容器都在一个网络下就可以正常使用

    ~ docker network ls                  
    NETWORK ID     NAME                DRIVER    SCOPE
    9f062437c4c8   bridge              bridge    local
    c09e61ec2461   docker_go_default   bridge    local
    d059c7815581   host                host      local
    4809f70a4de2   none                null      local
    

    查看网络下具体的容器

    docker network inspect c09e61ec2461
    

    image-20220731101025350.png

  • 6、直接在浏览器上输入地址访问

    http://localhost:8000/
    
  • 7、同样的可以使用容器分阶段构建

猜你喜欢

转载自juejin.im/post/7126364569043206157