七叶笔记 » golang编程 » Go docker环境配置

Go docker环境配置

一.先安装git,用于后续代码拉取:

 yum -y install git  

二.安装docker:

1.更新yum, 安装依赖

 sudo yum update
sudo yum install -y yum-utils device-mapper-persistent-data lvm2  

2.将docker源添加到系统中

 sudo yum-config-manager --add-repo   

3. 安装docker

 sudo yum install docker-ce docker-ce-cli containerd.io  

4. 启动docker和添加开启自启动

 sudo systemctl start docker
sudo systemctl enable docker  

5.查看docker版本

 docker -v  

三、安装go环境

 wget wget 
tar -zxvf go1.16.1.linux-amd64.tar.gz
mv go/ /usr/local/  

添加环境变量 GOROOT 和将 GOBIN 添加到 PATH 中

 vi /etc/profile
export GOROOT=/usr/local/go
export PATH=$PATH:$GOROOT/bin  

配置完毕后,执行命令令其生效

 source /etc/profile  

在控制台输入 go version ,若输出版本号则 安装成功 ,如下:

 $ go version
go version go1.16.1 linux/amd64  

打开module和配置代理

 $go env -w GO111MODULE=on
$go env -w GOPROXY=
$go env -w GOPATH=/data/gowork  

四、git拉取项目代码

 cd /
mkdir -r /data/gowork/src
cd /data/gowork/src
git clone 
cd go-blog
go mod tidy  

五、将Golang应用部署到Docker

 vi Dockerfile

FROM golang:latest

ENV GOPROXY 
# 移动到工作目录
WORKDIR /data/gowork/src/go-blog
# 将代码复制到容器中
COPY . /data/gowork/src/go-blog
# 将我们的代码编译成二进制可执行文件
RUN go build .

EXPOSE 8000
ENTRYPOINT ["./go-blog"]  

注意 go-blog docker 容器里编译,并没有在宿主机现场编译

构建镜像

 #在go-blog目录下执行
docker build -t go-blog-docker .

#输出:
Sending build context to Docker daemon 96.39 MB
Step 1/6 : FROM golang:latest
 ---> d632bbfe5767
Step 2/6 : WORKDIR $GOPATH/src/github.com/EDDYCJY/go-gin-example
 ---> 56294f978c5d
Removing intermediate container e112997b995d
Step 3/6 : COPY . $GOPATH/src/github.com/EDDYCJY/go-gin-example
 ---> 3b60960120cf
Removing intermediate container 63e310b3f60c
Step 4/6 : RUN go build .
 ---> Running in 52648a431450
go: downloading github.com/gin-gonic/gin v1.3.0
go: downloading github.com/go-ini/ini v1.32.1-0.20180214101753-32e4be5f41bb
go: downloading github.com/swaggo/gin-swagger v1.0.1-0.20190110070702-0c6fcfd3c7f3
...
 ---> 7bfbeb301fea
Removing intermediate container 52648a431450
Step 5/6 : EXPOSE 8000
 ---> Running in 98f5b387d1bb
 ---> b65bd4076c65
Removing intermediate container 98f5b387d1bb
Step 6/6 : ENTRYPOINT ./go-gin-example
 ---> Running in c4f6cdeb667b
 ---> d8a109c7697c
Successfully built aab0b3fdee0a
Successfully tagged go-blog-docker:latest  

验证镜像:

 docker images
输出:
go-blog-docker latest aab0b3fdee0a About a minute ago 1.37GB
golang latest 73fa8a9cf041 15 hours ago 941MB  

创建并运行一个新容器

 执行命令 
docker run -p 8000:8000 go-blog-docker

输出:
2022/03/03 09:12:39 dial tcp 127.0.0.1:3306: connect: connection refused
[GIN-debug] GET    /swagger/*any             --> github.com/swaggo/gin-swagger.CustomWrapHandler.func1 (3 handlers)
[GIN-debug] GET    /auth                     --> go-blog/routers/api.GetAuth (3 handlers)
[GIN-debug] GET    /api/v1/tags              --> go-blog/routers/api/v1.GetTags (4 handlers)
[GIN-debug] POST   /api/v1/tags              --> go-blog/routers/api/v1.AddTag (4 handlers)
[GIN-debug] PUT    /api/v1/tags/:id          --> go-blog/routers/api/v1.EditTag (4 handlers)
[GIN-debug] DELETE /api/v1/tags/:id          --> go-blog/routers/api/v1.DeleteTag (4 handlers)
[GIN-debug] GET    /api/v1/articles          --> go-blog/routers/api/v1.GetArticles (4 handlers)
[GIN-debug] GET    /api/v1/articles/:id      --> go-blog/routers/api/v1.GetArticle (4 handlers)
[GIN-debug] POST   /api/v1/articles          --> go-blog/routers/api/v1.AddArticle (4 handlers)
[GIN-debug] PUT    /api/v1/articles/:id      --> go-blog/routers/api/v1.EditArticle (4 handlers)
[GIN-debug] DELETE /api/v1/articles/:id      --> go-blog/routers/api/v1.DeleteArticle (4 handlers)
  

仔细看看控制台的输出了一条错误 dial tcp 127.0.0.1:3306: connect: connection refused

我们研判一下,发现是 Mysql 的问题,接下来第二项我们将解决这个问题。

六、Mysql安装

拉取镜像

Docker 的公共仓库 Dockerhub 下载 MySQL 镜像(国内建议配个镜像)

 $ docker pull mysql  

创建并运行一个新容器

运行 Mysql 容器,并设置执行成功后返回容器 ID

 $ docker run --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root -d mysql:latest
输出:
8c86ac986da4922492934b6fe074254c9165b8ee3e184d29865921b0fef29e64  

进入 Mysql容器

 #进入mysql容器命令:
docker exec -it mysql bash
#连接mysql
mysql -uroot -p -h localhost

#退出容器命令
exit  

Mysql 挂载数据卷

倘若不做任何干涉,在每次启动一个 Mysql 容器时,数据库都是空的。另外容器删除之后,数据就丢失了(还有各类意外情况),非常糟糕!

数据卷

数据卷 是被设计用来持久化数据的,它的生命周期独立于容器,Docker 不会在容器被删除后自动删除 数据卷,并且也不存在垃圾回收这样的机制来处理没有任何容器引用的 数据卷。如果需要在删除容器的同时移除数据卷。可以在删除容器的时候使用 docker rm -v 这个命令

数据卷 是一个可供一个或多个容器使用的特殊目录,它绕过 UFS,可以提供很多有用的特性:

  • 数据卷 可以在容器之间共享和重用
  • 对 数据卷 的修改会立马生效
  • 对 数据卷 的更新,不会影响镜像
  • 数据卷 默认会一直存在,即使容器被删除

如何挂载

首先创建一个目录用于存放数据卷;示例目录 /data/docker-mysql ,注意 –name 原本名称为 mysql 的容器,需要将其删除 docker rm

 #删除之前的容器
docker stop mysql
docker rm mysql

#重新运行
docker run --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root -v /data/docker-mysql:/var/lib/mysql -d mysql:latest  

创建成功,检查目录 /data/docker-mysql ,下面多了不少数据库文件

远程连接:

MySQL错误号码 2058

 mysql> use mysql;
Database changed
mysql> select host,user,plugin,authentication_string from user where user = 'root';
+-----------+------+-----------------------+------------------------------------------------------------------------+
| host      | user | plugin                | authentication_string                                                  |
+-----------+------+-----------------------+------------------------------------------------------------------------+
| %         | root | caching_sha2_password | $A$005$ru3S) >y(Z3@il]wvVwxn/VoB7KXrDWmV9eQvw2NMFQrbYOKo.WGlhU1M3/ |
| localhost | root | mysql_native_password | *6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9                              |
+-----------+------+-----------------------+------------------------------------------------------------------------+
2 rows in set (0.00 sec)

#发现我们看一下host,这里的host表示的是可以远程连接,但是这个远程连接的密码是加密的方式的,我做的方法是两边切换一下,最后调整如下就可以登录了
UPDATE `user` SET `plugin`='mysql_native_password',authentication_string='*81F5E21E35407D884A6CD4A731AEBFB6AF209E1B' WHERE `host`="%" AND `user`="root" LIMIT 1;
flush privileges;  

验证

接下来交由你进行验证,目标是创建一些测试表和数据,然后删除当前容器,重新创建的容器,数据库数据也依然存在(当然了数据卷指向要一致)

七、需要将go容器与mysql容器关联起来

vim conf/app.ini

修改:

 HOST = mysql:3306  

重新构建镜像

删除之前go-blog镜像

删除原本的有问题的镜像, -f 是强制删除及其关联状态

若不执行 -f ,你需要执行 docker ps -a 查到所关联的容器,将其 rm 解除两者依赖关系

 docker rmi -f gin-blog-docker  

重复先前第五步骤,回到 go-blog 的项目根目录下 执行

 docker build -t go-blog-docker .  

创建并运行一个新容器

Q:我们需要将 Golang 容器和 Mysql 容器关联起来,那么我们需要怎么做呢?

A:增加命令 –link mysql:mysql Golang 容器与 Mysql 容器互联;通过 –link 可以在容器内直接使用其关联的容器别名进行访问 ,而不通过 IP,但是 –link 只能解决单机容器间的关联,在分布式多机的情况下,需要通过别的方式 容器方式互联进行连接( ambassador)

 分布式多机情况使用通过容器方式互联:
#启动ambassador1:
sudo docker run -d --link mysql:mysql --name ambassador1 -p 3306:3306 ambassador  
#启动ambassador2:
sudo docker run -d --name ambassador2 --expose 3306 -e MYSQL_PORT_3306_TCP=tcp://x.x.x.x:3306 ambassador  
#启动go-blog:
sudo docker run -i -t --rm --link ambassador2:mysql go-blog-docker  

运行

执行命令 docker run –link mysql:mysql -p 8000:8000 go-blog-docker

 $ docker run --link mysql:mysql -p 8000:8000 go-blog-docker
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:    export GIN_MODE=release
 - using code:    gin.SetMode(gin.ReleaseMode)
...
Actual pid is 1  

结果

检查启动输出、接口测试、数据库内数据,均正常;我们的 Golang 容器和 Mysql 容器成功关联运行,大功告成 🙂

补充另外一个问题:go-block-docker这个镜像占用太大了

创建超小的 Golang 镜像

Q:为什么这么镜像体积这么大?

A: FROM golang:latest 拉取的是官方 golang 镜像,包含 Golang 的编译和运行环境,外加一堆 GCC、build 工具,相当齐全

这是有问题的, 我们可以不在 Golang 容器中现场编译的 ,压根用不到那些东西,我们只需要一个能够运行可执行文件的环境即可

构建 Scratch 镜像

Scratch 镜像,简洁、小巧,基本是个空镜像

修改 Dockerfile

 FROM scratch

WORKDIR /data/gowork/src/go-blog
COPY . /data/gowork/src/go-blog

EXPOSE 8000
CMD ["./go-blog"]  

编译可执行文件

 CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o go-blog   

编译所生成的可执行文件会依赖一些库,并且是动态链接。在这里因为使用的是 scratch 镜像,它是空镜像,因此我们需要将生成的可执行文件静态链接所依赖的库

构建镜像

 $ docker build -t go-blog-docker-scratch .  

注意,假设你的 Golang 应用没有依赖任何的配置等文件,是可以直接把可执行文件给拷贝进去即可,其他都不必关心

这里可以有好几种解决方案

  • 依赖文件统一管理挂载
  • go-bindata 一下

因此这里如果 解决了文件依赖的问题 后,就不需要把目录给 COPY 进去了

运行

 $ docker run --link mysql:mysql -p 8000:8000 go-blog-docker-scratch  

思考:

docker已经发行很多年了为什么最近几年企业才大力使用,得益于k8s

早期cgroups也能实现容器,后来docker出来更方便了,但是生产上不利于维护与部署,之后有了docker-composer再后来k8s技术成熟,运维技术的积累,企业才敢开始大力推广使用。

相关文章