一.先安装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技术成熟,运维技术的积累,企业才敢开始大力推广使用。