当前位置: 首页 > 后端技术 > PHP

Gin实践系列9将Golang应用部署到Docker

时间:2023-03-29 19:58:57 PHP

项目地址:https://github.com/EDDYCJY/go...(上车,支持一波)原文地址:将Golang应用部署到Docker注:之前首先,您需要安装docker并配置镜像源。本章源码在f-20180324-docker分支。从本章开始,项目目录以go-gin-example为基础(请根据自己本地项目灵活更改)。介绍到这里简单介绍了Docker,建议多了解Docker。它是一种开源的轻量级容器技术,允许开发人员将他们的应用程序和他们运行的上下文打包成一个可移植的镜像,然后将它们发布到任何支持Docker的系统。跑步。通过容器技术,Docker为应用程序提供了一个几乎没有性能开销的隔离运行环境。简化配置、代码流水线管理,提高开发效率。快速隔离应用程序并持续部署它们。接下来我们正式开始docker对项目所需要的处理和处理。写,每个标题都是Golang的一个步骤大纲1.写一个Dockerfile在go-gin-example项目的根目录下创建一个Dockerfile,写入内容FROMgolang:latestWORKDIR$GOPATH/src/github.com/EDDYCJY/go-杜松子酒示例复制。$GOPATH/src/github.com/EDDYCJY/go-gin-exampleRUNgobuild.EXPOSE8000ENTRYPOINT["./go-gin-example"]使用golang:latest镜像作为基础镜像,设置工作目录为$GOPATH/src/go-gin-example,并将当前上下文目录的内容复制到$GOPATH/src/go-gin-examplegobuild编译完成后,设置容器启动程序为./go-gin-example,也就是我们编译出来的可执行文件。请注意,go-gin-example是在docker容器中编译的,而不是在宿主机上编译的。Dockerfile文件是用来定义Docker镜像生成过程的配置文件。该文件的内容是一个命令。每条指令构建一层,所以每条指令的内容是描述该层应该如何构建;这些指令应用于基础图像并最终创建一个新图像。你可以认为是用来快速创建一个自定义的Docker镜像1.FROM指定基础镜像(必须有指令,并且必须是第一条指令)2.WORKDIR格式为WORKDIR<工作目录路径>使用WORKDIR指令指定工作目录(或当前目录),以后每一层的当前目录都会更改为指定的目录。如果该目录不存在,WORKDIR将帮助您创建该目录。3.COPY格式:COPY...COPY["",...""]COPY指令将从中复制文件/目录构建上下文目录新建层镜像中的位置4.RUN用于执行命令行命令格式:RUN5.EXPOSE格式为EXPOSE[...]EXPOSE命令是声明容器在运行时提供服务端口。这只是一个声明。在运行时,应用程序不会因为这条语句而打开这个端口的服务。在Dockerfile中写这样一条语句有两个好处,可以帮助镜像用户了解镜像服务。运行时使用随机端口映射时,即dockerrun-P时,会自动随机映射EXPOSE的端口。6、ENTRYPOINT的格式与RUN命令相同,分为两种格式:exec格式:""shell格式:ENTRYPOINT["curl","-s","http://ip.cn"]ENTRYPOINT命令是指定容器启动程序和参数2.构建镜像go-gin-在example的项目根目录下执行dockerbuild-tgin-blog-docker。该命令的作用是创建/构建镜像。-t指定名称为gin-blog-docker。构建内容是当前上下文目录$dockerbuild-tgin-blog-docker.SendingbuildcontexttoDockerdaemon96.39MBStep1/6:FROMgolang:latest--->d632bbfe5767Step2/6:WORKDIR$GOPATH/src/github.com/EDDYCJY/go-gin-example--->56294f978c5dRemovingintermediatecontainere112997b995dStep3/6:COPY.$GOPATH/src/github.com/EDDYCJY/go-gin-example--->3b60960120cfRemovingintermediatecontainer63e310b3f60cStep4.--->Runningin52648a431450--->7bfbeb301feaRemovingintermediatecontainer52648a431450Step5/6:EXPOSE8000--->Runningin98f5b387d1bb--->b65bd4076c65Removingintermediatecontainer98f5b387d1bbStep6/6:ENTRYPOINT./go-gin-example--->Runninginc4f6cdeb667b--->d8a109c7697cRemovingintermediatecontainerc4f6cdeb667bSuccessfullybuiltd8a109c7697c三、验证镜像查看所有的镜像,确定刚刚构建的gin-blog-docker镜像是否存在$dockerimagesREPOSITORYTAGIMAGEIDCREATEDSIZEgin-blog-dockerlatestd8a109c7697cAboutaminuteago946MBdocker.io/golanglatestd632bbfe57678daysago779MB...4.CreateandrunanewcontainerExecutethecommanddockerrun-p8000:8000gin-blog-docker$dockerrun-p8000:8000gin-blog-dockerdialtcp127.0.0.1:3306:connect:connectionrefused[GIN-debug][WARNING]Runningin"debug"mode.Switchto"release"modeinproduction.-usingenv:exportGIN_MODE=release-usingcode:gin.SetMode(gin.ReleaseMode)...Actualpidis1操作成功,你以为你完成了吗?你想太多了。仔细看控制台的输出,有错误dialtcp127.0.0.1:3306:connect:connectionrefused。我们判断一下,发现是Mysql的问题。接下来,我们就来解决这个问题Mysqlone。拉取镜像从Docker的公共仓库Dockerhub下载MySQL镜像(国内建议配置镜像)$dockerpullmysql2.新建并运行一个新的容器来运行Mysql容器,并设置执行成功后返回的容器ID$dockerrun--namemysql-p3306:3306-eMYSQL_ROOT_PASSWORD=rootroot-dmysql8c86ac986da4922492934b6fe074254c9165b8ee3e184d29865921b0fef29e64连接到Mysql初始化的Mysql应该是Golang+Mysql中所示1.删除镜像有几个问题因为我们需要镜像删除有问题的镜像,重建一个新的镜像,重建一个不同名称和标签的新镜像,删除原来的有问题的镜像。-f是强制删除及其相关状态。如果不执行-f,则需要执行dockerps-a查看到相关的容器,将其rm解除两人依赖关系$dockerrmi-fgin-blog-dockerUntagged:gin-blog-docker:latestDeleted:sha256:d8a109c7697c3c2d9b4de7dbb49669d10106902122817b6467a031706bc52ab4Deleted:sha256:b65bd4076c65a3c24029ca4def3b3f37001ff7c9eca09e2590c4d29e1e23dce5Deleted:sha256:7bfbeb301fea9d8912a4b7c43e4bb8b69bdc57f0b416b372bfb6510e476a7deeDeleted:sha256:3b60960120cf619181c1762cdc1b8ce318b8c815e056659809252dd321bcb642Deleted:sha256:56294f978c5dfcfa4afa8ad033fd76b755b7ecb5237c6829550741a4d2ce10bc二、修改配置文件将项目的配置文件conf/app.ini,内容修改为#debugorreleaseRUN_MODE=debug[app]PAGE_SIZE=10JWT_SECRET=233[server]HTTP_PORT=8000READ_TIMEOUT=60WRITE_TIMEOUT=60[database]TYPE=mysqlUSER=rootPASSWORD=rootrootHOST=mysql:3306NAME=blogTABLE_PREFIX=blog_3.重建镜像重复前面的步骤,回到gin-blog的项目根目录执行dockerbuild-tgin-blog-docker4.创建并运行新的容器关联Q:我们需要将Golang容器与Mysql容器关联起来,那么我们需要怎么做呢?A:添加命令--linkmysql:mysql,实现Golang容器与Mysql容器互联;通过--link,可以直接使用其关联的容器别名在容器中访问,而不是通过IP,但是--link只能解决单机容器之间的关联,在分布式多机的情况下,需要以其他方式连接以运行命令dockerrun--linkmysql:mysql-p8000:8000gin-blog-docker$dockerrun--linkmysql:mysql-p8000:8000gin-blog-docker[GIN-debug][警告]在“调试”模式下运行。在生产中切换到“发布”模式。-使用环境:exportGIN_MODE=release-使用代码:gin.SetMode(gin.ReleaseMode)...Actualpidis1结果检查启动输出,接口测试,数据库中的数据,都正常;我们的Golang容器和Mysql容器成功关联运行,大功告成:)回顾心得虽然应用已经能够运行起来了,但是如果你对Golang和Docker有一定的了解,希望你至少能想到2个问题。为什么gin-blog-docker占用这么多空间?(可以使用dockerps-as|grepgin-blog-docker查看)这样直接使用mysql容器,数据存放在哪里?创建一个超小的Golang镜像Q:第一个问题,为什么镜像这么大?A:FROMgolang:latest拉取golang官方镜像,里面包含了Golang的编译和运行环境,加上一堆GCC和构建工具,比较齐全。这是有问题的。我们可以现场编译,不用在Golang容器中使用。少了这些,我们只需要一个可以运行可执行文件的环境就可以构建一个Scratch镜像Scratch镜像简单、紧凑,基本上是一个空镜像1.修改DockerfileFROMscratchWORKDIR$GOPATH/src/github.com/EDDYCJY/go-gin-exampleCOPY。$GOPATH/src/github.com/EDDYCJY/go-gin-exampleEXPOSE8000CMD["./go-gin-example"]2.编译可执行文件CGO_ENABLED=0GOOS=linuxgobuild-a-installsuffixcgo-ogo-杜松子酒示例。编译生成的可执行文件会依赖一些库,动态链接这里因为使用了scratch镜像,是一个空镜像,所以我们需要静态链接生成的可执行文件所依赖的库。3.构建镜像$dockerbuild-tgin-blog-docker-scratch。将构建上下文发送到Docker守护进程133.1MB第1/5步:从头开始--->第2/5步:WORKDIR$GOPATH/src/github。com/EDDYCJY/go-gin-example--->使用缓存--->ee07e166a638Step3/5:复制。$GOPATH/src/github.com/EDDYCJY/go-gin-example--->1489a0693d51Removingintermediatecontainere3e9efc0fe4dStep4/5:EXPOSE8000--->Runninginb5630de5544a--->6993e9f8c944Removingintermediatecontainerb5630de5544aStep5/5步...在,你不需要关心任何其他事情。这里有几种解决方案,依赖文件的统一管理,挂载go-bindata...所以这里如果解决了文件依赖的问题,就不需要把目录给COPY了。4.运行$dockerrun--linkmysql:mysql-p8000:8000gin-blog-docker-scratch[GIN-debug][警告]在“调试”模式下运行。切换到“发布”模式在生产中。-使用环境:exportGIN_MODE=release-使用代码:gin.SetMode(gin.ReleaseMode)[GIN-debug]GET/auth-->github.com/EDDYCJY/go-gin-example/routers/api。GetAuth(3handlers)...运行成功,程序正常接收请求。接下来查看占用大小,执行dockerps-as命令$dockerps-asCONTAINERIDIMAGECOMMAND...SIZE9ebdba5a8445gin-blog-docker-scratch"./go-gin-example"...0B(virtual132MB)427ee79e6857gin-blog-docker"./go-gin-example"...0B(virtual946MB)从结果上看,占用容器的大小以Scratch镜像为准,目标Mysql挂载数据卷。如果不做任何干预,每启动一个Mysql容器,数据库都是空的。另外容器删除后,数据会丢失(还有各种类异常),很糟糕!Datavolume数据卷是为了持久化数据而设计的,它的生命周期是独立于容器的,容器删除后Docker不会自动删除数据卷,也没有垃圾回收等机制来处理没有容器引用的数据卷.如果在删除容器的同时需要移除数据卷。删除容器时可以使用dockerrm-v命令。数据卷是一个特殊的目录,可以被一个或多个容器使用。它绕过了UFS,可以提供很多有用的特性:数据卷可以在容器之间共享,并且Reuse对数据卷的修改会立即生效。数据量的更新不会影响镜像。默认情况下,数据卷将始终存在,即使容器被删除。注意:数据卷的使用类似于Linux下挂载目录或文件。指定挂载点目录下的文件会被隐藏,挂载的数据卷可以显示出来。如何挂载首先创建一个存放数据卷的目录;示例目录/data/docker-mysql,注意--name需要删除原名为mysql的容器dockerrm$dockerrun--namemysql-p3306:3306-eMYSQL_ROOT_PASSWORD=rootroot-v/data/docker-mysql:/var/lib/mysql-dmysql54611dbcd62eca33fb320f3f624c7941f15697d998f40b24ee535a1acf93ae72创建成功,查看目录/data/docker-mysql,下面有很多数据库文件供验证,目的是创建一些测试表和数据,然后删除当前容器,重新创建容器,数据库数据依然存在(当然数据卷指向要一致)。我已经完成了验证,你呢?参考本系列示例代码go-gin-example本系列目录连载1Golang介绍及环境安装连载2BuildBlogAPI的(一)连载3BuildBlogAPI的(2)连载4BuildBlogAPI的(3)JWT的使用身份验证连载6写一个简单的文件日志连载7Golang优雅重启HTTP服务连载8为它添加Swagger连载9部署Golang应用到Docker连载10自定义GORM回调实现图片上传和序列化13.优化你的应用结构和实现Redis缓存.连载14.导出导入Excel连载15.生成二维码合并海报连载16.在图片上绘制文字连载17.使用NginxGolang交叉编译部署Go应用请入门Makefile书籍Docker-从入门到实践